diff --git a/Resources/audio/grayson.raw b/Resources/audio/grayson.raw new file mode 100644 index 0000000000..a1702317fa Binary files /dev/null and b/Resources/audio/grayson.raw differ diff --git a/Source/SerialInterface.h b/Source/SerialInterface.h index e4a165af87..331143e2f2 100644 --- a/Source/SerialInterface.h +++ b/Source/SerialInterface.h @@ -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 diff --git a/Source/audio.cpp b/Source/audio.cpp index a00b149284..b362b176f8 100644 --- a/Source/audio.cpp +++ b/Source/audio.cpp @@ -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); } diff --git a/Source/audio.h b/Source/audio.h index a97e7ff970..894674ce03 100644 --- a/Source/audio.h +++ b/Source/audio.h @@ -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 diff --git a/Source/main.cpp b/Source/main.cpp index 31c954e3e3..f23ca75915 100644 --- a/Source/main.cpp +++ b/Source/main.cpp @@ -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); diff --git a/interface.xcodeproj/project.pbxproj b/interface.xcodeproj/project.pbxproj index eec36c5839..ebc198df7c 100644 --- a/interface.xcodeproj/project.pbxproj +++ b/interface.xcodeproj/project.pbxproj @@ -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 = ""; }; 532C802816AF3B1900B1A969 /* libportaudio.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libportaudio.a; sourceTree = ""; }; 532C802916AF3B1900B1A969 /* portaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = portaudio.h; sourceTree = ""; }; + 533B578516B2160600FCABF1 /* grayson.raw */ = {isa = PBXFileReference; lastKnownFileType = file; path = grayson.raw; sourceTree = ""; }; 538BA8A216B1B719000BF99C /* love.raw */ = {isa = PBXFileReference; lastKnownFileType = file; path = love.raw; sourceTree = ""; }; 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;