Fixed access violations

Implemented a divide-and-conquer approach to speeding up reverb engine, without increasing latency using multiple, different sized FFT's.  Algorithm optimized to ensure that the same amount of processing is done each frame.  Reverb now working in real-time.
This commit is contained in:
2013-02-16 01:35:05 -08:00
parent eee1dc28e0
commit 7e0459653d
6 changed files with 42 additions and 15 deletions

View File

@@ -152,7 +152,7 @@ void KRAudioManager::renderReverbImpulseResponse(KRAudioSample *impulse_response
DSPSplitComplex impulse_block_data_complex = m_reverb_workspace[1];
DSPSplitComplex conv_data_complex = m_reverb_workspace[2];
int reverb_offset = (m_reverb_input_next_sample - impulse_response_offset);
int reverb_offset = (m_reverb_input_next_sample + KRENGINE_AUDIO_BLOCK_LENGTH - frame_count);
if(reverb_offset < 0) {
reverb_offset += KRENGINE_REVERB_MAX_SAMPLES;
} else {
@@ -180,7 +180,7 @@ void KRAudioManager::renderReverbImpulseResponse(KRAudioSample *impulse_response
for(int channel=0; channel < impulse_response_channels; channel++) {
impulse_response->sample(impulse_response_offset, frame_count, channel, impulse_block_data_complex.realp, 1.0f);
memset(impulse_block_data_complex.realp + frame_count, 0, KRENGINE_AUDIO_BLOCK_LENGTH * sizeof(float));
memset(impulse_block_data_complex.realp + frame_count, 0, frame_count * sizeof(float));
memset(impulse_block_data_complex.imagp, 0, fft_size * sizeof(float));
vDSP_fft_zip(m_fft_setup, &impulse_block_data_complex, 1, fft_size_log_2, kFFTDirection_Forward);
@@ -189,10 +189,10 @@ void KRAudioManager::renderReverbImpulseResponse(KRAudioSample *impulse_response
vDSP_vsmul(conv_data_complex.realp, 1, &scale, conv_data_complex.realp, 1, fft_size);
int output_offset = m_output_accumulation_block_start;
int output_offset = (m_output_accumulation_block_start + impulse_response_offset * KRENGINE_MAX_OUTPUT_CHANNELS) % (KRENGINE_REVERB_MAX_SAMPLES * KRENGINE_MAX_OUTPUT_CHANNELS);
frames_left = fft_size;
while(frames_left) {
int frames_to_process = (KRENGINE_REVERB_MAX_SAMPLES * KRENGINE_MAX_OUTPUT_CHANNELS - m_output_accumulation_block_start) / 2;
int frames_to_process = (KRENGINE_REVERB_MAX_SAMPLES * KRENGINE_MAX_OUTPUT_CHANNELS - output_offset) / KRENGINE_MAX_OUTPUT_CHANNELS;
if(frames_to_process > frames_left) frames_to_process = frames_left;
vDSP_vadd(m_output_accumulation + output_offset + channel, KRENGINE_MAX_OUTPUT_CHANNELS, conv_data_complex.realp + fft_size - frames_left, 1, m_output_accumulation + output_offset + channel, KRENGINE_MAX_OUTPUT_CHANNELS, frames_to_process);
frames_left -= frames_to_process;
@@ -229,11 +229,36 @@ void KRAudioManager::renderReverb()
KRAudioSample *impulse_response_sample = getContext().getAudioManager()->get("test_reverb");
if(impulse_response_sample) {
int impulse_response_blocks = impulse_response_sample->getFrameCount() / KRENGINE_AUDIO_BLOCK_LENGTH + 1;
for(int impulse_response_block=0; impulse_response_block < impulse_response_blocks; impulse_response_block++) {
renderReverbImpulseResponse(impulse_response_sample, impulse_response_block * KRENGINE_AUDIO_BLOCK_LENGTH, KRENGINE_AUDIO_BLOCK_LOG2N);
int period_log_2 = 0;
int impulse_response_block=0;
int period_count = 0;
// fprintf(stderr, "m_reverb_sequence - %i - ", m_reverb_sequence);
while(impulse_response_block < impulse_response_blocks) {
int period = 1 << period_log_2;
if((m_reverb_sequence + period - period_count) % period == 0) {
// fprintf(stderr, "-%02i-", period);
renderReverbImpulseResponse(impulse_response_sample, impulse_response_block * KRENGINE_AUDIO_BLOCK_LENGTH, KRENGINE_AUDIO_BLOCK_LOG2N + period_log_2);
} else {
// fprintf(stderr, "----");
}
impulse_response_block += period;
period_count++;
if(period_count >= period) {
period_count = 0;
if(KRENGINE_AUDIO_BLOCK_LOG2N + period_log_2 + 1 < KRENGINE_REVERB_MAX_FFT_LOG_2) { // FFT Size is double the number of frames in the period
period_log_2++;
}
}
}
// fprintf(stderr, "\n");
}
m_reverb_sequence = (m_reverb_sequence + 1) % 0x1000000;
// Rotate reverb buffer
m_reverb_input_next_sample = (m_reverb_input_next_sample + KRENGINE_AUDIO_BLOCK_LENGTH) % KRENGINE_REVERB_MAX_SAMPLES;
}
@@ -302,7 +327,7 @@ void KRAudioManager::initSiren()
memset(m_output_accumulation, 0, buffer_size * 2);
m_output_accumulation_block_start = 0;
m_reverb_workspace_data = (float *)malloc(KRENGINE_REVERB_WORKSPACE_SIZE * 6);
m_reverb_workspace_data = (float *)malloc(KRENGINE_REVERB_WORKSPACE_SIZE * 6 * sizeof(float));
m_reverb_workspace[0].realp = m_reverb_workspace_data + KRENGINE_REVERB_WORKSPACE_SIZE * 0;
m_reverb_workspace[0].imagp = m_reverb_workspace_data + KRENGINE_REVERB_WORKSPACE_SIZE * 1;
m_reverb_workspace[1].realp = m_reverb_workspace_data + KRENGINE_REVERB_WORKSPACE_SIZE * 2;
@@ -312,7 +337,7 @@ void KRAudioManager::initSiren()
m_reverb_sequence = 0;
m_fft_setup = vDSP_create_fftsetup( 16, kFFTRadix2);
m_fft_setup = vDSP_create_fftsetup( KRENGINE_REVERB_MAX_FFT_LOG_2, kFFTRadix2);
// ----====---- Initialize Core Audio Objects ----====----
OSDEBUG(NewAUGraph(&m_auGraph));