summaryrefslogtreecommitdiff
path: root/src/audio/AudioSource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/AudioSource.cpp')
-rw-r--r--src/audio/AudioSource.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/audio/AudioSource.cpp b/src/audio/AudioSource.cpp
new file mode 100644
index 0000000..7f6ae4a
--- /dev/null
+++ b/src/audio/AudioSource.cpp
@@ -0,0 +1,156 @@
+//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+#include "AudioSource.h"
+#include "AudioEngine.h"
+
+#include <string>
+#include <algorithm>
+
+using namespace std;
+
+namespace avg {
+
+AudioSource::AudioSource(AudioMsgQueue& msgQ, AudioMsgQueue& statusQ, int sampleRate)
+ : m_MsgQ(msgQ),
+ m_StatusQ(statusQ),
+ m_SampleRate(sampleRate),
+ m_bPaused(false),
+ m_bSeeking(false),
+ m_Volume(1.0),
+ m_LastVolume(1.0)
+{
+}
+
+AudioSource::~AudioSource()
+{
+}
+
+void AudioSource::pause()
+{
+ m_bPaused = true;
+}
+
+void AudioSource::play()
+{
+ m_bPaused = false;
+}
+
+void AudioSource::notifySeek()
+{
+ while (m_bSeeking) {
+ processNextMsg(true);
+ }
+ m_bSeeking = true;
+}
+
+void AudioSource::setVolume(float volume)
+{
+ m_Volume = volume;
+}
+
+void AudioSource::fillAudioBuffer(AudioBufferPtr pBuffer)
+{
+ bool bContinue = true;
+ while (bContinue && m_bSeeking) {
+ bContinue = processNextMsg(false);
+ }
+ if (!m_bPaused) {
+ unsigned char* pDest = (unsigned char *)(pBuffer->getData());
+ int framesLeftToFill = pBuffer->getNumFrames();
+ AudioMsgPtr pMsg;
+ while (framesLeftToFill > 0) {
+ int framesLeftInBuffer = 0;
+ if (m_pInputAudioBuffer) {
+ framesLeftInBuffer = m_pInputAudioBuffer->getNumFrames()
+ - m_CurInputAudioPos;
+ }
+ while (framesLeftInBuffer > 0 && framesLeftToFill > 0) {
+ int framesToCopy = min(framesLeftToFill, framesLeftInBuffer);
+ // cerr << "framesToCopy: " << framesToCopy << endl;
+ char * pInputPos = (char*)m_pInputAudioBuffer->getData() +
+ m_CurInputAudioPos*pBuffer->getFrameSize();
+ int bytesToCopy = framesToCopy*pBuffer->getFrameSize();
+ memcpy(pDest, pInputPos, bytesToCopy);
+ m_CurInputAudioPos += framesToCopy;
+ framesLeftToFill -= framesToCopy;
+ framesLeftInBuffer -= framesToCopy;
+ pDest += bytesToCopy;
+
+ m_LastTime += framesToCopy/m_SampleRate;
+ // cerr << " " << m_LastTime << endl;
+ }
+ if (framesLeftToFill != 0) {
+ bool bContinue = processNextMsg(false);
+ if (!bContinue) {
+ framesLeftToFill = 0;
+ }
+ }
+ }
+ pBuffer->volumize(m_LastVolume, m_Volume);
+ m_LastVolume = m_Volume;
+
+ AudioMsgPtr pStatusMsg(new AudioMsg);
+ pStatusMsg->setAudioTime(m_LastTime);
+ m_StatusQ.push(pStatusMsg);
+ }
+}
+
+bool AudioSource::processNextMsg(bool bWait)
+{
+ AudioMsgPtr pMsg = m_MsgQ.pop(bWait);
+ if (pMsg) {
+ switch (pMsg->getType()) {
+ case AudioMsg::AUDIO:
+ m_pInputAudioBuffer = pMsg->getAudioBuffer();
+ m_CurInputAudioPos = 0;
+ m_LastTime = pMsg->getAudioTime();
+// cerr << " New buffer: " << m_LastTime << endl;
+ return true;
+ case AudioMsg::END_OF_FILE: {
+// cerr << " AudioSource: EOF" << endl;
+ m_bSeeking = false;
+ AudioMsgPtr pStatusMsg(new AudioMsg);
+ pStatusMsg->setEOF();
+ m_StatusQ.push(pStatusMsg);
+ return false;
+ }
+ case AudioMsg::SEEK_DONE: {
+// cerr << " AudioSource: SEEK_DONE" << endl;
+ m_bSeeking = false;
+ m_pInputAudioBuffer = AudioBufferPtr();
+ m_LastTime = pMsg->getSeekTime();
+ AudioMsgPtr pStatusMsg(new AudioMsg);
+ pStatusMsg->setSeekDone(pMsg->getSeekSeqNum(), m_LastTime);
+ m_StatusQ.push(pStatusMsg);
+ return true;
+ }
+ default:
+ AVG_ASSERT(false);
+ return false;
+ }
+ } else {
+ // cerr << "no pop" << endl;
+ return false;
+ }
+}
+
+}