diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 374976c691..62eaacc7c8 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -468,7 +468,8 @@ void Audio::handleAudioInput() { } // Add tone injection if enabled - const float TONE_FREQ = 220.f / SAMPLE_RATE * TWO_PI; + //const float TONE_FREQ = 220.f / SAMPLE_RATE * TWO_PI; + const float TONE_FREQ = 440.f / SAMPLE_RATE * TWO_PI; const float QUARTER_VOLUME = 8192.f; if (_toneInjectionEnabled) { loudness = 0.f; @@ -760,11 +761,20 @@ void Audio::processReceivedAudio(unsigned int sampleTime, AudioRingBuffer& ringB // copy the samples we'll resample from the ring buffer - this also // pushes the read pointer of the ring buffer forwards ringBuffer.readSamples(ringBufferSamples, numNetworkOutputSamples); + + } // add the next numNetworkOutputSamples from each QByteArray // in our _localInjectionByteArrays QVector to the localInjectedSamples + + if (Menu::getInstance()->isOptionChecked(MenuOption::LowPassFilter)) { + int channels = _desiredOutputFormat.channelCount(); + int filterSamples = numNetworkOutputSamples / channels; + lowPassFilter(ringBufferSamples, filterSamples, channels); + } + // copy the packet from the RB to the output linearResampling(ringBufferSamples, (int16_t*) outputBuffer.data(), @@ -894,6 +904,37 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { } } + +// simple 3 pole low pass filter +void Audio::lowPassFilter(int16_t* inputBuffer, int samples, int channels) { + + //qDebug() << "lowPassFilter() samples=" << samples << " channels=" << channels; + //const int POLE_COUNT = 3; + + for (int c = 0; c < channels; c++) { + const float C1 = 0.0f; // 0.25f; + const float C2 = 1.0f; // 0.5f; + const float C3 = 0.0f; // 0.25f; + int16_t S1,S2,S3; + S1 = inputBuffer[c]; // start with the Nth sample, based on the current channel, this is the fist sample for the channel + for (int i = 0; i < samples; i++) { + int sampleAt = (i * channels) + c; + int nextSampleAt = sampleAt + channels; + S2 = inputBuffer[sampleAt]; + if (i == samples - 1) { + S3 = inputBuffer[sampleAt]; + } else { + S3 = inputBuffer[nextSampleAt]; + } + // save our S1 for next time before we mod this + S1 = inputBuffer[sampleAt]; + inputBuffer[sampleAt] = (C1 * S1) + (C2 * S2) + (C3 * S3); + //qDebug() << "channel=" << c << " sampleAt=" << sampleAt; + } + } +} + + // Starts a collision sound. magnitude is 0-1, with 1 the loudest possible sound. void Audio::startCollisionSound(float magnitude, float frequency, float noise, float duration, bool flashScreen) { _collisionSoundMagnitude = magnitude; diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 052eb06bdd..fe3a6cbb7c 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -55,7 +55,7 @@ public: void setJitterBufferSamples(int samples) { _jitterBufferSamples = samples; } int getJitterBufferSamples() { return _jitterBufferSamples; } - void lowPassFilter(int16_t* inputBuffer); + void lowPassFilter(int16_t* inputBuffer, int samples, int channels); virtual void startCollisionSound(float magnitude, float frequency, float noise, float duration, bool flashScreen); virtual void startDrumSound(float volume, float frequency, float duration, float decay); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3dd4733c64..9bb63b4a34 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -371,6 +371,9 @@ Menu::Menu() : false, appInstance->getAudio(), SLOT(toggleAudioSpatialProcessing())); + addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::LowPassFilter, + Qt::CTRL | Qt::SHIFT | Qt::Key_F, + false); addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b6feb2e2f5..99df84784a 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -270,6 +270,7 @@ namespace MenuOption { const QString Login = "Login"; const QString Logout = "Logout"; const QString LookAtVectors = "Look-at Vectors"; + const QString LowPassFilter = "Low Pass Filter"; const QString MetavoxelEditor = "Metavoxel Editor..."; const QString Chat = "Chat..."; const QString Metavoxels = "Metavoxels";