From 4f7f3c2a609a897db8bc64f1cf1ffcc3cd36196c Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 19 Jan 2017 15:17:07 -0500 Subject: [PATCH] mv localInjectorsBuffer to float-based localInjectorsStream The localInjectorsBuffer is based on AudioRingBuffer, which only accounts for int16_t. Local injectors are mixed, and so they can exceed std::numeric_limits before limiting. This will allow them to remain as float until limiting (in the device callback) - once the new stream is implemented. --- libraries/audio-client/src/AudioClient.cpp | 46 +++++++++------------- libraries/audio-client/src/AudioClient.h | 21 +++++++--- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index eadbe08b20..491c4e341b 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -132,7 +132,7 @@ AudioClient::AudioClient() : _loopbackAudioOutput(NULL), _loopbackOutputDevice(NULL), _inputRingBuffer(0), - _localInjectorsBuffer(0), + _localInjectorsStream(0), _receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES), _isStereoInput(false), _outputStarveDetectionStartTimeMsec(0), @@ -154,7 +154,7 @@ AudioClient::AudioClient() : _localAudioThread(this), _audioLimiter(AudioConstants::SAMPLE_RATE, OUTPUT_CHANNEL_COUNT), _outgoingAvatarAudioSequenceNumber(0), - _audioOutputIODevice(_localInjectorsBuffer, _receivedAudioStream, this), + _audioOutputIODevice(_localInjectorsStream, _receivedAudioStream, this), _stats(&_receivedAudioStream), _inputGate(), _positionGetter(DEFAULT_POSITION_GETTER), @@ -1072,7 +1072,7 @@ void AudioClient::prepareLocalAudioInjectors() { return; } - int bufferCapacity = _localInjectorsBuffer.getSampleCapacity(); + int bufferCapacity = _localInjectorsStream.getSampleCapacity(); if (_localToOutputResampler) { // avoid overwriting the buffer bufferCapacity -= @@ -1086,7 +1086,7 @@ void AudioClient::prepareLocalAudioInjectors() { // lock for every write to avoid locking out the device callback Lock lock(_localAudioMutex); - samplesNeeded = bufferCapacity - _localInjectorsBuffer.samplesAvailable(); + samplesNeeded = bufferCapacity - _localInjectorsStream.samplesAvailable(); if (samplesNeeded <= 0) { break; } @@ -1101,22 +1101,20 @@ void AudioClient::prepareLocalAudioInjectors() { _localReverb.render(_localMixBuffer, _localMixBuffer, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); } - convertToScratch(_localScratchBuffer, _localMixBuffer, AudioConstants::NETWORK_FRAME_SAMPLES_STEREO); - int samples; if (_localToOutputResampler) { // resample to output sample rate - int frames = _localToOutputResampler->render(_localScratchBuffer, _localOutputScratchBuffer, + int frames = _localToOutputResampler->render(_localMixBuffer, _localOutputMixBuffer, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); // write to local injectors' ring buffer samples = frames * AudioConstants::STEREO; - _localInjectorsBuffer.writeSamples(_localOutputScratchBuffer, samples); + _localInjectorsStream.writeSamples(_localOutputMixBuffer, samples); } else { // write to local injectors' ring buffer samples = AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; - _localInjectorsBuffer.writeSamples(_localScratchBuffer, + _localInjectorsStream.writeSamples(_localMixBuffer, AudioConstants::NETWORK_FRAME_SAMPLES_STEREO); } @@ -1440,8 +1438,8 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice delete[] _outputScratchBuffer; _outputScratchBuffer = NULL; - delete[] _localOutputScratchBuffer; - _localOutputScratchBuffer = NULL; + delete[] _localOutputMixBuffer; + _localOutputMixBuffer = NULL; } if (_networkToOutputResampler) { @@ -1501,8 +1499,8 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice _outputPeriod = periodSampleSize * 2; _outputMixBuffer = new float[_outputPeriod]; _outputScratchBuffer = new int16_t[_outputPeriod]; - _localOutputScratchBuffer = new int16_t[_outputPeriod]; - _localInjectorsBuffer.resizeForFrameSize(_outputPeriod * 2); + _localOutputMixBuffer = new float[_outputPeriod]; + _localInjectorsStream.resizeForFrameSize(_outputPeriod * 2); qCDebug(audioclient) << "Output Buffer capacity in frames: " << _audioOutput->bufferSize() / AudioConstants::SAMPLE_SIZE / (float)deviceFrameSize << "requested bytes:" << requestedSize << "actual bytes:" << _audioOutput->bufferSize() << @@ -1630,22 +1628,16 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { samplesRequested = networkSamplesPopped; } - int injectorSamplesPopped; + int injectorSamplesPopped = 0; { Lock lock(_audio->_localAudioMutex); - if ((injectorSamplesPopped = _localInjectorsBuffer.readSamples(scratchBuffer, samplesRequested)) > 0) { - qCDebug(audiostream, "Read %d samples from injectors (%d available, %d requested)", injectorSamplesPopped, _localInjectorsBuffer.samplesAvailable(), samplesRequested); - - if (_audio->_shouldEchoToServer) { - // omit local audio, it should be echoed - injectorSamplesPopped = 0; - } else if (networkSamplesPopped == 0) { - convertToMix(mixBuffer, scratchBuffer, injectorSamplesPopped); - } else { - // add to mix buffer (float) - for (int i = 0; i < injectorSamplesPopped; i++) { - mixBuffer[i] += (float)scratchBuffer[i] * (1 / 32768.0f); - } + if (_audio->_shouldEchoToServer) { + // omit local audio, it should be echoed + _localInjectorsStream.skipSamples(samplesRequested); + } else { + bool append = networkSamplesPopped > 0; + if ((injectorSamplesPopped = _localInjectorsStream.readSamples(mixBuffer, samplesRequested, append)) > 0) { + qCDebug(audiostream, "Read %d samples from injectors (%d available, %d requested)", injectorSamplesPopped, _localInjectorsStream.samplesAvailable(), samplesRequested); } } } diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 78fd97abb2..8befd86f26 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -69,6 +69,17 @@ class QIODevice; class Transform; class NLPacket; +class LocalInjectorsStream { +public: + LocalInjectorsStream(int numFrameSamples); + int getSampleCapacity() { return 0; }; + int samplesAvailable() { return 0; } + int writeSamples(const float*, int numSamples) { return 0; } + void resizeForFrameSize(int numFrameSamples) {} + int skipSamples(int numSamples) { return 0; } + int readSamples(float* mixBuffer, int numSamples, bool append) { return 0; } +}; + class AudioInjectorsThread : public QThread { Q_OBJECT @@ -97,9 +108,9 @@ public: class AudioOutputIODevice : public QIODevice { public: - AudioOutputIODevice(AudioRingBuffer& localInjectorsBuffer, MixedProcessedAudioStream& receivedAudioStream, + AudioOutputIODevice(LocalInjectorsStream& localInjectorsStream, MixedProcessedAudioStream& receivedAudioStream, AudioClient* audio) : - _localInjectorsBuffer(localInjectorsBuffer), _receivedAudioStream(receivedAudioStream), + _localInjectorsStream(localInjectorsStream), _receivedAudioStream(receivedAudioStream), _audio(audio), _unfulfilledReads(0) {} void start() { open(QIODevice::ReadOnly | QIODevice::Unbuffered); } @@ -108,7 +119,7 @@ public: qint64 writeData(const char * data, qint64 maxSize) override { return 0; } int getRecentUnfulfilledReads() { int unfulfilledReads = _unfulfilledReads; _unfulfilledReads = 0; return unfulfilledReads; } private: - AudioRingBuffer& _localInjectorsBuffer; + LocalInjectorsStream& _localInjectorsStream; MixedProcessedAudioStream& _receivedAudioStream; AudioClient* _audio; int _unfulfilledReads; @@ -277,7 +288,7 @@ private: QAudioOutput* _loopbackAudioOutput; QIODevice* _loopbackOutputDevice; AudioRingBuffer _inputRingBuffer; - AudioRingBuffer _localInjectorsBuffer; + LocalInjectorsStream _localInjectorsStream; MixedProcessedAudioStream _receivedAudioStream; bool _isStereoInput; @@ -322,7 +333,7 @@ private: // for local audio (used by audio injectors thread) float _localMixBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO]; int16_t _localScratchBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_AMBISONIC]; - int16_t* _localOutputScratchBuffer { NULL }; + float* _localOutputMixBuffer { NULL }; AudioInjectorsThread _localAudioThread; Mutex _localAudioMutex;