Siren audio engine in progress - Implementing Impulse-Response based reverb

This commit is contained in:
2013-02-15 15:13:48 -08:00
parent 4984dc9fbf
commit 0db5f91796
6 changed files with 85 additions and 28 deletions

View File

@@ -363,7 +363,7 @@
/* Begin PBXFileReference section */
104A335C1672D31B001C8BA6 /* KRCollider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = KRCollider.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
104A335D1672D31C001C8BA6 /* KRCollider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = KRCollider.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
10CC33A3168530A300BB9846 /* libPVRTexLib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPVRTexLib.a; path = PVRTexTool/Library/OSX_x86/Static/libPVRTexLib.a; sourceTree = PVRTexLib; };
10CC33A3168530A300BB9846 /* libPVRTexLib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPVRTexLib.a; path = Utilities/PVRTexLib/MacOS/libPVRTexLib.a; sourceTree = PVRSDK; };
E4030E4B160A3CF000592648 /* KRStockGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRStockGeometry.h; sourceTree = "<group>"; };
E40BA45215EFF79500D7C3DD /* KRAABB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRAABB.cpp; sourceTree = "<group>"; };
E40BA45315EFF79500D7C3DD /* KRAABB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRAABB.h; sourceTree = "<group>"; };

View File

@@ -37,7 +37,6 @@
#include "KRContext.h"
#include <Accelerate/Accelerate.h>
#include <vecLib/vDSP.h>
OSStatus alcASASetListenerProc(const ALuint property, ALvoid *data, ALuint dataSize);
ALvoid alcMacOSXRenderingQualityProc(const ALint value);
@@ -64,6 +63,7 @@ KRAudioManager::KRAudioManager(KRContext &context) : KRContextObject(context)
m_reverb_input_samples = NULL;
m_reverb_input_next_sample = 0;
m_reverb_accumulation = NULL;
for(int i=0; i < KRENGINE_MAX_REVERB_IMPULSE_MIX; i++) {
m_reverb_impulse_responses[i] = NULL;
m_reverb_impulse_responses_weight[i] = 0.0f;
@@ -137,7 +137,6 @@ void KRAudioManager::renderBlock()
// ----====---- Clear output accumulation buffer ----====----
memcpy(m_output_accumulation, m_reverb_accumulation, KRENGINE_FILTER_LENGTH * KRENGINE_MAX_OUTPUT_CHANNELS * sizeof(float));
memset(m_reverb_accumulation, 0, KRENGINE_FILTER_LENGTH * KRENGINE_MAX_OUTPUT_CHANNELS * sizeof(float));
// memset(m_output_accumulation, 0, KRENGINE_FILTER_LENGTH * KRENGINE_MAX_OUTPUT_CHANNELS * sizeof(float));
// ----====---- Render direct / HRTF audio ----====----
@@ -154,26 +153,22 @@ void KRAudioManager::renderBlock()
if(reverb_send_level > 0.0f) {
KRAudioSample *sample = source->getAudioSample();
if(sample) {
sample->sample((int)((__int64_t)m_audio_frame - source->getStartAudioFrame()), 44100, KRENGINE_FILTER_LENGTH, 0, reverb_data);
for(int i=0; i < KRENGINE_FILTER_LENGTH; i++) {
reverb_accum[i] += reverb_data[i] * reverb_send_level;
}
sample->sample((int)((__int64_t)m_audio_frame - source->getStartAudioFrame()), KRENGINE_FILTER_LENGTH, 0, reverb_data, reverb_send_level);
vDSP_vadd(reverb_accum, 1, reverb_data, 1, reverb_accum, 1, KRENGINE_FILTER_LENGTH);
}
}
}
m_reverb_input_next_sample += KRENGINE_FILTER_LENGTH;
if(m_reverb_input_next_sample >= KRENGINE_REVERB_MAX_SAMPLES) {
m_reverb_input_next_sample = 0;
}
// Apply impulse response reverb
// KRAudioSample *impulse_response = getContext().getAudioManager()->get("hrtf_kemar_H-10e000a");
// KRAudioSample *impulse_response = getContext().getAudioManager()->get("hrtf_kemar_H10e040a");
KRAudioSample *impulse_response = getContext().getAudioManager()->get("test_reverb");
if(impulse_response) {
int impulse_response_blocks = impulse_response->getFrameCount(44100) / KRENGINE_FILTER_LENGTH + 1;
impulse_response_blocks = 50;
int impulse_response_blocks = impulse_response->getFrameCount() / KRENGINE_FILTER_LENGTH + 1;
for(int impulse_response_block=0; impulse_response_block < impulse_response_blocks; impulse_response_block++) {
float impulse_block_start_index = impulse_response_block * KRENGINE_FILTER_LENGTH;
int reverb_block_start_index = (m_reverb_input_next_sample - KRENGINE_FILTER_LENGTH * (impulse_response_block + 1));
@@ -196,18 +191,22 @@ void KRAudioManager::renderBlock()
vDSP_fft_zip(m_fft_setup, &reverb_sample_data_complex, 1, KRENGINE_FILTER_LOG2 + 1, kFFTDirection_Forward);
int impulse_response_channels = 2;
for(int channel=0; channel < impulse_response_channels; channel++) {
float impulse_response_block_real[KRENGINE_FILTER_LENGTH * 2] __attribute__ ((aligned));
float impulse_response_block_imag[KRENGINE_FILTER_LENGTH * 2] __attribute__ ((aligned));
impulse_response->sample(impulse_block_start_index, 44100, KRENGINE_FILTER_LENGTH, channel, impulse_response_block_real);
impulse_response->sample(impulse_block_start_index, KRENGINE_FILTER_LENGTH, channel, impulse_response_block_real, 1.0f);
memset(impulse_response_block_real + KRENGINE_FILTER_LENGTH, 0, KRENGINE_FILTER_LENGTH * sizeof(float));
memset(impulse_response_block_imag, 0, KRENGINE_FILTER_LENGTH * 2 * sizeof(float));
DSPSplitComplex impulse_block_data_complex;
impulse_block_data_complex.realp = impulse_response_block_real;
impulse_block_data_complex.realp = impulse_response_block_real ;
impulse_block_data_complex.imagp = impulse_response_block_imag;
float conv_data_real[KRENGINE_FILTER_LENGTH * 2] __attribute__ ((aligned));
@@ -425,12 +424,11 @@ void KRAudioManager::initSiren()
m_reverb_input_samples = (float *)malloc(buffer_size);
memset(m_reverb_input_samples, 0, buffer_size);
m_reverb_input_next_sample = 0;
memset(m_reverb_input_samples, 0, buffer_size);
memset(m_reverb_accumulation, 0, KRENGINE_FILTER_LENGTH * 2 * sizeof(float));
m_reverb_accumulation = (float *)malloc(buffer_size * 2); // 2 channels
memset(m_reverb_accumulation, 0, buffer_size * 2);
m_fft_setup = vDSP_create_fftsetup( KRENGINE_FILTER_LOG2 + 1, kFFTRadix2); // We add 1 to KRENGINE_FILTER_LOG2, as we will zero-out the second half of the buffer when doing the overlap-add FFT convolution method
m_fft_setup = vDSP_create_fftsetup( 16, kFFTRadix2);
// ----====---- Initialize Core Audio Objects ----====----
OSDEBUG(NewAUGraph(&m_auGraph));
@@ -587,6 +585,11 @@ void KRAudioManager::cleanupSiren()
free(m_reverb_input_samples);
m_reverb_input_samples = NULL;
}
if(m_reverb_accumulation) {
free(m_reverb_accumulation);
m_reverb_accumulation = NULL;
}
for(int i=0; i < KRENGINE_MAX_REVERB_IMPULSE_MIX; i++) {
m_reverb_impulse_responses[i] = NULL;

View File

@@ -132,9 +132,9 @@ private:
KRAudioSample *m_reverb_impulse_responses[KRENGINE_MAX_REVERB_IMPULSE_MIX];
float m_reverb_impulse_responses_weight[KRENGINE_MAX_REVERB_IMPULSE_MIX];
float m_reverb_accumulation[KRENGINE_FILTER_LENGTH * 2];
float *m_reverb_accumulation;
float m_output_accumulation[KRENGINE_FILTER_LENGTH * KRENGINE_MAX_OUTPUT_CHANNELS]; // Interleaved output accumulation buffer
float *m_output_accumulation[KRENGINE_FILTER_LENGTH * KRENGINE_MAX_OUTPUT_CHANNELS]; // Interleaved output accumulation buffer
int m_output_sample;
FFTSetup m_fft_setup;

View File

@@ -35,6 +35,8 @@
#include "KRAudioBuffer.h"
#include "KRContext.h"
#include <Accelerate/Accelerate.h>
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension) : KRResource(context, name)
{
m_pData = new KRDataBlock();
@@ -78,9 +80,10 @@ int KRAudioSample::getChannelCount()
return m_channelsPerFrame;
}
int KRAudioSample::getFrameCount(int frame_rate)
int KRAudioSample::getFrameCount()
{
return (int)((__int64_t)m_totalFrames * (__int64_t)frame_rate / (__int64_t)m_frameRate);
//return (int)((__int64_t)m_totalFrames * (__int64_t)frame_rate / (__int64_t)m_frameRate);
return m_totalFrames;
}
float KRAudioSample::sample(int frame_offset, int frame_rate, int channel)
@@ -116,12 +119,62 @@ float KRAudioSample::sample(int frame_offset, int frame_rate, int channel)
}
}
void KRAudioSample::sample(int frame_offset, int frame_rate, int frame_count, int channel, float *buffer)
void KRAudioSample::sample(int frame_offset, int frame_count, int channel, float *buffer, float amplitude)
{
// FINDME, TODO, HACK - Replace with optimized function utilizing SIMD
for(int i=0; i < frame_count; i++ ) {
buffer[i] = sample(frame_offset + i, frame_rate, channel);
if(frame_offset + frame_count < 0) {
// Range is entirely before the sample
memset(buffer, 0, frame_count * sizeof(float));
} else if(frame_offset >= m_totalFrames) {
// Range is entirely after the sample
memset(buffer, 0, frame_count * sizeof(float));
} else {
int start_frame = frame_offset < 0 ? 0 : frame_offset;
int prefix_frames = frame_offset < 0 ? -frame_offset : 0;
if(prefix_frames > 0) {
// Prefix with padding of 0's
memset(buffer, 0, prefix_frames * sizeof(float));
}
int frames_per_buffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int buffer_index = start_frame / frames_per_buffer;
int buffer_offset = start_frame % frames_per_buffer;
int processed_frames = prefix_frames;
while(processed_frames < frame_count) {
int frames_left = frame_count - processed_frames;
if(buffer_index >= m_bufferCount) {
// Suffix with padding of 0's
memset(buffer + processed_frames, 0, frames_left * sizeof(float));
processed_frames += frames_left;
} else {
KRAudioBuffer *source_buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
int frames_to_copy = source_buffer->getFrameCount() - buffer_offset;
if(frames_to_copy > frames_left) frames_to_copy = frames_left;
if(frames_to_copy > 0) {
/*
void vDSP_vflt16 (
short *A,
vDSP_Stride __vDSP_I,
float *__vDSP_C,
vDSP_Stride __vDSP_K,
vDSP_Length __vDSP_N
);
*/
signed short *source_data = source_buffer->getFrameData() + buffer_offset * m_channelsPerFrame + channel;
vDSP_vflt16(source_data, m_channelsPerFrame, buffer + processed_frames, 1, frames_to_copy);
//memcpy(buffer + processed_frames, source_buffer->getFrameData() + buffer_offset, frames_to_copy * m_channelsPerFrame * sizeof(float));
processed_frames += frames_to_copy;
}
buffer_index++;
buffer_offset = 0;
}
}
}
float scale = amplitude / 32768.0f;
vDSP_vsmul(buffer, 1, &scale, buffer, 1, frame_count);
}
OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc

View File

@@ -56,9 +56,9 @@ public:
// Siren audio engine interface
int getChannelCount();
int getFrameCount(int frame_rate);
int getFrameCount();
float sample(int frame_offset, int frame_rate, int channel);
void sample(int frame_offset, int frame_rate, int frame_count, int channel, float *buffer);
void sample(int frame_offset, int frame_count, int channel, float *buffer, float amplitude);
private:

View File

@@ -82,6 +82,7 @@ using std::queue;
#endif
#include <Accelerate/Accelerate.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioToolbox/AudioFile.h>
#include <AudioToolbox/ExtendedAudioFile.h>