audio test using two sources, no panning

This commit is contained in:
Stephen Birarda 2013-01-25 11:16:42 -08:00
parent d9caf566de
commit 706bc587de
6 changed files with 120 additions and 91 deletions

BIN
Resources/audio/grayson.raw Normal file

Binary file not shown.

View file

@ -10,7 +10,7 @@ int init_port (int baud);
int read_sensors(int first_measurement, float * avg_adc_channels, int * adc_channels, int * samples_averaged, int * LED_state);
#define NUM_CHANNELS 6
#define SERIAL_PORT_NAME "/dev/tty.usbmodemfa141"
#define SERIAL_PORT_NAME "/dev/tty.usbmodemfd131"
// Acceleration sensors, in screen/world coord system (X = left/right, Y = Up/Down, Z = fwd/back)
#define ACCEL_X 4

View file

@ -48,54 +48,61 @@ int audioCallback (const void *inputBuffer,
int16_t *outputLeft = ((int16_t **) outputBuffer)[0];
int16_t *outputRight = ((int16_t **) outputBuffer)[1];
float yawRatio = 0;
// float yawRatio = 0;
// int numSamplesDelay = abs(floor(yawRatio * PHASE_DELAY_AT_90));
//
// if (numSamplesDelay > PHASE_DELAY_AT_90) {
// numSamplesDelay = PHASE_DELAY_AT_90;
// }
//
// int16_t *leadingBuffer = yawRatio > 0 ? outputLeft : outputRight;
// int16_t *trailingBuffer = yawRatio > 0 ? outputRight : outputLeft;
//
int16_t *samplesToQueue = new int16_t[BUFFER_LENGTH_BYTES];
int numSamplesDelay = abs(floor(yawRatio * PHASE_DELAY_AT_90));
if (numSamplesDelay > PHASE_DELAY_AT_90) {
numSamplesDelay = PHASE_DELAY_AT_90;
for (int s = 0; s < AUDIO_SOURCES; s++) {
int wrapAroundSamples = (BUFFER_LENGTH_BYTES / sizeof(int16_t)) - (data->sources[s].lengthInSamples - data->sources[s].samplePointer);
if (wrapAroundSamples <= 0) {
memcpy(samplesToQueue, data->sources[s].audioData + data->sources[s].samplePointer, BUFFER_LENGTH_BYTES);
data->sources[s].samplePointer += (BUFFER_LENGTH_BYTES / sizeof(int16_t));
} else {
memcpy(samplesToQueue, data->sources[s].audioData + data->sources[s].samplePointer, (data->sources[s].lengthInSamples - data->sources[s].samplePointer) * sizeof(int16_t));
memcpy(samplesToQueue + (data->sources[s].lengthInSamples - data->sources[s].samplePointer), data->sources[s].audioData, wrapAroundSamples * sizeof(int16_t));
data->sources[s].samplePointer = wrapAroundSamples;
}
glm::vec3 headPos = data->linkedHead->getPos();
glm::vec3 sourcePos = data->sources[s].position;
float distance = sqrtf(powf(-headPos[0] - sourcePos[0], 2) + powf(-headPos[2] - sourcePos[2], 2));
float amplitudeRatio = powf(0.5, cbrtf(distance * 10));
std::cout << "The AR to source " << s << " is " << amplitudeRatio << "\n";
for (int i = 0; i < BUFFER_LENGTH_BYTES / sizeof(int16_t); i++) {
samplesToQueue[i] *= amplitudeRatio;
outputLeft[i] = s == 0 ? samplesToQueue[i] : outputLeft[i] + samplesToQueue[i];
}
if (wrapAroundSamples > 0) {
delete[] samplesToQueue;
}
}
int16_t *leadingBuffer = yawRatio > 0 ? outputLeft : outputRight;
int16_t *trailingBuffer = yawRatio > 0 ? outputRight : outputLeft;
int wrapAroundSamples = (BUFFER_LENGTH_BYTES / sizeof(int16_t)) - (data->fileSamples - data->samplePointer);
int16_t *samplesToQueue;
if (wrapAroundSamples < 0) {
samplesToQueue = data->fileBuffer + data->samplePointer;
data->samplePointer += (BUFFER_LENGTH_BYTES / sizeof(int16_t));
} else {
samplesToQueue = new int16_t[BUFFER_LENGTH_BYTES];
memcpy(samplesToQueue, data->fileBuffer + data->samplePointer, (data->fileSamples - data->samplePointer) * sizeof(int16_t));
memcpy(samplesToQueue, data->fileBuffer, wrapAroundSamples * sizeof(int16_t));
data->samplePointer = wrapAroundSamples;
for (int f = 0; f < BUFFER_LENGTH_BYTES; f++) {
outputLeft[f] = (int) floor(outputLeft[f] / AUDIO_SOURCES);
outputRight[f] = outputLeft[f];
}
// int offsetBytes = numSamplesDelay * sizeof(int16_t);
// memcpy(trailingBuffer, data->sources[1].delayBuffer + (PHASE_DELAY_AT_90 - numSamplesDelay), offsetBytes);
// memcpy(trailingBuffer + numSamplesDelay, samplesToQueue, BUFFER_LENGTH_BYTES - offsetBytes);
memcpy(leadingBuffer, samplesToQueue, BUFFER_LENGTH_BYTES);
int offsetBytes = numSamplesDelay * sizeof(int16_t);
memcpy(trailingBuffer, data->delayBuffer + (PHASE_DELAY_AT_90 - numSamplesDelay), offsetBytes);
memcpy(trailingBuffer + numSamplesDelay, samplesToQueue, BUFFER_LENGTH_BYTES - offsetBytes);
glm::vec3 headPos = data->linkedHead->getPos();
glm::vec3 sourcePos = data->sources[0].position;
float distance = sqrtf(powf(-headPos[0] - sourcePos[0], 2) + powf(-headPos[2] - sourcePos[2], 2));
float amplitudeRatio = powf(0.5, cbrtf(distance));
for (int i = 0; i < BUFFER_LENGTH_BYTES / sizeof(int16_t); i++) {
leadingBuffer[i] *= amplitudeRatio;
trailingBuffer[i] *= amplitudeRatio;
}
if (wrapAroundSamples > 0) {
delete[] samplesToQueue;
}
// copy PHASE_DELAY_AT_90 samples to delayBuffer in case we need it next go around
memcpy(data->delayBuffer, data->fileBuffer + data->samplePointer - PHASE_DELAY_AT_90, PHASE_DELAY_AT_90 * sizeof(int16_t));
// // copy PHASE_DELAY_AT_90 samples to delayBuffer in case we need it next go around
// memcpy(data->sources[1].delayBuffer, data->sources[1].audioData + data->sources[1].samplePointer - PHASE_DELAY_AT_90, PHASE_DELAY_AT_90 * sizeof(int16_t));
return paContinue;
}
@ -114,17 +121,13 @@ bool Audio::init()
}
bool Audio::init(Head* mainHead)
{
initialized = true;
{
data = new AudioData();
data->linkedHead = mainHead;
err = Pa_Initialize();
if (err != paNoError) goto error;
Audio::readFile();
err = Pa_OpenDefaultStream(&stream,
NULL, // input channels
2, // output channels
@ -133,10 +136,18 @@ bool Audio::init(Head* mainHead)
512, // frames per buffer
audioCallback, // callback function
(void *) data); // user data to be passed to callback
if (err != paNoError) goto error;
err = Pa_StartStream(stream);
data->sources[0].position = glm::vec3(3, 0, -1);
readFile("love.raw", &data->sources[0]);
data->sources[1].position = glm::vec3(-1, 0, 3);
readFile("grayson.raw", &data->sources[1]);
initialized = true;
// start the stream now that sources are good to go
Pa_StartStream(stream);
if (err != paNoError) goto error;
return paNoError;
@ -150,29 +161,37 @@ error:
void Audio::sourceSetup()
{
// render gl objects on screen for our three sources
// assume that glMatrixPush() has been called and we are at 0,0,0
glColor3f(1, 0, 0);
AudioSource source1 = AudioSource();
source1.position = glm::vec3(3, 0, -1);
data->sources[0] = source1;
glTranslatef(source1.position[0], source1.position[1], source1.position[2]);
glutSolidCube(0.5);
if (initialized) {
// render gl objects on screen for our sources
glPushMatrix();
glTranslatef(data->sources[0].position[0], data->sources[0].position[1], data->sources[0].position[2]);
glColor3f(1, 0, 0);
glutSolidCube(0.5);
glPopMatrix();
glPushMatrix();
glTranslatef(data->sources[1].position[0], data->sources[1].position[1], data->sources[1].position[2]);
glColor3f(0, 0, 1);
glutSolidCube(0.5);
glPopMatrix();
}
}
void Audio::readFile()
void Audio::readFile(const char *filename, struct AudioSource *source)
{
FILE *soundFile = fopen("love.raw", "r");
FILE *soundFile = fopen(filename, "r");
// get length of file:
std::fseek(soundFile, 0, SEEK_END);
data->fileSamples = std::ftell(soundFile) / sizeof(int16_t);
source->lengthInSamples = std::ftell(soundFile) / sizeof(int16_t);
std::rewind(soundFile);
data->fileBuffer = new int16_t[data->fileSamples];
std::fread(data->fileBuffer, sizeof(int16_t), data->fileSamples, soundFile);
source->audioData = new int16_t[source->lengthInSamples];
std::fread(source->audioData, sizeof(int16_t), source->lengthInSamples, soundFile);
std::fclose(soundFile);
}

View file

@ -15,11 +15,7 @@
#define BUFFER_LENGTH_BYTES 1024
#define PHASE_DELAY_AT_90 20
struct AudioSource {
glm::vec3 position;
int16_t *audioData;
};
#define AUDIO_SOURCES 2
class Audio {
public:
@ -32,33 +28,45 @@ public:
// terminates audio I/O
static bool terminate();
private:
static void readFile();
static bool initialized;
static struct AudioData {
int samplePointer;
int fileSamples;
// length in bytes of audio buffer
struct AudioSource {
glm::vec3 position;
int16_t *audioData;
int16_t *delayBuffer;
int16_t *fileBuffer;
int lengthInSamples;
int samplePointer;
Head* linkedHead;
AudioSource sources[3];
AudioSource() {
samplePointer = 0;
AudioData() {
samplePointer = 0;
// alloc memory for sample delay buffer
delayBuffer = new int16_t[PHASE_DELAY_AT_90];
memset(delayBuffer, 0, sizeof(int16_t) * PHASE_DELAY_AT_90);
};
~AudioSource() {
delete[] delayBuffer;
delete[] audioData;
}
};
static void readFile(const char *filename, struct AudioSource *source);
static bool initialized;
static struct AudioData {
Head* linkedHead;
AudioSource sources[AUDIO_SOURCES];
AudioData() {
sources[0] = AudioSource();
sources[1] = AudioSource();
sources[2] = AudioSource();
}
~AudioData() {
delete[] fileBuffer;
delete[] delayBuffer;
}
// ~AudioData() {
// delete sources[0];
// delete sources[1];
// delete sources[2];
// }
} *data;
// protects constructor so that public init method is used

View file

@ -602,9 +602,7 @@ void display(void)
// render audio sources and start them
if (audio_on) {
glPushMatrix();
Audio::sourceSetup();
glPopMatrix();
}
//glm::vec3 test(0.5, 0.5, 0.5);

View file

@ -51,6 +51,7 @@
532C803A16AF3B1900B1A969 /* libopencv_video.2.4.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 532C802516AF3B1900B1A969 /* libopencv_video.2.4.3.dylib */; };
532C803B16AF3B1900B1A969 /* libopencv_videostab.2.4.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 532C802616AF3B1900B1A969 /* libopencv_videostab.2.4.3.dylib */; };
532C803C16AF3B1900B1A969 /* libportaudio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 532C802816AF3B1900B1A969 /* libportaudio.a */; };
533B578716B2160C00FCABF1 /* grayson.raw in CopyFiles */ = {isa = PBXBuildFile; fileRef = 533B578516B2160600FCABF1 /* grayson.raw */; };
538BA8A316B1B71E000BF99C /* love.raw in CopyFiles */ = {isa = PBXBuildFile; fileRef = 538BA8A216B1B719000BF99C /* love.raw */; };
B6BDADE115F44A9D002A07DF /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADDE15F444DB002A07DF /* CoreServices.framework */; };
B6BDADE215F44AA5002A07DF /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADD815F444C1002A07DF /* CoreAudio.framework */; };
@ -69,6 +70,7 @@
files = (
532C7CCC16AF301E00B1A969 /* grayson-particle.png in CopyFiles */,
532C7CCD16AF301E00B1A969 /* int-texture256-v2.png in CopyFiles */,
533B578716B2160C00FCABF1 /* grayson.raw in CopyFiles */,
532C7CCE16AF301E00B1A969 /* int-texture256-v4.png in CopyFiles */,
538BA8A316B1B71E000BF99C /* love.raw in CopyFiles */,
532C7CCF16AF301E00B1A969 /* int-texture256-v5.png in CopyFiles */,
@ -502,6 +504,7 @@
532C802616AF3B1900B1A969 /* libopencv_videostab.2.4.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libopencv_videostab.2.4.3.dylib; sourceTree = "<group>"; };
532C802816AF3B1900B1A969 /* libportaudio.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libportaudio.a; sourceTree = "<group>"; };
532C802916AF3B1900B1A969 /* portaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = portaudio.h; sourceTree = "<group>"; };
533B578516B2160600FCABF1 /* grayson.raw */ = {isa = PBXFileReference; lastKnownFileType = file; path = grayson.raw; sourceTree = "<group>"; };
538BA8A216B1B719000BF99C /* love.raw */ = {isa = PBXFileReference; lastKnownFileType = file; path = love.raw; sourceTree = "<group>"; };
8DD76F6C0486A84900D96B5E /* interface */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = interface; sourceTree = BUILT_PRODUCTS_DIR; };
B6BDADD815F444C1002A07DF /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
@ -1283,6 +1286,7 @@
536E784516B0A1C900A2F6F3 /* audio */ = {
isa = PBXGroup;
children = (
533B578516B2160600FCABF1 /* grayson.raw */,
538BA8A216B1B719000BF99C /* love.raw */,
);
path = audio;