Merge pull request #2589 from PhilipRosedale/master

Tweaks to VU meter, tone injector, and fix to noise gate
This commit is contained in:
Brad Hefta-Gaub 2014-04-02 03:14:52 -07:00
commit c2bf3cd7d0
2 changed files with 45 additions and 38 deletions

View file

@ -2534,14 +2534,22 @@ void Application::displayOverlay() {
const float CLIPPING_INDICATOR_TIME = 1.0f;
const float AUDIO_METER_AVERAGING = 0.5;
const float LOG2 = log(2.f);
const float MAX_LOG2_SAMPLE = 15.f;
const float METER_LOUDNESS_SCALE = 2.8f / 5.f;
const float LOG2_LOUDNESS_FLOOR = 11.f;
float audioLevel = 0.f;
float loudness = _audio.getLastInputLoudness() + 1.f;
_trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.f - AUDIO_METER_AVERAGING) * loudness;
float log2loudness = log(_trailingAudioLoudness) / LOG2;
audioLevel = log2loudness / MAX_LOG2_SAMPLE * AUDIO_METER_SCALE_WIDTH;
if (log2loudness <= LOG2_LOUDNESS_FLOOR) {
audioLevel = (log2loudness / LOG2_LOUDNESS_FLOOR) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
} else {
audioLevel = (log2loudness - (LOG2_LOUDNESS_FLOOR - 1.f)) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
}
if (audioLevel > AUDIO_METER_SCALE_WIDTH) {
audioLevel = AUDIO_METER_SCALE_WIDTH;
}
bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));

View file

@ -444,12 +444,12 @@ void Audio::handleAudioInput() {
measuredDcOffset += monoAudioSamples[i];
monoAudioSamples[i] -= (int16_t) _dcOffset;
thisSample = fabsf(monoAudioSamples[i]);
if (thisSample > (32767.f * CLIPPING_THRESHOLD)) {
if (thisSample >= (32767.f * CLIPPING_THRESHOLD)) {
_timeSinceLastClip = 0.0f;
}
loudness += thisSample;
// Noise Reduction: Count peaks above the average loudness
if (thisSample > (_noiseGateMeasuredFloor * NOISE_GATE_HEIGHT)) {
if (_noiseGateEnabled && (thisSample > (_noiseGateMeasuredFloor * NOISE_GATE_HEIGHT))) {
samplesOverNoiseGate++;
}
}
@ -462,32 +462,41 @@ void Audio::handleAudioInput() {
_dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.f - DC_OFFSET_AVERAGING) * measuredDcOffset;
}
//
_lastInputLoudness = fabs(loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
float averageOfAllSampleFrames = 0.f;
_noiseSampleFrames[_noiseGateSampleCounter++] = _lastInputLoudness;
if (_noiseGateSampleCounter == NUMBER_OF_NOISE_SAMPLE_FRAMES) {
float smallestSample = FLT_MAX;
for (int i = 0; i <= NUMBER_OF_NOISE_SAMPLE_FRAMES - NOISE_GATE_FRAMES_TO_AVERAGE; i+= NOISE_GATE_FRAMES_TO_AVERAGE) {
float thisAverage = 0.0f;
for (int j = i; j < i + NOISE_GATE_FRAMES_TO_AVERAGE; j++) {
thisAverage += _noiseSampleFrames[j];
averageOfAllSampleFrames += _noiseSampleFrames[j];
}
thisAverage /= NOISE_GATE_FRAMES_TO_AVERAGE;
if (thisAverage < smallestSample) {
smallestSample = thisAverage;
}
// Add tone injection if enabled
const float TONE_FREQ = 220.f / SAMPLE_RATE * TWO_PI;
const float QUARTER_VOLUME = 8192.f;
if (_toneInjectionEnabled) {
loudness = 0.f;
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
monoAudioSamples[i] = QUARTER_VOLUME * sinf(TONE_FREQ * (float)(i + _proceduralEffectSample));
loudness += fabsf(monoAudioSamples[i]);
}
averageOfAllSampleFrames /= NUMBER_OF_NOISE_SAMPLE_FRAMES;
_noiseGateMeasuredFloor = smallestSample;
_noiseGateSampleCounter = 0;
}
_lastInputLoudness = fabs(loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
if (_noiseGateEnabled) {
// If Noise Gate is enabled, check and turn the gate on and off
if (!_toneInjectionEnabled && _noiseGateEnabled) {
float averageOfAllSampleFrames = 0.f;
_noiseSampleFrames[_noiseGateSampleCounter++] = _lastInputLoudness;
if (_noiseGateSampleCounter == NUMBER_OF_NOISE_SAMPLE_FRAMES) {
float smallestSample = FLT_MAX;
for (int i = 0; i <= NUMBER_OF_NOISE_SAMPLE_FRAMES - NOISE_GATE_FRAMES_TO_AVERAGE; i+= NOISE_GATE_FRAMES_TO_AVERAGE) {
float thisAverage = 0.0f;
for (int j = i; j < i + NOISE_GATE_FRAMES_TO_AVERAGE; j++) {
thisAverage += _noiseSampleFrames[j];
averageOfAllSampleFrames += _noiseSampleFrames[j];
}
thisAverage /= NOISE_GATE_FRAMES_TO_AVERAGE;
if (thisAverage < smallestSample) {
smallestSample = thisAverage;
}
}
averageOfAllSampleFrames /= NUMBER_OF_NOISE_SAMPLE_FRAMES;
_noiseGateMeasuredFloor = smallestSample;
_noiseGateSampleCounter = 0;
}
if (samplesOverNoiseGate > NOISE_GATE_WIDTH) {
_noiseGateOpen = true;
_noiseGateFramesToClose = NOISE_GATE_CLOSE_FRAME_DELAY;
@ -501,16 +510,6 @@ void Audio::handleAudioInput() {
_lastInputLoudness = 0;
}
}
//
// Add tone injection if enabled
//
const float TONE_FREQ = 220.f / SAMPLE_RATE * TWO_PI;
const float QUARTER_VOLUME = 8192.f;
if (_toneInjectionEnabled) {
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
monoAudioSamples[i] = QUARTER_VOLUME * sinf(TONE_FREQ * (float)(i + _proceduralEffectSample));
}
}
// add input data just written to the scope
QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection,