summaryrefslogtreecommitdiff
path: root/src/audio
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2014-06-24 20:05:13 +0100
committerDimitri John Ledkov <xnox@ubuntu.com>2014-06-24 20:05:13 +0100
commitdd22bd15f6ed3e5eb5c77ab427029be50fe20148 (patch)
treed9491ee40d80688b7f5b1f20504f022686827a57 /src/audio
libavg (1.8.1-1) unstable; urgency=medium
* New upstream release (Closes: #739664) * Mark libdc1394-22-dev as linux-any build-dependency. * Add libvdpau-dev build-dependency. * Add libavresample-dev build-dependency. # imported from the archive
Diffstat (limited to 'src/audio')
-rw-r--r--src/audio/AudioBuffer.cpp105
-rw-r--r--src/audio/AudioBuffer.h61
-rw-r--r--src/audio/AudioEngine.cpp295
-rw-r--r--src/audio/AudioEngine.h94
-rw-r--r--src/audio/AudioMsg.cpp165
-rw-r--r--src/audio/AudioMsg.h85
-rw-r--r--src/audio/AudioParams.cpp40
-rw-r--r--src/audio/AudioParams.h39
-rw-r--r--src/audio/AudioSource.cpp156
-rw-r--r--src/audio/AudioSource.h66
-rw-r--r--src/audio/Dynamics.h343
-rw-r--r--src/audio/IProcessor.h37
-rw-r--r--src/audio/Makefile.am17
-rw-r--r--src/audio/testlimiter.cpp112
14 files changed, 1615 insertions, 0 deletions
diff --git a/src/audio/AudioBuffer.cpp b/src/audio/AudioBuffer.cpp
new file mode 100644
index 0000000..64032c3
--- /dev/null
+++ b/src/audio/AudioBuffer.cpp
@@ -0,0 +1,105 @@
+//
+// 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
+//
+// Original author of this file is Nick Hebner (hebnern@gmail.com).
+//
+
+#include "AudioBuffer.h"
+
+#include <string>
+#include <cstring>
+
+#define VOLUME_FADE_SAMPLES 100
+
+namespace avg {
+
+AudioBuffer::AudioBuffer(int numFrames, AudioParams ap)
+ : m_NumFrames(numFrames),
+ m_AP(ap)
+{
+ m_pData = new short[numFrames*sizeof(short)*ap.m_Channels];
+}
+
+AudioBuffer::~AudioBuffer()
+{
+ delete[] m_pData;
+}
+
+short* AudioBuffer::getData()
+{
+ return m_pData;
+}
+
+int AudioBuffer::getNumFrames()
+{
+ return m_NumFrames;
+}
+
+int AudioBuffer::getNumBytes()
+{
+ return m_NumFrames*m_AP.m_Channels*sizeof(short);
+}
+
+int AudioBuffer::getFrameSize()
+{
+ return m_AP.m_Channels*sizeof(short);
+}
+
+int AudioBuffer::getNumChannels()
+{
+ return m_AP.m_Channels;
+}
+
+int AudioBuffer::getRate()
+{
+ return m_AP.m_SampleRate;
+}
+
+void AudioBuffer::clear()
+{
+ memset(m_pData, 0, m_NumFrames*sizeof(short)*m_AP.m_Channels);
+}
+
+void AudioBuffer::volumize(float lastVol, float curVol)
+{
+ float volDiff = lastVol - curVol;
+
+ if (curVol == 1.0f && volDiff == 0.0f) {
+ return;
+ }
+
+ for (int i = 0; i < m_NumFrames*m_AP.m_Channels; i++) {
+ float fadeVol = 0;
+ if (volDiff != 0 && i < VOLUME_FADE_SAMPLES) {
+ fadeVol = volDiff * (VOLUME_FADE_SAMPLES - i) / VOLUME_FADE_SAMPLES;
+ }
+
+ int s = int(m_pData[i] * (curVol + fadeVol));
+
+ if (s < -32768)
+ s = -32768;
+ if (s > 32767)
+ s = 32767;
+
+ m_pData[i] = s;
+ }
+}
+
+}
diff --git a/src/audio/AudioBuffer.h b/src/audio/AudioBuffer.h
new file mode 100644
index 0000000..1dbf068
--- /dev/null
+++ b/src/audio/AudioBuffer.h
@@ -0,0 +1,61 @@
+//
+// 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
+//
+// Original author of this file is Nick Hebner (hebnern@gmail.com).
+//
+
+#ifndef _AudioBuffer_H_
+#define _AudioBuffer_H_
+
+#include "../api.h"
+#include "AudioParams.h"
+
+#include <boost/shared_ptr.hpp>
+
+namespace avg
+{
+
+class AVG_API AudioBuffer
+{
+ public:
+ AudioBuffer(int numFrames, AudioParams ap);
+ virtual ~AudioBuffer();
+
+ short* getData();
+ int getNumFrames();
+ int getNumBytes();
+ int getFrameSize();
+ int getNumChannels();
+ int getRate();
+ void clear();
+
+ void volumize(float lastVol, float curVol);
+
+ private:
+ int m_NumFrames;
+ short* m_pData;
+ AudioParams m_AP;
+};
+
+typedef boost::shared_ptr<AudioBuffer> AudioBufferPtr;
+
+}
+
+#endif
diff --git a/src/audio/AudioEngine.cpp b/src/audio/AudioEngine.cpp
new file mode 100644
index 0000000..aad1b9f
--- /dev/null
+++ b/src/audio/AudioEngine.cpp
@@ -0,0 +1,295 @@
+//
+// 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
+//
+// Original author of this file is Nick Hebner (hebnern@gmail.com).
+//
+
+#include "AudioEngine.h"
+
+#include "Dynamics.h"
+
+#include "../base/Exception.h"
+#include "../base/Logger.h"
+
+#include <iostream>
+
+using namespace std;
+using namespace boost;
+
+namespace avg {
+
+AudioEngine* AudioEngine::s_pInstance = 0;
+
+AudioEngine* AudioEngine::get()
+{
+ return s_pInstance;
+}
+
+AudioEngine::AudioEngine()
+ : m_pTempBuffer(),
+ m_pMixBuffer(0),
+ m_pLimiter(0),
+ m_bEnabled(true),
+ m_Volume(1)
+{
+ AVG_ASSERT(s_pInstance == 0);
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) {
+ AVG_LOG_ERROR("Can't init SDL audio subsystem.");
+ exit(-1);
+ }
+ s_pInstance = this;
+}
+
+AudioEngine::~AudioEngine()
+{
+ if (m_pMixBuffer) {
+ delete[] m_pMixBuffer;
+ }
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ m_AudioSources.clear();
+}
+
+int AudioEngine::getChannels()
+{
+ return m_AP.m_Channels;
+}
+
+int AudioEngine::getSampleRate()
+{
+ return m_AP.m_SampleRate;
+}
+
+const AudioParams * AudioEngine::getParams()
+{
+ if (isEnabled()) {
+ return &m_AP;
+ } else {
+ return 0;
+ }
+}
+
+void AudioEngine::init(const AudioParams& ap, float volume)
+{
+ m_Volume = volume;
+ m_AP = ap;
+ Dynamics<float, 2>* pLimiter = new Dynamics<float, 2>(float(m_AP.m_SampleRate));
+ pLimiter->setThreshold(0.f); // in dB
+ pLimiter->setAttackTime(0.f); // in seconds
+ pLimiter->setReleaseTime(0.05f); // in seconds
+ pLimiter->setRmsTime(0.f); // in seconds
+ pLimiter->setRatio(std::numeric_limits<float>::infinity());
+ pLimiter->setMakeupGain(0.f); // in dB
+ m_pLimiter = pLimiter;
+
+ SDL_AudioSpec desired;
+ desired.freq = m_AP.m_SampleRate;
+ desired.format = AUDIO_S16SYS;
+ desired.channels = m_AP.m_Channels;
+ desired.silence = 0;
+ desired.samples = m_AP.m_OutputBufferSamples;
+ desired.callback = audioCallback;
+ desired.userdata = this;
+
+ int err = SDL_OpenAudio(&desired, 0);
+ if (err < 0) {
+ static bool bWarned = false;
+ if (!bWarned) {
+ AVG_TRACE(Logger::category::CONFIG, Logger::severity::WARNING,
+ "Can't open audio: " << SDL_GetError());
+ bWarned = true;
+ }
+ }
+}
+
+void AudioEngine::teardown()
+{
+ {
+ lock_guard lock(m_Mutex);
+ SDL_PauseAudio(1);
+ }
+ // Optimized away - takes too long.
+// SDL_CloseAudio();
+
+ m_AudioSources.clear();
+ if (m_pLimiter) {
+ delete m_pLimiter;
+ m_pLimiter = 0;
+ }
+}
+
+void AudioEngine::setAudioEnabled(bool bEnabled)
+{
+ SDL_LockAudio();
+ lock_guard lock(m_Mutex);
+ AVG_ASSERT(m_AudioSources.empty());
+ m_bEnabled = bEnabled;
+ if (m_bEnabled) {
+ play();
+ } else {
+ pause();
+ }
+ SDL_UnlockAudio();
+}
+
+void AudioEngine::play()
+{
+ SDL_PauseAudio(0);
+}
+
+void AudioEngine::pause()
+{
+ SDL_PauseAudio(1);
+}
+
+int AudioEngine::addSource(AudioMsgQueue& dataQ, AudioMsgQueue& statusQ)
+{
+ SDL_LockAudio();
+ lock_guard lock(m_Mutex);
+ static int nextID = -1;
+ nextID++;
+ AudioSourcePtr pSrc(new AudioSource(dataQ, statusQ, m_AP.m_SampleRate));
+ m_AudioSources[nextID] = pSrc;
+ SDL_UnlockAudio();
+ return nextID;
+}
+
+void AudioEngine::removeSource(int id)
+{
+ SDL_LockAudio();
+ lock_guard lock(m_Mutex);
+ int numErased = m_AudioSources.erase(id);
+ AVG_ASSERT(numErased == 1);
+ SDL_UnlockAudio();
+}
+
+void AudioEngine::pauseSource(int id)
+{
+ lock_guard lock(m_Mutex);
+ AudioSourceMap::iterator itSource = m_AudioSources.find(id);
+ AVG_ASSERT(itSource != m_AudioSources.end());
+ AudioSourcePtr pSource = itSource->second;
+ pSource->pause();
+}
+
+void AudioEngine::playSource(int id)
+{
+ lock_guard lock(m_Mutex);
+ AudioSourceMap::iterator itSource = m_AudioSources.find(id);
+ AVG_ASSERT(itSource != m_AudioSources.end());
+ AudioSourcePtr pSource = itSource->second;
+ pSource->play();
+}
+
+void AudioEngine::notifySeek(int id)
+{
+ lock_guard lock(m_Mutex);
+ AudioSourceMap::iterator itSource = m_AudioSources.find(id);
+ AVG_ASSERT(itSource != m_AudioSources.end());
+ AudioSourcePtr pSource = itSource->second;
+ pSource->notifySeek();
+}
+
+void AudioEngine::setSourceVolume(int id, float volume)
+{
+ lock_guard lock(m_Mutex);
+ AudioSourceMap::iterator itSource = m_AudioSources.find(id);
+ AVG_ASSERT(itSource != m_AudioSources.end());
+ AudioSourcePtr pSource = itSource->second;
+ pSource->setVolume(volume);
+}
+
+void AudioEngine::setVolume(float volume)
+{
+ SDL_LockAudio();
+ lock_guard lock(m_Mutex);
+ m_Volume = volume;
+ SDL_UnlockAudio();
+}
+
+float AudioEngine::getVolume() const
+{
+ return m_Volume;
+}
+
+bool AudioEngine::isEnabled() const
+{
+ return m_bEnabled;
+}
+
+void AudioEngine::mixAudio(Uint8 *pDestBuffer, int destBufferLen)
+{
+ int numFrames = destBufferLen/(2*getChannels()); // 16 bit samples.
+
+ if (m_AudioSources.size() == 0) {
+ return;
+ }
+ if (!m_pTempBuffer || m_pTempBuffer->getNumFrames() < numFrames) {
+ if (m_pTempBuffer) {
+ delete[] m_pMixBuffer;
+ }
+ m_pTempBuffer = AudioBufferPtr(new AudioBuffer(numFrames, m_AP));
+ m_pMixBuffer = new float[getChannels()*numFrames];
+ }
+
+ for (int i = 0; i < getChannels()*numFrames; ++i) {
+ m_pMixBuffer[i]=0;
+ }
+ {
+ lock_guard lock(m_Mutex);
+ AudioSourceMap::iterator it;
+ for (it = m_AudioSources.begin(); it != m_AudioSources.end(); it++) {
+ m_pTempBuffer->clear();
+ it->second->fillAudioBuffer(m_pTempBuffer);
+ addBuffers(m_pMixBuffer, m_pTempBuffer);
+ }
+ }
+ calcVolume(m_pMixBuffer, numFrames*getChannels(), getVolume());
+ for (int i = 0; i < numFrames; ++i) {
+ m_pLimiter->process(m_pMixBuffer+i*getChannels());
+ for (int j = 0; j < getChannels(); ++j) {
+ ((short*)pDestBuffer)[i*2+j]=short(m_pMixBuffer[i*2+j]*32768);
+ }
+ }
+}
+
+void AudioEngine::audioCallback(void *userData, Uint8 *audioBuffer, int audioBufferLen)
+{
+ AudioEngine *pThis = (AudioEngine*)userData;
+ pThis->mixAudio(audioBuffer, audioBufferLen);
+}
+
+void AudioEngine::addBuffers(float *pDest, AudioBufferPtr pSrc)
+{
+ int numFrames = pSrc->getNumFrames();
+ short * pData = pSrc->getData();
+ for(int i = 0; i < numFrames*getChannels(); ++i) {
+ pDest[i] += pData[i]/32768.0f;
+ }
+}
+
+void AudioEngine::calcVolume(float *pBuffer, int numSamples, float volume)
+{
+ // TODO: We need a VolumeFader class that keeps state.
+ for(int i = 0; i < numSamples; ++i) {
+ pBuffer[i] *= volume;
+ }
+}
+
+}
diff --git a/src/audio/AudioEngine.h b/src/audio/AudioEngine.h
new file mode 100644
index 0000000..bb93196
--- /dev/null
+++ b/src/audio/AudioEngine.h
@@ -0,0 +1,94 @@
+//
+// 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
+//
+// Original author of this file is Nick Hebner (hebnern@gmail.com).
+//
+
+#ifndef _AudioEngine_H_
+#define _AudioEngine_H_
+
+#include "../api.h"
+#include "AudioSource.h"
+#include "AudioParams.h"
+#include "AudioBuffer.h"
+#include "IProcessor.h"
+
+#include <SDL/SDL.h>
+
+#include <boost/thread/mutex.hpp>
+
+#include <map>
+
+namespace avg {
+
+typedef std::map<int, AudioSourcePtr> AudioSourceMap;
+
+class AVG_API AudioEngine
+{
+ public:
+ static AudioEngine* get();
+ AudioEngine();
+ virtual ~AudioEngine();
+
+ int getChannels();
+ int getSampleRate();
+ const AudioParams * getParams();
+
+ void setAudioEnabled(bool bEnabled);
+
+ void init(const AudioParams& ap, float volume);
+ void teardown();
+
+ void play();
+ void pause();
+
+ int addSource(AudioMsgQueue& dataQ, AudioMsgQueue& statusQ);
+ void removeSource(int id);
+ void pauseSource(int id);
+ void playSource(int id);
+ void notifySeek(int id);
+ void setSourceVolume(int id, float volume);
+
+ void setVolume(float volume);
+ float getVolume() const;
+ bool isEnabled() const;
+
+ private:
+ void mixAudio(Uint8 *pDestBuffer, int destBufferLen);
+ static void audioCallback(void *userData, Uint8 *audioBuffer, int audioBufferLen);
+ void addBuffers(float *pDest, AudioBufferPtr pSrc);
+ void calcVolume(float *pBuffer, int numSamples, float volume);
+
+ AudioParams m_AP;
+ AudioBufferPtr m_pTempBuffer;
+ float * m_pMixBuffer;
+ IProcessor<float>* m_pLimiter;
+ boost::mutex m_Mutex;
+
+ bool m_bEnabled;
+ AudioSourceMap m_AudioSources;
+ float m_Volume;
+
+ static AudioEngine* s_pInstance;
+};
+
+}
+
+#endif
diff --git a/src/audio/AudioMsg.cpp b/src/audio/AudioMsg.cpp
new file mode 100644
index 0000000..2e1d6df
--- /dev/null
+++ b/src/audio/AudioMsg.cpp
@@ -0,0 +1,165 @@
+//
+// 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 "AudioMsg.h"
+
+#include "../base/ObjectCounter.h"
+#include "../base/Exception.h"
+
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+AudioMsg::AudioMsg()
+ : m_MsgType(NONE)
+{
+ ObjectCounter::get()->incRef(&typeid(*this));
+}
+
+AudioMsg::~AudioMsg()
+{
+ ObjectCounter::get()->decRef(&typeid(*this));
+}
+
+void AudioMsg::setAudio(AudioBufferPtr pAudioBuffer, float audioTime)
+{
+ AVG_ASSERT(pAudioBuffer);
+ setType(AUDIO);
+ m_pAudioBuffer = pAudioBuffer;
+ m_AudioTime = audioTime;
+}
+
+void AudioMsg::setAudioTime(float audioTime)
+{
+ setType(AUDIO_TIME);
+ m_AudioTime = audioTime;
+}
+
+void AudioMsg::setEOF()
+{
+ setType(END_OF_FILE);
+}
+
+void AudioMsg::setError(const Exception& ex)
+{
+ setType(ERROR);
+ m_pEx = new Exception(ex);
+}
+
+void AudioMsg::setSeekDone(int seqNum, float seekTime)
+{
+ setType(SEEK_DONE);
+ AVG_ASSERT(seqNum != -1);
+ m_SeekSeqNum = seqNum;
+ m_SeekTime = seekTime;
+}
+
+void AudioMsg::setClosed()
+{
+ setType(CLOSED);
+}
+
+AudioMsg::MsgType AudioMsg::getType()
+{
+ return m_MsgType;
+}
+
+AudioBufferPtr AudioMsg::getAudioBuffer() const
+{
+ AVG_ASSERT(m_MsgType == AUDIO);
+ return m_pAudioBuffer;
+}
+
+float AudioMsg::getAudioTime() const
+{
+ AVG_ASSERT(m_MsgType == AUDIO_TIME || m_MsgType == AUDIO);
+ return m_AudioTime;
+}
+
+const Exception& AudioMsg::getException() const
+{
+ AVG_ASSERT(m_MsgType == ERROR);
+ return *m_pEx;
+}
+
+int AudioMsg::getSeekSeqNum()
+{
+ AVG_ASSERT(m_MsgType == SEEK_DONE);
+ return m_SeekSeqNum;
+}
+
+float AudioMsg::getSeekTime()
+{
+ AVG_ASSERT(m_MsgType == SEEK_DONE);
+ return m_SeekTime;
+}
+
+void AudioMsg::dump()
+{
+ switch (m_MsgType) {
+ case NONE:
+ cerr << "NONE" << endl;
+ break;
+ case AUDIO:
+ cerr << "AUDIO" << endl;
+ break;
+ case AUDIO_TIME:
+ cerr << "AUDIO_TIME" << endl;
+ break;
+ case END_OF_FILE:
+ cerr << "END_OF_FILE" << endl;
+ break;
+ case ERROR:
+ cerr << "ERROR" << endl;
+ break;
+ case FRAME:
+ cerr << "FRAME" << endl;
+ break;
+ case VDPAU_FRAME:
+ cerr << "VDPAU_FRAME" << endl;
+ break;
+ case SEEK_DONE:
+ cerr << "SEEK_DONE" << endl;
+ break;
+ case PACKET:
+ cerr << "PACKET" << endl;
+ break;
+ case CLOSED:
+ cerr << "CLOSED" << endl;
+ break;
+ default:
+ AVG_ASSERT(false);
+ break;
+ }
+}
+
+void AudioMsg::setType(MsgType msgType)
+{
+ AVG_ASSERT(m_MsgType == NONE);
+ m_MsgType = msgType;
+}
+
+
+
+}
+
diff --git a/src/audio/AudioMsg.h b/src/audio/AudioMsg.h
new file mode 100644
index 0000000..89895e3
--- /dev/null
+++ b/src/audio/AudioMsg.h
@@ -0,0 +1,85 @@
+//
+// 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
+//
+
+#ifndef _AudioMsg_H_
+#define _AudioMsg_H_
+
+#include "../api.h"
+#include "../base/Queue.h"
+
+#include "AudioBuffer.h"
+
+#include <boost/shared_ptr.hpp>
+
+namespace avg {
+
+class AVG_API AudioMsg {
+public:
+ enum MsgType {NONE, AUDIO, AUDIO_TIME, END_OF_FILE, ERROR, FRAME, VDPAU_FRAME,
+ SEEK_DONE, PACKET, CLOSED};
+ AudioMsg();
+ void setAudio(AudioBufferPtr pAudioBuffer, float audioTime);
+ void setAudioTime(float audioTime);
+ void setEOF();
+ void setError(const Exception& ex);
+ void setSeekDone(int seqNum, float seekTime);
+ void setClosed();
+
+ virtual ~AudioMsg();
+
+ MsgType getType();
+
+ AudioBufferPtr getAudioBuffer() const;
+ float getAudioTime() const;
+
+ const Exception& getException() const;
+
+ int getSeekSeqNum();
+ float getSeekTime();
+
+ virtual void dump();
+
+protected:
+ void setType(MsgType msgType);
+
+private:
+ MsgType m_MsgType;
+
+ // AUDIO
+ AudioBufferPtr m_pAudioBuffer;
+ float m_AudioTime;
+
+ // ERROR
+ Exception* m_pEx;
+
+ // SEEK_DONE
+ int m_SeekSeqNum;
+ float m_SeekTime;
+
+};
+
+typedef boost::shared_ptr<AudioMsg> AudioMsgPtr;
+typedef Queue<AudioMsg> AudioMsgQueue;
+typedef boost::shared_ptr<AudioMsgQueue> AudioMsgQueuePtr;
+
+}
+#endif
+
diff --git a/src/audio/AudioParams.cpp b/src/audio/AudioParams.cpp
new file mode 100644
index 0000000..eee3768
--- /dev/null
+++ b/src/audio/AudioParams.cpp
@@ -0,0 +1,40 @@
+//
+// 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
+//
+// Original author of this file is Nick Hebner (hebnern@gmail.com).
+//
+
+#include "AudioParams.h"
+
+#include "../base/ObjectCounter.h"
+
+namespace avg {
+ AudioParams::AudioParams()
+ {
+ }
+
+ AudioParams::AudioParams(int sampleRate, int channels, int outputBufferSamples)
+ : m_SampleRate(sampleRate),
+ m_Channels(channels),
+ m_OutputBufferSamples(outputBufferSamples)
+ {
+ }
+}
+
diff --git a/src/audio/AudioParams.h b/src/audio/AudioParams.h
new file mode 100644
index 0000000..5e04b1d
--- /dev/null
+++ b/src/audio/AudioParams.h
@@ -0,0 +1,39 @@
+//
+// 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
+//
+// Original author of this file is Nick Hebner (hebnern@gmail.com).
+//
+
+#ifndef _AudioParams_H_
+#define _AudioParams_H_
+
+namespace avg {
+
+struct AudioParams {
+ AudioParams();
+ AudioParams(int sampleRate, int channels, int outputBufferSamples);
+ int m_SampleRate;
+ int m_Channels;
+ int m_OutputBufferSamples;
+};
+
+}
+
+#endif
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;
+ }
+}
+
+}
diff --git a/src/audio/AudioSource.h b/src/audio/AudioSource.h
new file mode 100644
index 0000000..f90daed
--- /dev/null
+++ b/src/audio/AudioSource.h
@@ -0,0 +1,66 @@
+//
+// 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
+//
+
+#ifndef _AudioSource_H_
+#define _AudioSource_H_
+
+#include "../api.h"
+
+#include "AudioMsg.h"
+
+#include <boost/shared_ptr.hpp>
+
+namespace avg
+{
+
+class AVG_API AudioSource
+{
+public:
+ AudioSource(AudioMsgQueue& msgQ, AudioMsgQueue& statusQ, int sampleRate);
+ virtual ~AudioSource();
+
+ void pause();
+ void play();
+ void notifySeek();
+ void setVolume(float volume);
+
+ void fillAudioBuffer(AudioBufferPtr pBuffer);
+
+private:
+ bool processNextMsg(bool bWait);
+
+ AudioMsgQueue& m_MsgQ;
+ AudioMsgQueue& m_StatusQ;
+ int m_SampleRate;
+ AudioBufferPtr m_pInputAudioBuffer;
+ float m_LastTime;
+ int m_CurInputAudioPos;
+ bool m_bPaused;
+ bool m_bSeeking;
+ float m_Volume;
+ float m_LastVolume;
+};
+
+typedef boost::shared_ptr<AudioSource> AudioSourcePtr;
+
+}
+
+#endif
diff --git a/src/audio/Dynamics.h b/src/audio/Dynamics.h
new file mode 100644
index 0000000..e5293e5
--- /dev/null
+++ b/src/audio/Dynamics.h
@@ -0,0 +1,343 @@
+//
+// 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
+//
+// Original author of this file is Andreas Beisler.
+//
+
+#pragma once
+#ifndef __Dynamics_H__
+#define __Dynamics_H__
+
+#include "../api.h"
+#include "IProcessor.h"
+
+#include <math.h>
+#include <cmath>
+#include <limits>
+#include <memory.h>
+
+#define LOOKAHEAD 64
+#define AVG1 27
+#define AVG2 38
+
+namespace avg {
+
+// Dynamics processor (compressor & limiter).
+template<typename T, int CHANNELS>
+class AVG_API Dynamics: public IProcessor<T>
+{
+ public:
+ Dynamics(T fs);
+ virtual ~Dynamics();
+ virtual void process(T* pSamples);
+
+ void setThreshold(T threshold);
+ T getThreshold() const;
+ void setRmsTime(T rmsTime);
+ T getRmsTime() const;
+ void setRatio(T ratio);
+ T getRatio() const;
+ void setAttackTime(T attTime);
+ T getAttackTime() const;
+ void setReleaseTime(T relTime);
+ T getReleaseTime() const;
+ void setMakeupGain(T makeupGain);
+ T getMakeupGain() const;
+
+ private:
+ void maxFilter(T& rms);
+
+ T m_fs;
+
+ T threshold_;
+ T preGain_;
+
+ T rmsTime_;
+ T rmsCoef_;
+ T rms1_;
+
+ T* lookaheadBuf_;
+ int lookaheadBufIdx_;
+
+ T ratio_;
+ T inverseRatio_;
+
+ T attTime_;
+ T attCoef_;
+ T relTime_;
+ T relCoef_;
+ T env1_;
+
+ T* avg1Buf_;
+ int avg1BufRIdx_;
+ int avg1BufWIdx_;
+ T avg1Old_;
+
+ T* avg2Buf_;
+ int avg2BufRIdx_;
+ int avg2BufWIdx_;
+ T avg2Old_;
+
+ T* delayBuf_;
+ int delayBufIdx_;
+
+ T makeupGain_;
+ T postGain_;
+};
+
+template<typename T, int CHANNELS>
+Dynamics<T, CHANNELS>::Dynamics(T fs)
+ : m_fs(fs),
+ threshold_(0.),
+ preGain_(1.),
+ rmsTime_(0.),
+ rmsCoef_(0.),
+ rms1_(0.),
+ lookaheadBuf_(0),
+ lookaheadBufIdx_(0),
+ ratio_(std::numeric_limits<T>::infinity()),
+ inverseRatio_(0.),
+ attTime_(0.),
+ attCoef_(0.),
+ relTime_(0.),
+ relCoef_(0.),
+ env1_(0.),
+ avg1Buf_(0),
+ avg1BufRIdx_(0),
+ avg1BufWIdx_(AVG1 - 1),
+ avg1Old_(0.),
+ avg2Buf_(0),
+ avg2BufRIdx_(0),
+ avg2BufWIdx_(AVG2 - 1),
+ avg2Old_(0.),
+ delayBuf_(0),
+ delayBufIdx_(0),
+ makeupGain_(0.),
+ postGain_(1.)
+{
+ lookaheadBuf_ = new T[LOOKAHEAD];
+ for (int i = 0; i < LOOKAHEAD; i++) {
+ lookaheadBuf_[i] = 1.f;
+ }
+
+ avg1Buf_ = new T[AVG1];
+ memset(avg1Buf_, 0, sizeof(T) * (AVG1));
+
+ avg2Buf_ = new T[AVG2];
+ memset(avg2Buf_, 0, sizeof(T) * (AVG2));
+
+ delayBuf_ = new T[LOOKAHEAD*CHANNELS];
+ memset(delayBuf_, 0, sizeof(T)*LOOKAHEAD*CHANNELS);
+
+ setThreshold(0.);
+ setRmsTime(0.);
+ setRatio(std::numeric_limits<T>::infinity());
+ setAttackTime(0.);
+ setReleaseTime(0.05);
+ setMakeupGain(0.);
+}
+
+template<typename T, int CHANNELS>
+Dynamics<T, CHANNELS>::~Dynamics()
+{
+ delete[] lookaheadBuf_;
+
+ delete[] avg1Buf_;
+ delete[] avg2Buf_;
+
+ delete[] delayBuf_;
+}
+
+template<typename T, int CHANNELS>
+void Dynamics<T, CHANNELS>::maxFilter(T& rms)
+{
+ int j = lookaheadBufIdx_;
+ for (int i = 0; i < LOOKAHEAD; i++)
+ {
+ j = (j+1)&(LOOKAHEAD-1);
+ if (lookaheadBuf_[j] < rms) {
+ lookaheadBuf_[j] = rms;
+ }
+ }
+}
+
+template<typename T, int CHANNELS>
+void Dynamics<T, CHANNELS>::process(T* pSamples)
+{
+
+ //---------------- Preprocessing
+ T x = 0.f;
+ for (int i = 0; i < CHANNELS; i++) {
+ // Apply pregain
+ const T tmp = pSamples[i] * preGain_;
+
+ T abs = std::fabs(tmp);
+ if (abs > x) {
+ x = abs;
+ }
+ }
+
+ //---------------- RMS
+ T rms = (1.f - rmsCoef_) * x * x + rmsCoef_ * rms1_;
+ rms1_ = rms;
+ rms = sqrt(rms);
+
+ //---------------- Max filter
+ if (rms > 1.) {
+ maxFilter(rms);
+ }
+
+ //---------------- Ratio
+ T dbMax = std::log10(lookaheadBuf_[lookaheadBufIdx_]);
+ T dbComp = dbMax * inverseRatio_;
+ T comp = std::pow(static_cast<T>(10.), dbComp);
+ T c = comp / lookaheadBuf_[lookaheadBufIdx_];
+
+ lookaheadBuf_[lookaheadBufIdx_] = 1.;
+ lookaheadBufIdx_ = (lookaheadBufIdx_+1)%LOOKAHEAD;
+
+ //---------------- Attack/release envelope
+ if (env1_ <= c) {
+ c = c + (env1_ - c) * relCoef_;
+ } else {
+ c = c + (env1_ - c) * attCoef_;
+ }
+ env1_ = c;
+
+ //---------------- Smoothing
+ const T tmp1 = avg1Old_ + c - avg1Buf_[avg1BufRIdx_];
+ avg1Old_ = tmp1;
+ avg1Buf_[avg1BufWIdx_] = c;
+ c = tmp1;
+ avg1BufRIdx_ = (avg1BufRIdx_+1)%AVG1;
+ avg1BufWIdx_ = (avg1BufWIdx_+1)%AVG1;
+
+ const T tmp2 = avg2Old_ + c - avg2Buf_[avg2BufRIdx_];
+ avg2Old_ = tmp2;
+ avg2Buf_[avg2BufWIdx_] = c;
+ c = tmp2;
+ avg2BufRIdx_ = (avg2BufRIdx_+1)%AVG2;
+ avg2BufWIdx_ = (avg2BufWIdx_+1)%AVG2;
+
+ c = c / (static_cast<T>(AVG1) * static_cast<T>(AVG2));
+
+ //---------------- Postprocessing
+ for (int i = 0; i < CHANNELS; i++) {
+ // Delay input samples
+ const T in = delayBuf_[delayBufIdx_*CHANNELS+i];
+ delayBuf_[delayBufIdx_*CHANNELS+i] = pSamples[i];
+
+ // Apply control signal
+ pSamples[i] = in * c * postGain_;
+ }
+
+ delayBufIdx_ = (delayBufIdx_+1)&(LOOKAHEAD-1);
+}
+
+template<typename T, int CHANNELS>
+void Dynamics<T, CHANNELS>::setThreshold(T threshold)
+{
+ threshold_ = threshold;
+ preGain_ = std::pow(10.f, -threshold / 20.f);
+}
+
+template<typename T, int CHANNELS>
+T Dynamics<T, CHANNELS>::getThreshold() const
+{
+ return threshold_;
+}
+
+template<typename T, int CHANNELS>
+void Dynamics<T, CHANNELS>::setRmsTime(T rmsTime)
+{
+ rmsTime_ = rmsTime;
+ rmsCoef_ = 0.f;
+ if (rmsTime > 0.f) {
+ rmsCoef_ = std::pow(0.001f, 1.f / (m_fs * rmsTime));
+ }
+}
+
+template<typename T, int CHANNELS>
+T Dynamics<T, CHANNELS>::getRmsTime() const
+{
+ return rmsTime_;
+}
+
+template<typename T, int CHANNELS>
+void Dynamics<T, CHANNELS>::setRatio(T ratio)
+{
+ ratio_ = ratio;
+ inverseRatio_ = 1.f / ratio;
+}
+
+template<typename T, int CHANNELS>
+T Dynamics<T, CHANNELS>::getRatio() const
+{
+ return ratio_;
+}
+
+template<typename T, int CHANNELS>
+void Dynamics<T, CHANNELS>::setAttackTime(T attTime)
+{
+ attTime_ = attTime;
+ attCoef_ = 0.f;
+ if (attTime > 0.f) {
+ attCoef_ = pow(0.001f, 1.f / (m_fs * attTime));
+ }
+}
+
+template<typename T, int CHANNELS>
+T Dynamics<T, CHANNELS>::getAttackTime() const
+{
+ return attTime_;
+}
+
+template<typename T, int CHANNELS>
+void Dynamics<T, CHANNELS>::setReleaseTime(T relTime)
+{
+ relTime_ = relTime;
+ relCoef_ = 0.f;
+ if (relTime > 0.f) {
+ relCoef_ = pow(0.001f, 1.f / (m_fs * relTime));
+ }
+}
+
+template<typename T, int CHANNELS>
+T Dynamics<T, CHANNELS>::getReleaseTime() const
+{
+ return relTime_;
+}
+
+template<typename T, int CHANNELS>
+void Dynamics<T, CHANNELS>::setMakeupGain(T makeupGain)
+{
+ makeupGain_ = makeupGain;
+ postGain_ = std::pow(10.f, makeupGain / 20.f);
+}
+
+template<typename T, int CHANNELS>
+T Dynamics<T, CHANNELS>::getMakeupGain() const
+{
+ return makeupGain_;
+}
+
+}
+
+#endif
diff --git a/src/audio/IProcessor.h b/src/audio/IProcessor.h
new file mode 100644
index 0000000..4eab2f0
--- /dev/null
+++ b/src/audio/IProcessor.h
@@ -0,0 +1,37 @@
+//
+// 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
+//
+
+#ifndef _Processor_H_
+#define _Processor_H_
+
+namespace avg {
+
+template<typename T>
+class AVG_API IProcessor
+{
+public:
+ virtual ~IProcessor() {};
+ virtual void process(T* pSamples) = 0;
+
+};
+
+}
+#endif
diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am
new file mode 100644
index 0000000..f475c7c
--- /dev/null
+++ b/src/audio/Makefile.am
@@ -0,0 +1,17 @@
+AM_CPPFLAGS = -I.. @PTHREAD_CFLAGS@
+
+ALL_H = AudioEngine.h AudioBuffer.h AudioParams.h \
+ Dynamics.h IProcessor.h AudioMsg.h AudioSource.h
+
+TESTS = testlimiter
+
+noinst_LTLIBRARIES = libaudio.la
+noinst_PROGRAMS = testlimiter
+
+libaudio_la_SOURCES = AudioEngine.cpp AudioBuffer.cpp AudioParams.cpp AudioMsg.cpp \
+ AudioSource.cpp $(ALL_H)
+
+testlimiter_SOURCES = testlimiter.cpp $(ALL_H)
+testlimiter_LDADD = ./libaudio.la ../base/libbase.la \
+ ../base/triangulate/libtriangulate.la \
+ @BOOST_THREAD_LIBS@ @PTHREAD_LIBS@
diff --git a/src/audio/testlimiter.cpp b/src/audio/testlimiter.cpp
new file mode 100644
index 0000000..5c3a515
--- /dev/null
+++ b/src/audio/testlimiter.cpp
@@ -0,0 +1,112 @@
+//
+// 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 "Dynamics.h"
+
+#include "../base/TestSuite.h"
+#include "../base/MathHelper.h"
+
+#include <stdlib.h>
+#include <iostream>
+
+using namespace avg;
+using namespace std;
+
+class LimiterTest: public Test {
+public:
+ LimiterTest()
+ : Test("LimiterTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ const int CHANNELS = 2;
+ float fs = 44100.f;
+ int numSamples = int(fs * 0.1f);
+
+ // Setup a brickwall limiter
+ typedef Dynamics<float, CHANNELS> TStereoLimiter;
+ TStereoLimiter* d = new TStereoLimiter(fs);
+ d->setThreshold(0.f); // in dB
+ d->setAttackTime(0.f); // in seconds
+ d->setReleaseTime(0.05f); // in seconds
+ d->setRmsTime(0.f); // in seconds
+ d->setRatio(std::numeric_limits<float>::infinity());
+ d->setMakeupGain(0.f); // in dB
+
+ // Generate input and output test data
+ float* pSamples = new float[CHANNELS*numSamples];
+ for (int j = 0; j < numSamples; j++) {
+ for (int i = 0; i < CHANNELS; i++) {
+ pSamples[j*CHANNELS+i] = 2*sin(j*(440.f/44100)*float(M_PI));
+ }
+ }
+
+ // Let the limiter work.
+ for (int i=0; i<numSamples; ++i) {
+ d->process(pSamples+i*CHANNELS);
+ }
+
+ // Check if everything is ok.
+ bool bDiscontinuities = false;
+ bool bAboveThreshold = false;
+ for (int j = 1; j < numSamples; j++) {
+ for (int i = 0; i < CHANNELS; i++) {
+ // Test if anything is above the threshold.
+ if (pSamples[j*CHANNELS+i] > 1) {
+ bAboveThreshold = true;
+ }
+ if (fabs(pSamples[j*CHANNELS+i]-pSamples[(j-1)*CHANNELS+i]) > 0.05f) {
+ bDiscontinuities = true;
+// cerr << j << ": " << outSamples[j*OUT_CHANNELS+i] << ", " <<
+// outSamples[(j-1)*OUT_CHANNELS+i] << endl;
+ }
+ }
+ }
+ TEST(!bAboveThreshold);
+ TEST(!bDiscontinuities);
+/*
+ // Save data to ascii file.
+ FILE * pFile = fopen("data.txt", "w");
+ for (int j = 0; j < numSamples; j++) {
+ fprintf(pFile, "%f\n", pSamples[j*OUT_CHANNELS]);
+ }
+ fclose(pFile);
+*/
+ // Free memory
+ delete d;
+ delete[] pSamples;
+ }
+};
+
+int main(int nargs, char** args)
+{
+ LimiterTest test;
+ test.runTests();
+ bool bOK = test.isOk();
+
+ if (bOK) {
+ return 0;
+ } else {
+ return 1;
+ }
+}