diff options
author | Dimitri John Ledkov <xnox@ubuntu.com> | 2014-06-24 20:05:13 +0100 |
---|---|---|
committer | Dimitri John Ledkov <xnox@ubuntu.com> | 2014-06-24 20:05:13 +0100 |
commit | dd22bd15f6ed3e5eb5c77ab427029be50fe20148 (patch) | |
tree | d9491ee40d80688b7f5b1f20504f022686827a57 /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.cpp | 105 | ||||
-rw-r--r-- | src/audio/AudioBuffer.h | 61 | ||||
-rw-r--r-- | src/audio/AudioEngine.cpp | 295 | ||||
-rw-r--r-- | src/audio/AudioEngine.h | 94 | ||||
-rw-r--r-- | src/audio/AudioMsg.cpp | 165 | ||||
-rw-r--r-- | src/audio/AudioMsg.h | 85 | ||||
-rw-r--r-- | src/audio/AudioParams.cpp | 40 | ||||
-rw-r--r-- | src/audio/AudioParams.h | 39 | ||||
-rw-r--r-- | src/audio/AudioSource.cpp | 156 | ||||
-rw-r--r-- | src/audio/AudioSource.h | 66 | ||||
-rw-r--r-- | src/audio/Dynamics.h | 343 | ||||
-rw-r--r-- | src/audio/IProcessor.h | 37 | ||||
-rw-r--r-- | src/audio/Makefile.am | 17 | ||||
-rw-r--r-- | src/audio/testlimiter.cpp | 112 |
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; + } +} |