From 29b518610b7cae44a59aec955484803f1a3ba6e3 Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Sun, 17 Nov 2013 01:46:12 -0800 Subject: [PATCH] Implemented API to read and seek the audio playback position of KRAudioSource --HG-- extra : source : 5ef720e0f476c72b85a7e2fc841af965d2038264 --- KREngine/kraken/KRAudioSource.cpp | 96 +++++++++++++++++++++++-------- KREngine/kraken/KRAudioSource.h | 39 +++++++++++-- 2 files changed, 106 insertions(+), 29 deletions(-) diff --git a/KREngine/kraken/KRAudioSource.cpp b/KREngine/kraken/KRAudioSource.cpp index afef53d..094817d 100644 --- a/KREngine/kraken/KRAudioSource.cpp +++ b/KREngine/kraken/KRAudioSource.cpp @@ -56,6 +56,7 @@ KRAudioSource::KRAudioSource(KRScene &scene, std::string name) : KRNode(scene, n m_enable_obstruction = true; m_start_audio_frame = -1; + m_paused_audio_frame = 0; } KRAudioSource::~KRAudioSource() @@ -314,12 +315,13 @@ void KRAudioSource::setRolloffFactor(float rolloff_factor) void KRAudioSource::setLooping(bool looping) { + // Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect m_looping = looping; - // Audio source must be stopped and re-started for loop mode changes to take effect } bool KRAudioSource::getLooping() { + // Returns true if the playback will automatically loop return m_looping; } @@ -400,38 +402,54 @@ void KRAudioSource::physicsUpdate(float deltaTime) void KRAudioSource::play() { - KRAudioManager *audioManager = getContext().getAudioManager(); - m_start_audio_frame = audioManager->getAudioFrame(); - audioManager->activateAudioSource(this); - if(audioManager->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) { - getContext().getAudioManager()->makeCurrentContext(); - prime(); - updatePosition(); + // Start playback of audio at the current audio sample position. If audio is already playing, this has no effect. + // play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample. + // If not set to looping, audio playback ends automatically at the end of the sample + + if(!m_playing) { + KRAudioManager *audioManager = getContext().getAudioManager(); + assert(m_start_audio_frame == -1); + m_start_audio_frame = audioManager->getAudioFrame() - m_paused_audio_frame; + m_paused_audio_frame = -1; + 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_start_audio_frame = -1; - m_playing = false; - getContext().getAudioManager()->deactivateAudioSource(this); + // Stop playback of audio. If audio is already stopped, this has no effect. + // If play() is called afterwards, playback will continue at the current audio sample position. + + if(m_playing) { + m_paused_audio_frame = getAudioFrame(); + m_start_audio_frame = -1; + m_playing = false; + getContext().getAudioManager()->deactivateAudioSource(this); + } } bool KRAudioSource::isPlaying() { + // Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample. + return m_playing; } @@ -504,16 +522,46 @@ int KRAudioSource::getBufferFrame() return m_currentBufferFrame; } -__int64_t KRAudioSource::getStartAudioFrame() +__int64_t KRAudioSource::getAudioFrame() { - return m_start_audio_frame; + // Returns the audio playback position in units of integer audio frames. + + if(m_playing) { + return getContext().getAudioManager()->getAudioFrame() - m_start_audio_frame; + } else { + return m_paused_audio_frame; + } +} + +void KRAudioSource::setAudioFrame(__int64_t next_frame) +{ + // Sets the audio playback position with units of integer audio frames. + if(m_playing) { + m_start_audio_frame = getContext().getAudioManager()->getAudioFrame() - next_frame; + } else { + m_paused_audio_frame = next_frame; + } +} + + +float KRAudioSource::getAudioTime() +{ + // Gets the audio playback position with units of floating point seconds. + + return getAudioFrame() / 44100.0f; +} + +void KRAudioSource::setAudioTime(float new_position) +{ + // Sets the audio playback position with units of floating point seconds. + setAudioFrame(new_position * 44100.0f); } void KRAudioSource::sample(int frame_count, int channel, float *buffer, float gain) { KRAudioSample *source_sample = getAudioSample(); if(source_sample && m_playing) { - __int64_t next_frame = getContext().getAudioManager()->getAudioFrame() - getStartAudioFrame(); + __int64_t next_frame = getAudioFrame(); source_sample->sample(next_frame, frame_count, channel, buffer, gain, m_looping); if(!m_looping && next_frame > source_sample->getFrameCount()) { stop(); diff --git a/KREngine/kraken/KRAudioSource.h b/KREngine/kraken/KRAudioSource.h index 8472f36..a82343e 100644 --- a/KREngine/kraken/KRAudioSource.h +++ b/KREngine/kraken/KRAudioSource.h @@ -51,10 +51,41 @@ public: virtual void physicsUpdate(float deltaTime); void render(KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass); + + // ---- Audio Playback Controls ---- + + // Start playback of audio at the current audio sample position. If audio is already playing, this has no effect. + // play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample. + // If not set to looping, audio playback ends automatically at the end of the sample void play(); + + // Stop playback of audio. If audio is already stopped, this has no effect. + // If play() is called afterwards, playback will continue at the current audio sample position. void stop(); + + // Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample. bool isPlaying(); + // Returns the audio playback position in units of integer audio frames. + __int64_t getAudioFrame(); + + // Sets the audio playback position with units of integer audio frames. + void setAudioFrame(__int64_t next_frame); + + // Gets the audio playback position with units of floating point seconds. + float getAudioTime(); + + // Sets the audio playback position with units of floating point seconds. + void setAudioTime(float new_position); + + // Returns true if the playback will automatically loop + bool getLooping(); + + // Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect + void setLooping(bool looping); + + // ---- End: Audio Playback Controls ---- + void setSample(const std::string &sound_name); std::string getSample(); @@ -66,8 +97,7 @@ public: float getPitch(); void setPitch(float pitch); - bool getLooping(); - void setLooping(bool looping); + bool getIs3D(); void setIs3D(bool is3D); @@ -94,12 +124,11 @@ public: KRAudioBuffer *getBuffer(); int getBufferFrame(); - - __int64_t getStartAudioFrame(); void sample(int frame_count, int channel, float *buffer, float gain); private: - __int64_t m_start_audio_frame; // Global audio frame that matches the start of the audio sample playback + __int64_t m_start_audio_frame; // Global audio frame that matches the start of the audio sample playback; when paused or not playing, this contains a value of -1 + __int64_t m_paused_audio_frame; // When paused or not playing, this contains the local audio frame number. When playing, this contains a value of -1 int m_currentBufferFrame; // Siren Audio Engine frame number within current buffer void advanceBuffer();