2013-01-05 04:04:58 +00:00
//
// FileManager.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
# ifndef KRAUDIO_MANAGER_H
# define KRAUDIO_MANAGER_H
2013-01-11 03:21:19 +00:00
# include "KREngine-common.h"
2013-01-05 04:04:58 +00:00
# include "KRAudioSample.h"
# include "KRContextObject.h"
# include "KRDataBlock.h"
2013-01-11 03:21:19 +00:00
# include "KRMat4.h"
2013-02-07 13:00:51 -08:00
# include "KRAudioSource.h"
2013-01-05 04:04:58 +00:00
const int KRENGINE_AUDIO_MAX_POOL_SIZE = 32 ;
const int KRENGINE_AUDIO_MAX_BUFFER_SIZE = 64 * 1024 ;
const int KRENGINE_AUDIO_BUFFERS_PER_SOURCE = 3 ;
2013-02-16 01:35:05 -08:00
const int KRENGINE_AUDIO_BLOCK_LENGTH = 128 ; // Length of one block to process. Determines the latency of the audio system and sets size for FFT's used in HRTF convolution
const int KRENGINE_AUDIO_BLOCK_LOG2N = 7 ; // 2 ^ KRENGINE_AUDIO_BLOCK_LOG2N = KRENGINE_AUDIO_BLOCK_LENGTH
2013-02-14 14:13:46 -08:00
2013-03-06 15:46:54 -08:00
const int KRENGINE_REVERB_MAX_FFT_LOG2 = 17 ;
2013-02-20 18:24:07 -08:00
const int KRENGINE_REVERB_WORKSPACE_SIZE = 1 < < KRENGINE_REVERB_MAX_FFT_LOG2 ;
2013-02-15 16:35:49 -08:00
2013-02-28 19:09:27 -08:00
const float KRENGINE_AUDIO_CUTOFF = 0.02f ; // Cutoff gain level, to cull out processing of very quiet sounds
2013-02-15 17:03:49 -08:00
const int KRENGINE_REVERB_MAX_SAMPLES = 435200 ; // At least 10s reverb impulse response length, divisible by KRENGINE_AUDIO_BLOCK_LENGTH
2013-02-14 14:13:46 -08:00
const int KRENGINE_MAX_REVERB_IMPULSE_MIX = 16 ; // Maximum number of impulse response filters that can be mixed simultaneously
const int KRENGINE_MAX_OUTPUT_CHANNELS = 2 ;
2013-03-06 15:46:54 -08:00
const int KRENGINE_MAX_ACTIVE_SOURCES = 24 ;
2013-03-06 18:45:41 -08:00
const int KRENGINE_AUDIO_ANTICLICK_SAMPLES = 64 ;
2013-03-06 15:46:54 -08:00
2013-02-28 19:09:27 -08:00
class KRAmbientZone ;
class KRReverbZone ;
typedef struct {
float weight ;
KRAmbientZone * ambient_zone ;
KRAudioSample * ambient_sample ;
} siren_ambient_zone_weight_info ;
typedef struct {
float weight ;
KRReverbZone * reverb_zone ;
KRAudioSample * reverb_sample ;
} siren_reverb_zone_weight_info ;
2013-01-05 04:04:58 +00:00
class KRAudioManager : public KRContextObject {
public :
KRAudioManager ( KRContext & context ) ;
virtual ~ KRAudioManager ( ) ;
void add ( KRAudioSample * Sound ) ;
KRAudioSample * load ( const std : : string & name , const std : : string & extension , KRDataBlock * data ) ;
KRAudioSample * get ( const std : : string & name ) ;
2013-02-28 19:09:27 -08:00
// Listener position and orientation
KRScene * getListenerScene ( ) ;
void setListenerScene ( KRScene * scene ) ;
2013-02-21 11:21:18 -08:00
void setListenerOrientation ( const KRVector3 & position , const KRVector3 & forward , const KRVector3 & up ) ;
void setListenerOrientationFromModelMatrix ( const KRMat4 & modelMatrix ) ;
KRVector3 & getListenerForward ( ) ;
KRVector3 & getListenerPosition ( ) ;
KRVector3 & getListenerUp ( ) ;
2013-02-28 19:09:27 -08:00
// Global audio gain / attenuation
float getGlobalGain ( ) ;
void setGlobalGain ( float gain ) ;
float getGlobalReverbSendLevel ( ) ;
void setGlobalReverbSendLevel ( float send_level ) ;
float getGlobalAmbientGain ( ) ;
void setGlobalAmbientGain ( float gain ) ;
2013-01-05 04:04:58 +00:00
2013-02-28 19:09:27 -08:00
2013-01-05 04:04:58 +00:00
void makeCurrentContext ( ) ;
KRDataBlock * getBufferData ( int size ) ;
void recycleBufferData ( KRDataBlock * data ) ;
2013-02-07 01:02:39 -08:00
enum audio_engine_t {
KRAKEN_AUDIO_NONE ,
KRAKEN_AUDIO_OPENAL ,
KRAKEN_AUDIO_SIREN
} ;
audio_engine_t getAudioEngine ( ) ;
2013-02-07 13:00:51 -08:00
void activateAudioSource ( KRAudioSource * audioSource ) ;
void deactivateAudioSource ( KRAudioSource * audioSource ) ;
2013-02-08 17:28:17 -08:00
__int64_t getAudioFrame ( ) ;
KRAudioBuffer * getBuffer ( KRAudioSample & audio_sample , int buffer_index ) ;
2013-02-07 01:02:39 -08:00
2013-02-28 19:09:27 -08:00
void startFrame ( float deltaTime ) ;
2013-01-05 04:04:58 +00:00
private :
2013-02-14 14:13:46 -08:00
2013-02-28 19:09:27 -08:00
KRScene * m_listener_scene ; // For now, only one scene is allowed to have active audio at once
2013-02-14 14:13:46 -08:00
float m_global_reverb_send_level ;
2013-02-28 19:09:27 -08:00
float m_global_ambient_gain ;
2013-02-20 22:48:01 -08:00
float m_global_gain ;
2013-02-14 14:13:46 -08:00
2013-02-08 17:28:17 -08:00
KRVector3 m_listener_position ;
KRVector3 m_listener_forward ;
KRVector3 m_listener_up ;
2013-04-24 18:12:03 -07:00
unordered_map < std : : string , KRAudioSample * > m_sounds ;
2013-01-05 04:04:58 +00:00
std : : vector < KRDataBlock * > m_bufferPoolIdle ;
2013-02-08 17:28:17 -08:00
std : : vector < KRAudioBuffer * > m_bufferCache ;
2013-02-07 13:00:51 -08:00
std : : set < KRAudioSource * > m_activeAudioSources ;
2013-02-07 01:02:39 -08:00
void initAudio ( ) ;
void initOpenAL ( ) ;
void initSiren ( ) ;
2013-02-20 18:24:07 -08:00
void initHRTF ( ) ;
2013-02-07 01:02:39 -08:00
void cleanupAudio ( ) ;
void cleanupOpenAL ( ) ;
void cleanupSiren ( ) ;
audio_engine_t m_audio_engine ;
// OpenAL Handles
2013-01-05 04:04:58 +00:00
ALCcontext * m_alContext ;
ALCdevice * m_alDevice ;
2013-02-02 23:58:08 -08:00
2013-02-07 01:02:39 -08:00
// Siren Handles
AUGraph m_auGraph ;
AudioUnit m_auMixer ;
2013-02-07 13:00:51 -08:00
static OSStatus renderInput ( void * inRefCon , AudioUnitRenderActionFlags * ioActionFlags , const AudioTimeStamp * inTimeStamp , UInt32 inBusNumber , UInt32 inNumberFrames , AudioBufferList * ioData ) ;
void renderAudio ( UInt32 inNumberFrames , AudioBufferList * ioData ) ;
2013-02-08 17:28:17 -08:00
__int64_t m_audio_frame ; // Number of audio frames processed since the start of the application
2013-02-14 14:13:46 -08:00
float * m_reverb_input_samples ; // Circular-buffered reverb input, single channel
int m_reverb_input_next_sample ; // Pointer to next sample in reverb buffer
2013-02-15 23:27:04 -08:00
int m_reverb_sequence ;
2013-02-14 14:13:46 -08:00
KRAudioSample * m_reverb_impulse_responses [ KRENGINE_MAX_REVERB_IMPULSE_MIX ] ;
float m_reverb_impulse_responses_weight [ KRENGINE_MAX_REVERB_IMPULSE_MIX ] ;
2013-02-15 16:13:12 -08:00
float * m_output_accumulation ; // Interleaved output accumulation buffer
int m_output_accumulation_block_start ;
2013-02-14 14:13:46 -08:00
int m_output_sample ;
FFTSetup m_fft_setup ;
2013-02-20 18:24:07 -08:00
float * m_workspace_data ;
DSPSplitComplex m_workspace [ 3 ] ;
2013-02-14 14:13:46 -08:00
2013-02-22 15:37:38 -08:00
2013-02-15 16:13:12 -08:00
float * getBlockAddress ( int block_offset ) ;
2013-02-14 14:13:46 -08:00
void renderBlock ( ) ;
2013-02-15 16:13:12 -08:00
void renderReverb ( ) ;
2013-02-28 19:09:27 -08:00
void renderAmbient ( ) ;
2013-02-15 16:13:12 -08:00
void renderHRTF ( ) ;
void renderITD ( ) ;
2013-02-28 19:09:27 -08:00
void renderReverbImpulseResponse ( int impulse_response_offset , int frame_count_log2 ) ;
2013-02-20 18:24:07 -08:00
std : : vector < KRVector2 > m_hrtf_sample_locations ;
2013-02-22 15:37:38 -08:00
float * m_hrtf_data ;
2013-04-24 18:12:03 -07:00
unordered_map < KRVector2 , DSPSplitComplex > m_hrtf_spectral [ 2 ] ;
2013-02-20 18:24:07 -08:00
2013-03-06 15:46:54 -08:00
KRVector2 getNearestHRTFSample ( const KRVector2 & dir ) ;
2013-02-20 18:24:07 -08:00
void getHRTFMix ( const KRVector2 & dir , KRVector2 & hrtf1 , KRVector2 & hrtf2 , KRVector2 & hrtf3 , KRVector2 & hrtf4 , float & mix1 , float & mix2 , float & mix3 , float & mix4 ) ;
2013-02-22 15:37:38 -08:00
KRAudioSample * getHRTFSample ( const KRVector2 & hrtf_dir ) ;
DSPSplitComplex getHRTFSpectral ( const KRVector2 & hrtf_dir , const int channel ) ;
2013-02-28 19:09:27 -08:00
2013-04-25 17:23:36 -07:00
unordered_map < std : : string , siren_ambient_zone_weight_info > m_ambient_zone_weights ;
2013-02-28 19:09:27 -08:00
float m_ambient_zone_total_weight = 0.0f ; // For normalizing zone weights
2013-04-25 17:23:36 -07:00
unordered_map < std : : string , siren_reverb_zone_weight_info > m_reverb_zone_weights ;
2013-02-28 19:09:27 -08:00
float m_reverb_zone_total_weight = 0.0f ; // For normalizing zone weights
boost : : signals2 : : mutex m_mutex ;
2013-03-06 15:46:54 -08:00
mach_timebase_info_data_t m_timebase_info ;
2013-04-25 17:23:36 -07:00
unordered_multimap < KRVector2 , std : : pair < KRAudioSource * , std : : pair < float , float > > > m_mapped_sources , m_prev_mapped_sources ;
2013-03-06 18:45:41 -08:00
bool m_anticlick_block ;
2013-03-06 15:46:54 -08:00
bool m_high_quality_hrtf ; // If true, 4 HRTF samples will be interpolated; if false, the nearest HRTF sample will be used without interpolation
2013-01-05 04:04:58 +00:00
} ;
# endif /* defined(KRAUDIO_MANAGER_H) */