From a7deca0ced54e02016c1429d431fa0c25b87ef05 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 4 Mar 2013 10:37:48 -0800 Subject: [PATCH] add a broken flanger --- interface/src/Audio.cpp | 56 +++++++++++++++++++++++++++++++++++++++-- interface/src/Head.cpp | 6 ++--- interface/src/Head.h | 4 ++- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 4a5d4907ed..d376d6f164 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -36,6 +36,10 @@ const int SAMPLE_RATE = 22050; const float JITTER_BUFFER_LENGTH_MSECS = 30.0; const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_LENGTH_MSECS * (SAMPLE_RATE / 1000.0); +const int FLANGE_EFFECT_THRESHOLD = 200; +const int FLANGE_DELAY_MAX_SAMPLES = 100; +const float FLANGE_SAMPLE_WEIGHT = 0.70; + const short NUM_AUDIO_SOURCES = 2; const short ECHO_SERVER_TEST = 1; @@ -49,6 +53,8 @@ int starve_counter = 0; StDev stdev; bool stopAudioReceiveThread = false; +int samplesLeftForFlange = 0; + #define LOG_SAMPLE_DELAY 1 std::ofstream logFile; @@ -171,9 +177,55 @@ int audioCallback (const void *inputBuffer, ringBuffer->setStarted(true); // play whatever we have in the audio buffer - memcpy(outputLeft, ringBuffer->getNextOutput(), PACKET_LENGTH_BYTES_PER_CHANNEL); - memcpy(outputRight, ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES_PER_CHANNEL, PACKET_LENGTH_BYTES_PER_CHANNEL); + // if we haven't fired off the flange effect, check if we should + if (!samplesLeftForFlange && fabsf(data->linkedHead->getLastMeasuredYaw()) > FLANGE_EFFECT_THRESHOLD) { + // we should flange for one second + samplesLeftForFlange = SAMPLE_RATE; + } + for (int s = 0; s < PACKET_LENGTH_SAMPLES_PER_CHANNEL; s++) { + + int leftSample = ringBuffer->getNextOutput()[s]; + int rightSample = ringBuffer->getNextOutput()[s + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; + + if (samplesLeftForFlange > 0) { + int sampleFlangeDelay = (samplesLeftForFlange / (float) SAMPLE_RATE) * FLANGE_DELAY_MAX_SAMPLES; + + if (sampleFlangeDelay != FLANGE_DELAY_MAX_SAMPLES || s >= FLANGE_DELAY_MAX_SAMPLES) { + // we have a delayed sample to add to this sample + + int16_t *flangeFrame = ringBuffer->getNextOutput(); + int flangeIndex; + + if (s - sampleFlangeDelay < 0) { + // we need to grab the flange sample from earlier in the buffer + flangeFrame = ringBuffer->getNextOutput() - BUFFER_LENGTH_SAMPLES; + + if (flangeFrame < ringBuffer->getBuffer()) { + // we have wraparound + + flangeFrame = ringBuffer->getBuffer() + RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES; + } + + flangeIndex = PACKET_LENGTH_SAMPLES_PER_CHANNEL + (s - sampleFlangeDelay); + } else { + flangeIndex = s - sampleFlangeDelay; + } + + int16_t leftFlangeSample = flangeFrame[flangeIndex]; + int16_t rightFlangeSample = flangeFrame[flangeIndex + PACKET_LENGTH_SAMPLES_PER_CHANNEL]; + + leftSample = (1 - FLANGE_SAMPLE_WEIGHT) * leftSample + (FLANGE_SAMPLE_WEIGHT * leftFlangeSample); + rightSample = (1 - FLANGE_SAMPLE_WEIGHT) * rightSample + (FLANGE_SAMPLE_WEIGHT * rightFlangeSample); + + samplesLeftForFlange--; + } + } + + outputLeft[s] = leftSample; + outputRight[s] = rightSample; + } + ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES); if (ringBuffer->getNextOutput() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) { diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 1e5b3c4203..d3caf98f95 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -87,7 +87,7 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea const float PITCH_ACCEL_COUPLING = 0.5; const float ROLL_ACCEL_COUPLING = -1.0; float measured_pitch_rate = serialInterface->getRelativeValue(PITCH_RATE); - float measured_yaw_rate = serialInterface->getRelativeValue(YAW_RATE); + yawRate = serialInterface->getRelativeValue(YAW_RATE); float measured_lateral_accel = serialInterface->getRelativeValue(ACCEL_X) - ROLL_ACCEL_COUPLING*serialInterface->getRelativeValue(ROLL_RATE); float measured_fwd_accel = serialInterface->getRelativeValue(ACCEL_Z) - @@ -115,11 +115,11 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea if (head_mirror) { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(-measured_yaw_rate * HEAD_ROTATION_SCALE * frametime); + addYaw(-yawRate * HEAD_ROTATION_SCALE * frametime); addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } else { if ((Yaw < MAX_YAW) && (Yaw > MIN_YAW)) - addYaw(measured_yaw_rate * -HEAD_ROTATION_SCALE * frametime); + addYaw(yawRate * -HEAD_ROTATION_SCALE * frametime); addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE); } } diff --git a/interface/src/Head.h b/interface/src/Head.h index a6aaec725c..b1e71fd9f5 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -58,6 +58,8 @@ class Head : public AgentData { float getAverageLoudness() {return averageLoudness;}; void setAverageLoudness(float al) {averageLoudness = al;}; void setLoudness(float l) {loudness = l;}; + float getLastMeasuredYaw() {return yawRate;}; + void SetNewHeadTarget(float, float); glm::vec3 getPos() { return position; }; @@ -71,7 +73,7 @@ class Head : public AgentData { float Yaw; float Roll; float PitchRate; - float YawRate; + float yawRate; float RollRate; float EyeballPitch[2]; float EyeballYaw[2];