Added limiter and mute methods to KRAudioManager

--HG--
branch : nfb
This commit is contained in:
Peter Courtemanche
2014-01-14 13:32:56 -08:00
parent dea797a69c
commit 89f31f00ec
2 changed files with 117 additions and 2 deletions

View File

@@ -406,6 +406,9 @@ void KRAudioManager::renderBlock()
// ----====---- Render Ambient Sound ----====---- // ----====---- Render Ambient Sound ----====----
renderAmbient(); renderAmbient();
// ----====---- Render Ambient Sound ----====----
renderLimiter();
} }
// ----====---- Advance audio sources ----====---- // ----====---- Advance audio sources ----====----
@@ -1931,4 +1934,114 @@ void KRAudioManager::renderITD()
*/ */
} }
static bool audioIsMuted = false;
static bool audioShouldBecomeMuted = false;
static bool audioShouldBecomeUnmuted = false;
void audioLimit_Mute(bool onNotOff) {
if (onNotOff) {
if (audioIsMuted) return;
audioShouldBecomeMuted = true;
audioShouldBecomeUnmuted = false;
}
else {
if (!audioIsMuted) return;
audioShouldBecomeMuted = false;
audioShouldBecomeUnmuted = true;
}
}
float audioGetLimitParameters_Stereo(float *buffer, unsigned long framesize,
unsigned long *attack_sample_position, float *peak)
{
float limitvol = 1.0;
long attack_position = -1;
*peak = 0.0;
float max = 0.0;
float amplitude = 0.0;
float *src = buffer;
for (unsigned long i = 0; i < framesize * 2; i++) {
amplitude = fabs(*src); src++;
if (amplitude > max) max = amplitude;
if (amplitude > 0.995) if (attack_position < 0) attack_position = (i+1) / 2;
}
if (max > 0.995) limitvol = 0.995 / max;
*peak = max;
if (attack_position < 0) attack_position = framesize;
*attack_sample_position = (unsigned long) attack_position;
return limitvol;
} // returns the new limit volume, *attack_sample_position tells how fast we need to reach the new limit
void audioLimit_Stereo(float *stereo_buffer, unsigned long framesize)
{
static float limit_value = 1.0;
// (1) get the limiting parameters for the incoming audio data
float previouslimitvol = limit_value;
float peak;
unsigned long attack_sample_position;
// (1a) check for a mute or unmute state then get the next limit volume
float nextlimitvol = 0.0;
if (audioIsMuted && audioShouldBecomeUnmuted) { audioIsMuted = false; audioShouldBecomeUnmuted = false; }
if (audioShouldBecomeMuted) { audioIsMuted = true; audioShouldBecomeMuted = false; }
if (!audioIsMuted) nextlimitvol = audioGetLimitParameters_Stereo(stereo_buffer, framesize, &attack_sample_position, &peak);
// (1b) if no limiting is needed then return
if ((1.0 == nextlimitvol) && (1.0 == previouslimitvol)) { return; } // no limiting necessary
// (2) calculate limiting factors
float deltavol = 0.0;
if (previouslimitvol != nextlimitvol) {
deltavol = (nextlimitvol - previouslimitvol) / (float) attack_sample_position;
}
// (3) do the limiting
float *src = stereo_buffer;
if (0.0 == deltavol) { // fixed volume
for (unsigned long i=0; i < framesize; i++) {
*src = *src * nextlimitvol;
src++;
*src = *src * nextlimitvol;
src++;
}
}
else {
for (unsigned long i=0; i < attack_sample_position; i++) { // attack phase
*src = *src * previouslimitvol;
src++;
*src = *src * previouslimitvol;
src++;
previouslimitvol += deltavol;
}
if (nextlimitvol < 1.0) { // plateau phase
for (unsigned long i = attack_sample_position; i < framesize; i++) {
*src = *src * nextlimitvol;
src++;
*src = *src * nextlimitvol;
src++;
}
}
}
// (4) save our limit level for next time
limit_value = nextlimitvol;
}
void KRAudioManager::mute(bool onNotOff)
{
audioLimit_Mute(onNotOff);
}
void KRAudioManager::renderLimiter()
{
int output_offset = (m_output_accumulation_block_start) % (KRENGINE_REVERB_MAX_SAMPLES * KRENGINE_MAX_OUTPUT_CHANNELS);
float *output = m_output_accumulation + output_offset;
unsigned long numframes = KRENGINE_AUDIO_BLOCK_LENGTH;
audioLimit_Stereo(output, numframes);
}

View File

@@ -41,7 +41,7 @@
#include "KRAudioSource.h" #include "KRAudioSource.h"
const int KRENGINE_AUDIO_MAX_POOL_SIZE = 32; const int KRENGINE_AUDIO_MAX_POOL_SIZE = 32;
const int KRENGINE_AUDIO_MAX_BUFFER_SIZE = 64*1024; const int KRENGINE_AUDIO_MAX_BUFFER_SIZE = 64*1024; // this is the buffer for our decoded audio (not the source file data)
const int KRENGINE_AUDIO_BUFFERS_PER_SOURCE = 3; const int KRENGINE_AUDIO_BUFFERS_PER_SOURCE = 3;
const int KRENGINE_AUDIO_BLOCK_LOG2N = 7; // 2 ^ KRENGINE_AUDIO_BLOCK_LOG2N = KRENGINE_AUDIO_BLOCK_LENGTH const int KRENGINE_AUDIO_BLOCK_LOG2N = 7; // 2 ^ KRENGINE_AUDIO_BLOCK_LOG2N = KRENGINE_AUDIO_BLOCK_LENGTH
@@ -133,6 +133,7 @@ public:
KRAudioBuffer *getBuffer(KRAudioSample &audio_sample, int buffer_index); KRAudioBuffer *getBuffer(KRAudioSample &audio_sample, int buffer_index);
void mute(bool onNotOff);
void startFrame(float deltaTime); void startFrame(float deltaTime);
@@ -221,6 +222,7 @@ private:
void renderHRTF(); void renderHRTF();
void renderITD(); void renderITD();
void renderReverbImpulseResponse(int impulse_response_offset, int frame_count_log2); void renderReverbImpulseResponse(int impulse_response_offset, int frame_count_log2);
void renderLimiter();
std::vector<KRVector2> m_hrtf_sample_locations; std::vector<KRVector2> m_hrtf_sample_locations;
float *m_hrtf_data; float *m_hrtf_data;