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<int16_t> before limiting.
This will allow them to remain as float until
limiting (in the device callback) - once the new
stream is implemented.
This commit is contained in:
Zach Pomerantz 2017-01-19 15:17:07 -05:00
parent c5415f9624
commit 4f7f3c2a60
2 changed files with 35 additions and 32 deletions

View file

@ -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);
}
}
}

View file

@ -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;