From 29df6e6a3eaee61d9534dad9162516c1ca60cd8b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Feb 2013 12:21:38 -0800 Subject: [PATCH] send 256 samples per callback so mixer can reply with two channels --- interface/src/Audio.cpp | 58 +++++++++++++++------------------- interface/src/AudioData.cpp | 4 +-- interface/src/AudioData.h | 2 +- interface/src/main.cpp | 2 +- mixer/src/main.cpp | 48 +++++++++++++++++----------- shared/src/AudioRingBuffer.cpp | 25 +++++++++------ shared/src/AudioRingBuffer.h | 10 ++---- 7 files changed, 76 insertions(+), 73 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 74f6d51e7c..45d57873df 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -18,8 +18,16 @@ Oscilloscope * scope; -const short PACKET_LENGTH_BYTES = 1024; -const short PACKET_LENGTH_SAMPLES = PACKET_LENGTH_BYTES / sizeof(int16_t); +const int PACKET_LENGTH_BYTES = 1024; +const int PACKET_LENGTH_BYTES_PER_CHANNEL = PACKET_LENGTH_BYTES / 2; +const int PACKET_LENGTH_SAMPLES = PACKET_LENGTH_BYTES / sizeof(int16_t); +const int PACKET_LENGTH_SAMPLES_PER_CHANNEL = PACKET_LENGTH_SAMPLES / 2; + +const int BUFFER_LENGTH_BYTES = 512; +const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t); + +const int RING_BUFFER_FRAMES = 10; +const int RING_BUFFER_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES; const int PHASE_DELAY_AT_90 = 20; const float AMPLITUDE_RATIO_AT_90 = 0.5; @@ -97,7 +105,7 @@ int audioCallback (const void *inputBuffer, memcpy(dataPacket + 1 + (p * sizeof(float)), &data->sourcePosition[p], sizeof(float)); } - // copy the audio data to the last 1024 bytes of the data packet + // copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet memcpy(dataPacket + leadingBytes, inputLeft, BUFFER_LENGTH_BYTES); data->audioSocket->send((sockaddr *)&audioMixerSocket, dataPacket, BUFFER_LENGTH_BYTES + leadingBytes); @@ -126,21 +134,11 @@ int audioCallback (const void *inputBuffer, int16_t *outputLeft = ((int16_t **) outputBuffer)[0]; int16_t *outputRight = ((int16_t **) outputBuffer)[1]; - memset(outputLeft, 0, BUFFER_LENGTH_BYTES); - memset(outputRight, 0, BUFFER_LENGTH_BYTES); - - // Copy output data to oscilloscope - if (scope->getState()) { - for (int i = 0; i < BUFFER_LENGTH_SAMPLES; i++) { - scope->addData((float)outputRight[i]/32767.0, 2, i); - } - } + memset(outputLeft, 0, PACKET_LENGTH_BYTES_PER_CHANNEL); + memset(outputRight, 0, PACKET_LENGTH_BYTES_PER_CHANNEL); AudioRingBuffer *ringBuffer = data->ringBuffer; - int16_t *queueBuffer = data->samplesToQueue; - memset(queueBuffer, 0, BUFFER_LENGTH_BYTES); - // if we've been reset, and there isn't any new packets yet // just play some silence @@ -158,10 +156,10 @@ int audioCallback (const void *inputBuffer, ringBuffer->setStarted(true); // play whatever we have in the audio buffer - // no sample overlap, either a direct copy of the audio data, or a copy with some appended silence - memcpy(queueBuffer, ringBuffer->getNextOutput(), BUFFER_LENGTH_BYTES); + memcpy(outputLeft, ringBuffer->getNextOutput(), PACKET_LENGTH_BYTES_PER_CHANNEL); + memcpy(outputRight, ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES_PER_CHANNEL, PACKET_LENGTH_BYTES_PER_CHANNEL); - ringBuffer->setNextOutput(ringBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES); + ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES); if (ringBuffer->getNextOutput() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) { ringBuffer->setNextOutput(ringBuffer->getBuffer()); @@ -169,10 +167,6 @@ int audioCallback (const void *inputBuffer, } } - // copy whatever is in the queueBuffer to the outputLeft and outputRight buffers - memcpy(outputLeft, queueBuffer, BUFFER_LENGTH_BYTES); - memcpy(outputRight, queueBuffer, BUFFER_LENGTH_BYTES); - gettimeofday(&data->lastCallback, NULL); return paContinue; } @@ -190,7 +184,7 @@ void *receiveAudioViaUDP(void *args) { AudioRecThreadStruct *threadArgs = (AudioRecThreadStruct *) args; AudioData *sharedAudioData = threadArgs->sharedAudioData; - int16_t *receivedData = new int16_t[BUFFER_LENGTH_SAMPLES]; + int16_t *receivedData = new int16_t[PACKET_LENGTH_SAMPLES]; ssize_t receivedBytes; timeval previousReceiveTime, currentReceiveTime = {}; @@ -270,11 +264,11 @@ Audio::Audio(Oscilloscope * s) scope = s; - audioData = new AudioData(BUFFER_LENGTH_BYTES); + audioData = new AudioData(); // setup a UDPSocket audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT); - audioData->ringBuffer = new AudioRingBuffer(); + audioData->ringBuffer = new AudioRingBuffer(RING_BUFFER_SAMPLES, PACKET_LENGTH_SAMPLES); AudioRecThreadStruct threadArgs; threadArgs.sharedAudioData = audioData; @@ -285,8 +279,8 @@ Audio::Audio(Oscilloscope * s) 2, // input channels 2, // output channels (paInt16 | paNonInterleaved), // sample format - 22050, // sample rate (hz) - 512, // frames per buffer + SAMPLE_RATE, // sample rate (hz) + BUFFER_LENGTH_SAMPLES, // frames per buffer audioCallback, // callback function (void *) audioData); // user data to be passed to callback if (paError != paNoError) goto error; @@ -297,7 +291,7 @@ Audio::Audio(Oscilloscope * s) Pa_StartStream(stream); if (paError != paNoError) goto error; - + return; error: @@ -347,10 +341,10 @@ void Audio::render(int screenWidth, int screenHeight) timeval currentTime; gettimeofday(¤tTime, NULL); float timeLeftInCurrentBuffer = 0; - if (audioData->lastCallback.tv_usec > 0) timeLeftInCurrentBuffer = diffclock(&audioData->lastCallback, ¤tTime)/(1000.0*(float)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE) * frameWidth; + if (audioData->lastCallback.tv_usec > 0) timeLeftInCurrentBuffer = diffclock(&audioData->lastCallback, ¤tTime)/(1000.0*(float)PACKET_LENGTH_SAMPLES/(float)SAMPLE_RATE) * frameWidth; if (audioData->ringBuffer->getEndOfLastWrite() != NULL) - remainingBuffer = audioData->ringBuffer->diffLastWriteNextOutput() / BUFFER_LENGTH_SAMPLES * frameWidth; + remainingBuffer = audioData->ringBuffer->diffLastWriteNextOutput() / PACKET_LENGTH_SAMPLES * frameWidth; if (audioData->wasStarved == 0) glColor3f(0, 1, 0); else { @@ -378,12 +372,12 @@ void Audio::render(int screenWidth, int screenHeight) glEnd(); char out[20]; - sprintf(out, "%3.0f\n", audioData->averagedLatency/(float)frameWidth*(1000.0*(float)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE)); + sprintf(out, "%3.0f\n", audioData->averagedLatency/(float)frameWidth*(1000.0*(float)PACKET_LENGTH_SAMPLES/(float)SAMPLE_RATE)); drawtext(startX + audioData->averagedLatency - 10, topY-10, 0.08, 0, 1, 0, out, 1,1,0); // Show a Cyan bar with the most recently measured jitter stdev - int jitterPels = (float) audioData->measuredJitter/ ((1000.0*(float)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE)) * (float)frameWidth; + int jitterPels = (float) audioData->measuredJitter/ ((1000.0*(float)PACKET_LENGTH_SAMPLES/(float)SAMPLE_RATE)) * (float)frameWidth; glColor3f(0,1,1); glBegin(GL_QUADS); diff --git a/interface/src/AudioData.cpp b/interface/src/AudioData.cpp index afba708db4..ae1b9d6517 100644 --- a/interface/src/AudioData.cpp +++ b/interface/src/AudioData.cpp @@ -8,11 +8,10 @@ #include "AudioData.h" -AudioData::AudioData(int bufferLength) { +AudioData::AudioData() { mixerAddress = 0; mixerPort = 0; - samplesToQueue = new int16_t[bufferLength / sizeof(int16_t)]; averagedLatency = 0.0; lastCallback.tv_usec = 0; wasStarved = 0; @@ -22,6 +21,5 @@ AudioData::AudioData(int bufferLength) { AudioData::~AudioData() { - delete[] samplesToQueue; delete audioSocket; } \ No newline at end of file diff --git a/interface/src/AudioData.h b/interface/src/AudioData.h index 4efe39884a..d06d92811d 100644 --- a/interface/src/AudioData.h +++ b/interface/src/AudioData.h @@ -17,7 +17,7 @@ class AudioData { public: - AudioData(int bufferLength); + AudioData(); ~AudioData(); AudioRingBuffer *ringBuffer; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 1906b4e696..25cc888b06 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -80,7 +80,7 @@ int fullscreen = 0; in_addr_t localAddress; -Oscilloscope audioScope(512,200,true); +Oscilloscope audioScope(256,200,true); #define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you Head myHead; // The rendered head of oneself diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index af39a0a4a2..d976231d6b 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -19,11 +19,18 @@ const unsigned short MIXER_LISTEN_PORT = 55443; const float SAMPLE_RATE = 22050.0; -const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES/SAMPLE_RATE) * 1000000; const short JITTER_BUFFER_MSECS = 20; const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0); +const int BUFFER_LENGTH_BYTES = 1024; +const int BUFFER_LENGTH_SAMPLES_PER_CHANNEL = (BUFFER_LENGTH_BYTES / 2) / sizeof(int16_t); + +const short RING_BUFFER_FRAMES = 10; +const short RING_BUFFER_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + +const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000; + const long MAX_SAMPLE_VALUE = std::numeric_limits::max(); const long MIN_SAMPLE_VALUE = std::numeric_limits::min(); @@ -51,9 +58,10 @@ void *sendBuffer(void *args) if (agentBuffer != NULL && agentBuffer->getEndOfLastWrite() != NULL) { - if (!agentBuffer->isStarted() && agentBuffer->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) { + if (!agentBuffer->isStarted() + && agentBuffer->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES_PER_CHANNEL + JITTER_BUFFER_SAMPLES) { printf("Held back buffer %d.\n", i); - } else if (agentBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES) { + } else if (agentBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { printf("Buffer %d starved.\n", i); agentBuffer->setStarted(false); } else { @@ -68,24 +76,26 @@ void *sendBuffer(void *args) for (int i = 0; i < agentList.getAgents().size(); i++) { Agent *agent = &agentList.getAgents()[i]; - int16_t clientMix[BUFFER_LENGTH_SAMPLES] = {}; + int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {}; for (int j = 0; j < agentList.getAgents().size(); j++) { - if (i != j) { + if (i == j) { AudioRingBuffer *otherAgentBuffer = (AudioRingBuffer *)agentList.getAgents()[j].getLinkedData(); - float *agentPosition = ((AudioRingBuffer *)agent->getLinkedData())->getPosition(); - float *otherAgentPosition = otherAgentBuffer->getPosition(); +// float *agentPosition = ((AudioRingBuffer *)agent->getLinkedData())->getPosition(); +// float *otherAgentPosition = otherAgentBuffer->getPosition(); +// +// float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + +// powf(agentPosition[1] - otherAgentPosition[1], 2) + +// powf(agentPosition[2] - otherAgentPosition[2], 2)); +// +// float distanceCoeff = powf((logf(DISTANCE_RATIO * distanceToAgent) / logf(3)), 2); + float distanceCoeff = 1; - float distanceToAgent = sqrtf(powf(agentPosition[0] - otherAgentPosition[0], 2) + - powf(agentPosition[1] - otherAgentPosition[1], 2) + - powf(agentPosition[2] - otherAgentPosition[2], 2)); - - float distanceCoeff = powf((logf(DISTANCE_RATIO * distanceToAgent) / logf(3)), 2); - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) { + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { int16_t sample = (otherAgentBuffer->getNextOutput()[s] / distanceCoeff); clientMix[s] += sample; + clientMix[s + BUFFER_LENGTH_SAMPLES_PER_CHANNEL] += sample; } } } @@ -96,7 +106,7 @@ void *sendBuffer(void *args) for (int i = 0; i < agentList.getAgents().size(); i++) { AudioRingBuffer *agentBuffer = (AudioRingBuffer *)agentList.getAgents()[i].getLinkedData(); if (agentBuffer->wasAddedToMix()) { - agentBuffer->setNextOutput(agentBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES); + agentBuffer->setNextOutput(agentBuffer->getNextOutput() + BUFFER_LENGTH_SAMPLES_PER_CHANNEL); if (agentBuffer->getNextOutput() >= agentBuffer->getBuffer() + RING_BUFFER_SAMPLES) { agentBuffer->setNextOutput(agentBuffer->getBuffer()); @@ -127,8 +137,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; - packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); -// packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); +// packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); + packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); @@ -143,7 +153,7 @@ void *reportAliveToDS(void *args) { void attachNewBufferToAgent(Agent *newAgent) { if (newAgent->getLinkedData() == NULL) { - newAgent->setLinkedData(new AudioRingBuffer()); + newAgent->setLinkedData(new AudioRingBuffer(RING_BUFFER_SAMPLES, BUFFER_LENGTH_SAMPLES_PER_CHANNEL)); } } @@ -184,7 +194,7 @@ int main(int argc, const char * argv[]) while (true) { if(agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) { - if (receivedBytes >= BUFFER_LENGTH_BYTES) { + if (packetData[0] == 'I') { // add or update the existing interface agent agentList.addOrUpdateAgent(agentAddress, agentAddress, packetData[0]); agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes); diff --git a/shared/src/AudioRingBuffer.cpp b/shared/src/AudioRingBuffer.cpp index 15743b7d19..1abf6f234a 100644 --- a/shared/src/AudioRingBuffer.cpp +++ b/shared/src/AudioRingBuffer.cpp @@ -9,22 +9,27 @@ #include #include "AudioRingBuffer.h" -AudioRingBuffer::AudioRingBuffer() { +AudioRingBuffer::AudioRingBuffer(int ringSamples, int bufferSamples) { + ringBufferLengthSamples = ringSamples; + bufferLengthSamples = bufferSamples; + started = false; addedToMix = false; endOfLastWrite = NULL; - buffer = new int16_t[RING_BUFFER_SAMPLES]; + buffer = new int16_t[ringBufferLengthSamples]; nextOutput = buffer; }; AudioRingBuffer::AudioRingBuffer(const AudioRingBuffer &otherRingBuffer) { + ringBufferLengthSamples = otherRingBuffer.ringBufferLengthSamples; + bufferLengthSamples = otherRingBuffer.bufferLengthSamples; started = otherRingBuffer.started; addedToMix = otherRingBuffer.addedToMix; - buffer = new int16_t[RING_BUFFER_SAMPLES]; - memcpy(buffer, otherRingBuffer.buffer, sizeof(int16_t) * RING_BUFFER_SAMPLES); + buffer = new int16_t[ringBufferLengthSamples]; + memcpy(buffer, otherRingBuffer.buffer, sizeof(int16_t) * ringBufferLengthSamples); nextOutput = buffer + (otherRingBuffer.nextOutput - otherRingBuffer.buffer); endOfLastWrite = buffer + (otherRingBuffer.endOfLastWrite - otherRingBuffer.buffer); @@ -87,7 +92,7 @@ void AudioRingBuffer::setPosition(float *newPosition) { void AudioRingBuffer::parseData(void *data, int size) { unsigned char *audioDataStart = (unsigned char *) data; - if (size > BUFFER_LENGTH_BYTES) { + if (size > (bufferLengthSamples * sizeof(int16_t))) { for (int p = 0; p < 3; p ++) { memcpy(&position[p], audioDataStart + 1 + (sizeof(float) * p), sizeof(float)); @@ -98,19 +103,19 @@ void AudioRingBuffer::parseData(void *data, int size) { if (endOfLastWrite == NULL) { endOfLastWrite = buffer; - } else if (diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES) { + } else if (diffLastWriteNextOutput() > ringBufferLengthSamples - bufferLengthSamples) { endOfLastWrite = buffer; nextOutput = buffer; started = false; } - memcpy(endOfLastWrite, audioDataStart, BUFFER_LENGTH_BYTES); + memcpy(endOfLastWrite, audioDataStart, bufferLengthSamples * sizeof(int16_t)); - endOfLastWrite += BUFFER_LENGTH_SAMPLES; + endOfLastWrite += bufferLengthSamples; addedToMix = false; - if (endOfLastWrite >= buffer + RING_BUFFER_SAMPLES) { + if (endOfLastWrite >= buffer + ringBufferLengthSamples) { endOfLastWrite = buffer; } } @@ -123,7 +128,7 @@ short AudioRingBuffer::diffLastWriteNextOutput() short sampleDifference = endOfLastWrite - nextOutput; if (sampleDifference < 0) { - sampleDifference += RING_BUFFER_SAMPLES; + sampleDifference += ringBufferLengthSamples; } return sampleDifference; diff --git a/shared/src/AudioRingBuffer.h b/shared/src/AudioRingBuffer.h index f9c3f5e136..19d587d4f6 100644 --- a/shared/src/AudioRingBuffer.h +++ b/shared/src/AudioRingBuffer.h @@ -13,15 +13,9 @@ #include #include "AgentData.h" -const int BUFFER_LENGTH_BYTES = 1024; -const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t); - -const short RING_BUFFER_FRAMES = 10; -const short RING_BUFFER_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES; - class AudioRingBuffer : public AgentData { public: - AudioRingBuffer(); + AudioRingBuffer(int ringSamples, int bufferSamples); ~AudioRingBuffer(); AudioRingBuffer(const AudioRingBuffer &otherRingBuffer); @@ -42,6 +36,8 @@ class AudioRingBuffer : public AgentData { short diffLastWriteNextOutput(); private: + int ringBufferLengthSamples; + int bufferLengthSamples; float position[3]; int16_t *nextOutput; int16_t *endOfLastWrite;