diff options
author | Christian Daniel <cd@maintech.de> | 2013-03-22 11:18:30 +0100 |
---|---|---|
committer | Christian Daniel <cd@maintech.de> | 2013-03-22 11:18:30 +0100 |
commit | eca56e35be841396f6c57bab540a3e1503253d56 (patch) | |
tree | 4a0a29cd53a84339e56754c32bf67391c83494fe /sdrbase/audio/audiofifo.cpp | |
parent | 2c8c930b39fe069b36d81caa00401d9ac182a9d8 (diff) |
monster rework
- pluginify whole project
- reorganize directory structure
- fix PortAudio detection script
- implement generic channelizer
- fix several OpenGL problems
- rework presets
- add audio mixing
- too many more
Diffstat (limited to 'sdrbase/audio/audiofifo.cpp')
-rw-r--r-- | sdrbase/audio/audiofifo.cpp | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/sdrbase/audio/audiofifo.cpp b/sdrbase/audio/audiofifo.cpp new file mode 100644 index 0000000..dd475ca --- /dev/null +++ b/sdrbase/audio/audiofifo.cpp @@ -0,0 +1,218 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program 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 General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see <http://www.gnu.org/licenses/>. // +/////////////////////////////////////////////////////////////////////////////////// + +#include <string.h> +#include <QTime> +#include "audio/audiofifo.h" + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +AudioFifo::AudioFifo() : + m_fifo(NULL) +{ + m_size = 0; + m_fill = 0; + m_head = 0; + m_tail = 0; +} + +AudioFifo::AudioFifo(uint sampleSize, uint numSamples) : + m_fifo(NULL) +{ + QMutexLocker mutexLocker(&m_mutex); + + create(sampleSize, numSamples); +} + +AudioFifo::~AudioFifo() +{ + QMutexLocker mutexLocker(&m_mutex); + + if(m_fifo != NULL) { + delete[] m_fifo; + m_fifo = NULL; + } + + m_writeWaitCondition.wakeOne(); + m_readWaitCondition.wakeOne(); + + m_size = 0; +} + +bool AudioFifo::setSize(uint sampleSize, uint numSamples) +{ + QMutexLocker mutexLocker(&m_mutex); + + return create(sampleSize, numSamples); +} + +uint AudioFifo::write(const quint8* data, uint numSamples, int timeout) +{ + QTime time; + uint total; + uint remaining; + uint copyLen; + + if(m_fifo == NULL) + return 0; + + time.start(); + m_mutex.lock(); + + if(timeout == 0) + total = MIN(numSamples, m_size - m_fill); + else total = numSamples; + + remaining = total; + while(remaining > 0) { + if(isFull()) { + if(time.elapsed() < timeout) { + m_writeWaitLock.lock(); + m_mutex.unlock(); + int ms = timeout - time.elapsed(); + if(ms < 1) + ms = 1; + bool ok = m_writeWaitCondition.wait(&m_writeWaitLock, ms); + m_writeWaitLock.unlock(); + if(!ok) + return total - remaining; + m_mutex.lock(); + if(m_fifo == NULL) { + m_mutex.unlock(); + return 0; + } + } else { + m_mutex.unlock(); + return total - remaining; + } + } + copyLen = MIN(remaining, m_size - m_fill); + copyLen = MIN(copyLen, m_size - m_tail); + memcpy(m_fifo + (m_tail * m_sampleSize), data, copyLen * m_sampleSize); + m_tail += copyLen; + m_tail %= m_size; + m_fill += copyLen; + data += copyLen * m_sampleSize; + remaining -= copyLen; + m_readWaitCondition.wakeOne(); + } + + m_mutex.unlock(); + return total; +} + +uint AudioFifo::read(quint8* data, uint numSamples, int timeout) +{ + QTime time; + uint total; + uint remaining; + uint copyLen; + + if(m_fifo == NULL) + return 0; + + time.start(); + m_mutex.lock(); + + if(timeout == 0) + total = MIN(numSamples, m_fill); + else total = numSamples; + + remaining = total; + while(remaining > 0) { + if(isEmpty()) { + if(time.elapsed() < timeout) { + m_readWaitLock.lock(); + m_mutex.unlock(); + int ms = timeout - time.elapsed(); + if(ms < 1) + ms = 1; + bool ok = m_readWaitCondition.wait(&m_readWaitLock, ms); + m_readWaitLock.unlock(); + if(!ok) + return total - remaining; + m_mutex.lock(); + if(m_fifo == NULL) { + m_mutex.unlock(); + return 0; + } + } else { + m_mutex.unlock(); + return total - remaining; + } + } + + copyLen = MIN(remaining, m_fill); + copyLen = MIN(copyLen, m_size - m_head); + memcpy(data, m_fifo + (m_head * m_sampleSize), copyLen * m_sampleSize); + m_head += copyLen; + m_head %= m_size; + m_fill -= copyLen; + data += copyLen * m_sampleSize; + remaining -= copyLen; + m_writeWaitCondition.wakeOne(); + } + + m_mutex.unlock(); + return total; +} + +uint AudioFifo::drain(uint numSamples) +{ + QMutexLocker mutexLocker(&m_mutex); + + if(numSamples > m_fill) + numSamples = m_fill; + m_head = (m_head + numSamples) % m_size; + m_fill -= numSamples; + + m_writeWaitCondition.wakeOne(); + return numSamples; +} + +void AudioFifo::clear() +{ + QMutexLocker mutexLocker(&m_mutex); + + m_fill = 0; + m_head = 0; + m_tail = 0; + + m_writeWaitCondition.wakeOne(); +} + +bool AudioFifo::create(uint sampleSize, uint numSamples) +{ + if(m_fifo != NULL) { + delete[] m_fifo; + m_fifo = NULL; + } + + m_sampleSize = sampleSize; + m_size = 0; + m_fill = 0; + m_head = 0; + m_tail = 0; + + if((m_fifo = new qint8[numSamples * m_sampleSize]) == NULL) { + qDebug("out of memory"); + return false; + } + + m_size = numSamples; + return true; +} |