send 256 samples per callback so mixer can reply with two channels

This commit is contained in:
Stephen Birarda 2013-02-28 12:21:38 -08:00
parent 5978b50912
commit 29df6e6a3e
7 changed files with 76 additions and 73 deletions

View file

@ -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(&currentTime, NULL);
float timeLeftInCurrentBuffer = 0;
if (audioData->lastCallback.tv_usec > 0) timeLeftInCurrentBuffer = diffclock(&audioData->lastCallback, &currentTime)/(1000.0*(float)BUFFER_LENGTH_SAMPLES/(float)SAMPLE_RATE) * frameWidth;
if (audioData->lastCallback.tv_usec > 0) timeLeftInCurrentBuffer = diffclock(&audioData->lastCallback, &currentTime)/(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);

View file

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

View file

@ -17,7 +17,7 @@
class AudioData {
public:
AudioData(int bufferLength);
AudioData();
~AudioData();
AudioRingBuffer *ringBuffer;

View file

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

View file

@ -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<int16_t>::max();
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::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);

View file

@ -9,22 +9,27 @@
#include <cstring>
#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;

View file

@ -13,15 +13,9 @@
#include <stdint.h>
#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;