diff --git a/KREngine/kraken/KRAudioBuffer.cpp b/KREngine/kraken/KRAudioBuffer.cpp index 193f32a..c8eefdf 100644 --- a/KREngine/kraken/KRAudioBuffer.cpp +++ b/KREngine/kraken/KRAudioBuffer.cpp @@ -45,3 +45,18 @@ unsigned int KRAudioBuffer::getBufferID() { return m_bufferID; } + +int KRAudioBuffer::getFrameCount() +{ + return m_frameCount; +} + +int KRAudioBuffer::getFrameRate() +{ + return m_frameRate; +} + +signed short *KRAudioBuffer::getFrameData() +{ + return (signed short *)m_pData->getStart(); +} \ No newline at end of file diff --git a/KREngine/kraken/KRAudioBuffer.h b/KREngine/kraken/KRAudioBuffer.h index 7844c12..eb469de 100644 --- a/KREngine/kraken/KRAudioBuffer.h +++ b/KREngine/kraken/KRAudioBuffer.h @@ -22,6 +22,9 @@ public: ~KRAudioBuffer(); unsigned int getBufferID(); + int getFrameCount(); + int getFrameRate(); + signed short *getFrameData(); private: KRAudioManager *m_pSoundManager; diff --git a/KREngine/kraken/KRAudioManager.cpp b/KREngine/kraken/KRAudioManager.cpp index 3f277e3..c28b4a4 100644 --- a/KREngine/kraken/KRAudioManager.cpp +++ b/KREngine/kraken/KRAudioManager.cpp @@ -32,13 +32,14 @@ #include "KRAudioManager.h" #include "KREngine-common.h" #include "KRDataBlock.h" +#include "KRAudioBuffer.h" OSStatus alcASASetListenerProc(const ALuint property, ALvoid *data, ALuint dataSize); ALvoid alcMacOSXRenderingQualityProc(const ALint value); KRAudioManager::KRAudioManager(KRContext &context) : KRContextObject(context) { - m_audio_engine = KRAKEN_AUDIO_OPENAL; + m_audio_engine = KRAKEN_AUDIO_SIREN; // OpenAL m_alDevice = 0; @@ -63,15 +64,10 @@ void KRAudioManager::initAudio() } } -// audio render procedure, don't allocate memory, don't take any locks, don't waste time -static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) +void KRAudioManager::renderAudio(UInt32 inNumberFrames, AudioBufferList *ioData) { static float phase; static float pan_phase; - // Get a reference to the object that was passed with the callback - // In this case, the AudioController passed itself so - // that you can access its data. - KRAudioManager *THIS = (KRAudioManager*)inRefCon; // Get a pointer to the dataBuffer of the AudioBufferList @@ -96,20 +92,25 @@ static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioAction // -32767 to 32767 and then cast to an integer float left_channel = sinSignal * (sin(pan_phase) * 0.5f + 0.5f); float right_channel = sinSignal * (-sin(pan_phase) * 0.5f + 0.5f); + + + left_channel = 0; + right_channel = 0; + #if CA_PREFER_FIXED_POINT // Interleaved -// outA[i*2] = (SInt16)(left_channel * 32767.0f); -// outA[i*2 + 1] = (SInt16)(right_channel * 32767.0f); - + // outA[i*2] = (SInt16)(left_channel * 32767.0f); + // outA[i*2 + 1] = (SInt16)(right_channel * 32767.0f); + // Non-Interleaved outA[i] = (SInt32)(left_channel * 0x1000000f); outB[i] = (SInt32)(right_channel * 0x1000000f); #else - + // Interleaved -// outA[i*2] = (Float32)left_channel; -// outA[i*2 + 1] = (Float32)right_channel; - + // outA[i*2] = (Float32)left_channel; + // outA[i*2 + 1] = (Float32)right_channel; + // Non-Interleaved outA[i] = (Float32)left_channel; outB[i] = (Float32)right_channel; @@ -123,6 +124,60 @@ static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioAction phase = phase - M_PI * freq; } + for(std::set::iterator itr=m_activeAudioSources.begin(); itr != m_activeAudioSources.end(); itr++) { + int channel_count = 1; + + KRAudioSource *source = *itr; + KRAudioBuffer *buffer = source->getBuffer(); + int buffer_offset = source->getBufferFrame(); + int frames_advanced = 0; + for (UInt32 i = 0; i < inNumberFrames; ++i) { + float left_channel=0; + float right_channel=0; + if(buffer) { + short *frame = buffer->getFrameData() + (buffer_offset++ * channel_count); + frames_advanced++; + left_channel = (float)frame[0] / 32767.0f; + if(channel_count == 2) { + right_channel = (float)frame[1] / 32767.0f; + } else { + right_channel = left_channel; + } + if(buffer_offset >= buffer->getFrameCount()) { + source->advanceFrames(frames_advanced); + frames_advanced = 0; + buffer = source->getBuffer(); + buffer_offset = source->getBufferFrame(); + } + } + +#if CA_PREFER_FIXED_POINT + // Interleaved + // outA[i*2] = (SInt16)(left_channel * 32767.0f); + // outA[i*2 + 1] = (SInt16)(right_channel * 32767.0f); + + // Non-Interleaved + outA[i] += (SInt32)(left_channel * 0x1000000f); + outB[i] += (SInt32)(right_channel * 0x1000000f); +#else + + // Interleaved + // outA[i*2] = (Float32)left_channel; + // outA[i*2 + 1] = (Float32)right_channel; + + // Non-Interleaved + outA[i] += (Float32)left_channel; + outB[i] += (Float32)right_channel; +#endif + } + source->advanceFrames(frames_advanced); + } +} + +// audio render procedure, don't allocate memory, don't take any locks, don't waste time +OSStatus KRAudioManager::renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) +{ + ((KRAudioManager*)inRefCon)->renderAudio(inNumberFrames, ioData); return noErr; } @@ -298,7 +353,7 @@ void KRAudioManager::initSiren() OSDEBUG(AUGraphStart(m_auGraph)); - CAShow(m_auGraph); +// CAShow(m_auGraph); } } @@ -505,3 +560,13 @@ KRAudioManager::audio_engine_t KRAudioManager::getAudioEngine() { return m_audio_engine; } + +void KRAudioManager::activateAudioSource(KRAudioSource *audioSource) +{ + m_activeAudioSources.insert(audioSource); +} + +void KRAudioManager::deactivateAudioSource(KRAudioSource *audioSource) +{ + m_activeAudioSources.erase(audioSource); +} diff --git a/KREngine/kraken/KRAudioManager.h b/KREngine/kraken/KRAudioManager.h index f2bd005..4b13f69 100644 --- a/KREngine/kraken/KRAudioManager.h +++ b/KREngine/kraken/KRAudioManager.h @@ -38,6 +38,7 @@ #include "KRContextObject.h" #include "KRDataBlock.h" #include "KRMat4.h" +#include "KRAudioSource.h" const int KRENGINE_AUDIO_MAX_POOL_SIZE = 32; const int KRENGINE_AUDIO_MAX_BUFFER_SIZE = 64*1024; @@ -69,12 +70,16 @@ public: audio_engine_t getAudioEngine(); + void activateAudioSource(KRAudioSource *audioSource); + void deactivateAudioSource(KRAudioSource *audioSource); + private: map m_sounds; std::vector m_bufferPoolIdle; + std::set m_activeAudioSources; void initAudio(); void initOpenAL(); @@ -95,7 +100,8 @@ private: // Siren Handles AUGraph m_auGraph; AudioUnit m_auMixer; - + static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); + void renderAudio(UInt32 inNumberFrames, AudioBufferList *ioData); }; #endif /* defined(KRAUDIO_MANAGER_H) */ diff --git a/KREngine/kraken/KRAudioSource.cpp b/KREngine/kraken/KRAudioSource.cpp index fe104db..b78295a 100644 --- a/KREngine/kraken/KRAudioSource.cpp +++ b/KREngine/kraken/KRAudioSource.cpp @@ -39,6 +39,7 @@ OSStatus alcASASetSourceProc(const ALuint property, ALuint source, ALvoid *data, KRAudioSource::KRAudioSource(KRScene &scene, std::string name) : KRNode(scene, name) { + m_currentBufferFrame = 0; m_playing = false; m_is3d = true; m_isPrimed = false; @@ -154,22 +155,25 @@ void KRAudioSource::prime() m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name); } if(m_audioFile) { - getContext().getAudioManager()->makeCurrentContext(); - - // Initialize audio source - m_sourceID = 0; - ALDEBUG(alGenSources(1, &m_sourceID)); - // Prime the buffer queue m_nextBufferIndex = 0; for(int i=0; i < KRENGINE_AUDIO_BUFFERS_PER_SOURCE; i++) { queueBuffer(); } - //alSourcei(_sourceID, AL_BUFFER, firstBuffer.bufferID); - ALDEBUG(alSourcef(m_sourceID, AL_PITCH, m_pitch)); - ALDEBUG(alSourcei(m_sourceID, AL_LOOPING, m_looping && m_audioFile->getBufferCount() == 1)); - ALDEBUG(alSourcef(m_sourceID, AL_GAIN, m_gain)); + if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { + + // Initialize audio source + getContext().getAudioManager()->makeCurrentContext(); + + m_sourceID = 0; + ALDEBUG(alGenSources(1, &m_sourceID)); + + //alSourcei(_sourceID, AL_BUFFER, firstBuffer.bufferID); + ALDEBUG(alSourcef(m_sourceID, AL_PITCH, m_pitch)); + ALDEBUG(alSourcei(m_sourceID, AL_LOOPING, m_looping && m_audioFile->getBufferCount() == 1)); + ALDEBUG(alSourcef(m_sourceID, AL_GAIN, m_gain)); + } m_isPrimed = true; } @@ -182,7 +186,10 @@ void KRAudioSource::queueBuffer() m_audioBuffers.push(buffer); ALuint buffer_ids[1]; buffer_ids[0] = buffer->getBufferID(); - ALDEBUG(alSourceQueueBuffers(m_sourceID, 1, buffer_ids)); + + if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { + ALDEBUG(alSourceQueueBuffers(m_sourceID, 1, buffer_ids)); + } m_nextBufferIndex = (m_nextBufferIndex + 1) % m_audioFile->getBufferCount(); } @@ -230,9 +237,11 @@ void KRAudioSource::render(KRCamera *pCamera, std::vector &lights, co void KRAudioSource::setGain(float gain) { m_gain = gain; - if(m_isPrimed) { - getContext().getAudioManager()->makeCurrentContext(); - alSourcef(m_sourceID, AL_GAIN, m_gain); + if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { + if(m_isPrimed) { + getContext().getAudioManager()->makeCurrentContext(); + ALDEBUG(alSourcef(m_sourceID, AL_GAIN, m_gain)); + } } } @@ -244,10 +253,11 @@ float KRAudioSource::getGain() void KRAudioSource::setPitch(float pitch) { m_pitch = pitch; - if(m_isPrimed ) { - getContext().getAudioManager()->makeCurrentContext(); - alSourcef(m_sourceID, AL_PITCH, m_pitch); - + if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { + if(m_isPrimed ) { + getContext().getAudioManager()->makeCurrentContext(); + ALDEBUG(alSourcef(m_sourceID, AL_PITCH, m_pitch)); + } } } @@ -259,9 +269,11 @@ float KRAudioSource::getReferenceDistance() void KRAudioSource::setReferenceDistance(float reference_distance) { m_referenceDistance = reference_distance; - if(m_isPrimed && m_is3d) { - getContext().getAudioManager()->makeCurrentContext(); - ALDEBUG(alSourcef(m_sourceID, AL_REFERENCE_DISTANCE, m_referenceDistance)); + if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { + if(m_isPrimed && m_is3d) { + getContext().getAudioManager()->makeCurrentContext(); + ALDEBUG(alSourcef(m_sourceID, AL_REFERENCE_DISTANCE, m_referenceDistance)); + } } } @@ -273,9 +285,11 @@ float KRAudioSource::getReverb() void KRAudioSource::setReverb(float reverb) { m_reverb = reverb; - if(m_isPrimed && m_is3d) { - getContext().getAudioManager()->makeCurrentContext(); - ALDEBUG(alcASASetSourceProc(ALC_ASA_REVERB_SEND_LEVEL, m_sourceID, &m_reverb, sizeof(m_reverb))); + if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { + if(m_isPrimed && m_is3d) { + getContext().getAudioManager()->makeCurrentContext(); + ALDEBUG(alcASASetSourceProc(ALC_ASA_REVERB_SEND_LEVEL, m_sourceID, &m_reverb, sizeof(m_reverb))); + } } } @@ -288,9 +302,11 @@ float KRAudioSource::getRolloffFactor() void KRAudioSource::setRolloffFactor(float rolloff_factor) { m_rolloffFactor = rolloff_factor; - if(m_isPrimed && m_is3d) { - getContext().getAudioManager()->makeCurrentContext(); - ALDEBUG(alSourcef(m_sourceID, AL_ROLLOFF_FACTOR, m_rolloffFactor)); + if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { + if(m_isPrimed && m_is3d) { + getContext().getAudioManager()->makeCurrentContext(); + ALDEBUG(alSourcef(m_sourceID, AL_ROLLOFF_FACTOR, m_rolloffFactor)); + } } } @@ -337,54 +353,72 @@ void KRAudioSource::setIs3D(bool is3D) bool KRAudioSource::hasPhysics() { - return true; + KRAudioManager *audioManager = getContext().getAudioManager(); + return audioManager->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL; +} + +void KRAudioSource::advanceBuffer() +{ + if(m_audioBuffers.size()) { + delete m_audioBuffers.front(); + m_audioBuffers.pop(); + } + queueBuffer(); } void KRAudioSource::physicsUpdate(float deltaTime) { - if(m_isPrimed && m_playing) { - getContext().getAudioManager()->makeCurrentContext(); - updatePosition(); - ALint processed_count = 0; - ALDEBUG(alGetSourcei(m_sourceID, AL_BUFFERS_PROCESSED, &processed_count)); - while(processed_count-- > 0) { - ALuint finished_buffer = 0; - ALDEBUG(alSourceUnqueueBuffers(m_sourceID, 1, &finished_buffer)); - delete m_audioBuffers.front(); - m_audioBuffers.pop(); - queueBuffer(); - } + KRAudioManager *audioManager = getContext().getAudioManager(); + audioManager->activateAudioSource(this); + if(audioManager->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { - ALint val; - // Make sure the source is still playing, and restart it if needed. - ALDEBUG(alGetSourcei(m_sourceID, AL_SOURCE_STATE, &val)); - ALDEBUG(if(val != AL_PLAYING) alSourcePlay(m_sourceID)); + if(m_isPrimed && m_playing) { + getContext().getAudioManager()->makeCurrentContext(); + updatePosition(); + ALint processed_count = 0; + ALDEBUG(alGetSourcei(m_sourceID, AL_BUFFERS_PROCESSED, &processed_count)); + while(processed_count-- > 0) { + ALuint finished_buffer = 0; + ALDEBUG(alSourceUnqueueBuffers(m_sourceID, 1, &finished_buffer)); + advanceBuffer(); + } + + ALint val; + // Make sure the source is still playing, and restart it if needed. + ALDEBUG(alGetSourcei(m_sourceID, AL_SOURCE_STATE, &val)); + ALDEBUG(if(val != AL_PLAYING) alSourcePlay(m_sourceID)); + } } } void KRAudioSource::play() { - getContext().getAudioManager()->makeCurrentContext(); - prime(); - updatePosition(); + KRAudioManager *audioManager = getContext().getAudioManager(); + audioManager->activateAudioSource(this); + if(audioManager->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { + getContext().getAudioManager()->makeCurrentContext(); + prime(); + updatePosition(); - if(m_is3d) { - ALDEBUG(alSource3f(m_sourceID, AL_VELOCITY, 0.0f, 0.0f, 0.0f)); - ALDEBUG(alSourcef(m_sourceID, AL_REFERENCE_DISTANCE, m_referenceDistance)); - ALDEBUG(alSourcef(m_sourceID, AL_ROLLOFF_FACTOR, m_rolloffFactor)); - ALDEBUG(alcASASetSourceProc(ALC_ASA_REVERB_SEND_LEVEL, m_sourceID, &m_reverb, sizeof(m_reverb))); - ALDEBUG(alSourcei(m_sourceID, AL_SOURCE_RELATIVE, AL_FALSE)); - } else { - ALDEBUG(alSourcei(m_sourceID, AL_SOURCE_RELATIVE, AL_TRUE)); - ALDEBUG(alSource3f(m_sourceID, AL_POSITION, 0.0, 0.0, 0.0)); + if(m_is3d) { + ALDEBUG(alSource3f(m_sourceID, AL_VELOCITY, 0.0f, 0.0f, 0.0f)); + ALDEBUG(alSourcef(m_sourceID, AL_REFERENCE_DISTANCE, m_referenceDistance)); + ALDEBUG(alSourcef(m_sourceID, AL_ROLLOFF_FACTOR, m_rolloffFactor)); + ALDEBUG(alcASASetSourceProc(ALC_ASA_REVERB_SEND_LEVEL, m_sourceID, &m_reverb, sizeof(m_reverb))); + ALDEBUG(alSourcei(m_sourceID, AL_SOURCE_RELATIVE, AL_FALSE)); + } else { + ALDEBUG(alSourcei(m_sourceID, AL_SOURCE_RELATIVE, AL_TRUE)); + ALDEBUG(alSource3f(m_sourceID, AL_POSITION, 0.0, 0.0, 0.0)); + } + ALDEBUG(alSourcePlay(m_sourceID)); } - ALDEBUG(alSourcePlay(m_sourceID)); m_playing = true; } void KRAudioSource::stop() { - + m_playing = false; + getContext().getAudioManager()->deactivateAudioSource(this); } bool KRAudioSource::isPlaying() @@ -418,11 +452,40 @@ void KRAudioSource::updatePosition() ALDEBUG(alcASASetSourceProc(ALC_ASA_OCCLUSION, m_sourceID, &occlusion, sizeof(occlusion))); ALDEBUG(alcASASetSourceProc(ALC_ASA_OBSTRUCTION, m_sourceID, &obstruction, sizeof(obstruction))); ALDEBUG(alcASASetSourceProc(ALC_ASA_REVERB_SEND_LEVEL, m_sourceID, &m_reverb, sizeof(m_reverb))); - - } } +void KRAudioSource::advanceFrames(int frame_count) +{ + m_currentBufferFrame += frame_count; + + KRAudioBuffer *buffer = getBuffer(); + while(buffer != NULL && m_currentBufferFrame >= buffer->getFrameCount()) { + m_currentBufferFrame -= buffer->getFrameCount(); + advanceBuffer(); + buffer = getBuffer(); + } + + if(buffer == NULL) { + m_currentBufferFrame = 0; + stop(); + } +} + +KRAudioBuffer *KRAudioSource::getBuffer() +{ + if(m_playing) { + prime(); + return m_audioBuffers.front(); + } else { + return NULL; + } +} + +int KRAudioSource::getBufferFrame() +{ + return m_currentBufferFrame; +} OSStatus alcASASetSourceProc(const ALuint property, ALuint source, ALvoid *data, ALuint dataSize) { @@ -437,4 +500,3 @@ OSStatus alcASASetSourceProc(const ALuint property, ALuint source, ALvoid *data, err = proc(property, source, data, dataSize); return (err); } - diff --git a/KREngine/kraken/KRAudioSource.h b/KREngine/kraken/KRAudioSource.h index c7541c9..0ff1254 100644 --- a/KREngine/kraken/KRAudioSource.h +++ b/KREngine/kraken/KRAudioSource.h @@ -86,7 +86,16 @@ public: bool getEnableObstruction(); void setEnableObstruction(bool enable_obstruction); + // ---- Siren Audio Engine Interface ---- + + void advanceFrames(int frame_count); + KRAudioBuffer *getBuffer(); + int getBufferFrame(); + private: + int m_currentBufferFrame; // Siren Audio Engine frame number within current buffer + void advanceBuffer(); + std::string m_audio_sample_name; KRAudioSample *m_audioFile;