swap echo for forevermore sample, phase delay with gyro

This commit is contained in:
Stephen Birarda 2013-01-24 11:15:58 -08:00
parent 4d914128ea
commit 186f1217c3
4 changed files with 100 additions and 23 deletions

BIN
Resources/audio/love.raw Normal file

Binary file not shown.

View file

@ -6,6 +6,8 @@
// Copyright (c) 2013 Rosedale Lab. All rights reserved. // Copyright (c) 2013 Rosedale Lab. All rights reserved.
// //
#include <iostream>
#include <fstream>
#include "audio.h" #include "audio.h"
bool Audio::initialized; bool Audio::initialized;
@ -42,16 +44,51 @@ int audioCallback (const void *inputBuffer,
void *userData) void *userData)
{ {
Audio::AudioData *data = (Audio::AudioData *) userData; Audio::AudioData *data = (Audio::AudioData *) userData;
int16_t *input = (int16_t *) inputBuffer;
int16_t *output = (int16_t *) outputBuffer;
// check if we have input data int16_t *outputLeft = ((int16_t **) outputBuffer)[0];
if (input != NULL) { int16_t *outputRight = ((int16_t **) outputBuffer)[1];
memcpy(data->buffer, input, data->bufferLength * 2);
float yawRatio = data->linkedHead != NULL
? data->linkedHead->getYaw() / 90.0
: 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;
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;
} }
memcpy(output, data->buffer, data->bufferLength * 2); 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);
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));
return paContinue; return paContinue;
} }
@ -77,10 +114,12 @@ bool Audio::init(Head* mainHead)
err = Pa_Initialize(); err = Pa_Initialize();
if (err != paNoError) goto error; if (err != paNoError) goto error;
Audio::readFile();
err = Pa_OpenDefaultStream(&stream, err = Pa_OpenDefaultStream(&stream,
1, // input channels NULL, // input channels
1, // output channels 2, // output channels
paInt16, // sample format (paInt16 | paNonInterleaved), // sample format
22050, // sample rate (hz) 22050, // sample rate (hz)
512, // frames per buffer 512, // frames per buffer
audioCallback, // callback function audioCallback, // callback function
@ -100,6 +139,24 @@ error:
return false; return false;
} }
void Audio::readFile()
{
int length;
FILE *soundFile = fopen("love.raw", "r");
// get length of file:
std::fseek(soundFile, 0, SEEK_END);
data->fileSamples = 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);
std::fclose(soundFile);
}
/** /**
* Close the running audio stream, and deinitialize portaudio. * Close the running audio stream, and deinitialize portaudio.
* Should be called at the end of program execution. * Should be called at the end of program execution.

View file

@ -13,6 +13,9 @@
#include "portaudio.h" #include "portaudio.h"
#include "head.h" #include "head.h"
#define BUFFER_LENGTH_BYTES 1024
#define PHASE_DELAY_AT_90 20
class Audio { class Audio {
public: public:
// initializes audio I/O // initializes audio I/O
@ -22,27 +25,32 @@ public:
// terminates audio I/O // terminates audio I/O
static bool terminate(); static bool terminate();
private: private:
static void readFile();
static bool initialized; static bool initialized;
static struct AudioData { static struct AudioData {
// struct for left/right data in audio buffer int samplePointer;
struct BufferFrame { int fileSamples;
int16_t left, right;
} *buffer;
Head* linkedHead;
// length in bytes of audio buffer // length in bytes of audio buffer
const static unsigned int bufferLength = 1024;
int16_t *delayBuffer;
int16_t *fileBuffer;
Head* linkedHead;
AudioData() { AudioData() {
// alloc memory for buffer samplePointer = 0;
buffer = new BufferFrame[bufferLength];
memset(buffer, 0, sizeof(int16_t) * bufferLength * 2); // alloc memory for sample delay buffer
delayBuffer = new int16_t[PHASE_DELAY_AT_90];
memset(delayBuffer, 0, sizeof(int16_t) * PHASE_DELAY_AT_90);
} }
~AudioData() { ~AudioData() {
delete[] buffer; delete[] fileBuffer;
delete[] delayBuffer;
} }
} *data; } *data;

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 */; }; 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 */; }; 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 */; }; 532C803C16AF3B1900B1A969 /* libportaudio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 532C802816AF3B1900B1A969 /* libportaudio.a */; };
538BA8A316B1B71E000BF99C /* love.raw in CopyFiles */ = {isa = PBXBuildFile; fileRef = 538BA8A216B1B719000BF99C /* love.raw */; };
B6BDADE115F44A9D002A07DF /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADDE15F444DB002A07DF /* CoreServices.framework */; }; B6BDADE115F44A9D002A07DF /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADDE15F444DB002A07DF /* CoreServices.framework */; };
B6BDADE215F44AA5002A07DF /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADD815F444C1002A07DF /* CoreAudio.framework */; }; B6BDADE215F44AA5002A07DF /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADD815F444C1002A07DF /* CoreAudio.framework */; };
B6BDADE315F44AB0002A07DF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADDA15F444C9002A07DF /* AudioToolbox.framework */; }; B6BDADE315F44AB0002A07DF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BDADDA15F444C9002A07DF /* AudioToolbox.framework */; };
@ -69,6 +70,7 @@
532C7CCC16AF301E00B1A969 /* grayson-particle.png in CopyFiles */, 532C7CCC16AF301E00B1A969 /* grayson-particle.png in CopyFiles */,
532C7CCD16AF301E00B1A969 /* int-texture256-v2.png in CopyFiles */, 532C7CCD16AF301E00B1A969 /* int-texture256-v2.png in CopyFiles */,
532C7CCE16AF301E00B1A969 /* int-texture256-v4.png in CopyFiles */, 532C7CCE16AF301E00B1A969 /* int-texture256-v4.png in CopyFiles */,
538BA8A316B1B71E000BF99C /* love.raw in CopyFiles */,
532C7CCF16AF301E00B1A969 /* int-texture256-v5.png in CopyFiles */, 532C7CCF16AF301E00B1A969 /* int-texture256-v5.png in CopyFiles */,
532C7CD016AF301E00B1A969 /* philip-image.png in CopyFiles */, 532C7CD016AF301E00B1A969 /* philip-image.png in CopyFiles */,
532C7CD116AF301E00B1A969 /* pngtest8rgba.png in CopyFiles */, 532C7CD116AF301E00B1A969 /* pngtest8rgba.png in CopyFiles */,
@ -500,6 +502,7 @@
532C802616AF3B1900B1A969 /* libopencv_videostab.2.4.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libopencv_videostab.2.4.3.dylib; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 532C802916AF3B1900B1A969 /* portaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = portaudio.h; 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; }; 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; }; B6BDADD815F444C1002A07DF /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
B6BDADDA15F444C9002A07DF /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; B6BDADDA15F444C9002A07DF /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
@ -584,6 +587,8 @@
children = ( children = (
5325C22916AF4DBE0051A40B /* agent.cpp */, 5325C22916AF4DBE0051A40B /* agent.cpp */,
5325C22A16AF4DBE0051A40B /* agent.h */, 5325C22A16AF4DBE0051A40B /* agent.h */,
5325C26216AF4E2C0051A40B /* audio.cpp */,
5325C26316AF4E2C0051A40B /* audio.h */,
5325C22D16AF4DBE0051A40B /* cloud.cpp */, 5325C22D16AF4DBE0051A40B /* cloud.cpp */,
5325C22E16AF4DBE0051A40B /* cloud.h */, 5325C22E16AF4DBE0051A40B /* cloud.h */,
5325C22F16AF4DBE0051A40B /* cube.cpp */, 5325C22F16AF4DBE0051A40B /* cube.cpp */,
@ -617,8 +622,6 @@
5325C24D16AF4DBE0051A40B /* util.cpp */, 5325C24D16AF4DBE0051A40B /* util.cpp */,
5325C24E16AF4DBE0051A40B /* util.h */, 5325C24E16AF4DBE0051A40B /* util.h */,
5325C24F16AF4DBE0051A40B /* world.h */, 5325C24F16AF4DBE0051A40B /* world.h */,
5325C26216AF4E2C0051A40B /* audio.cpp */,
5325C26316AF4E2C0051A40B /* audio.h */,
); );
path = Source; path = Source;
sourceTree = "<group>"; sourceTree = "<group>";
@ -642,6 +645,7 @@
532C7AC116AF298D00B1A969 /* Resources */ = { 532C7AC116AF298D00B1A969 /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
536E784516B0A1C900A2F6F3 /* audio */,
532C7AC216AF298D00B1A969 /* images */, 532C7AC216AF298D00B1A969 /* images */,
); );
path = Resources; path = Resources;
@ -1276,6 +1280,14 @@
path = PortAudio; path = PortAudio;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
536E784516B0A1C900A2F6F3 /* audio */ = {
isa = PBXGroup;
children = (
538BA8A216B1B719000BF99C /* love.raw */,
);
path = audio;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */