| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // 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                  //
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:32:15 +02:00
										 |  |  | // (at your option) any later version.                                           //
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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>
 | 
					
						
							| 
									
										
										
										
											2017-08-24 23:54:51 +02:00
										 |  |  | #include "dsp/dsptypes.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | #include "audio/audiofifo.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-08 08:59:17 +01:00
										 |  |  | #include "audio/audionetsink.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define MIN(x, y) ((x) < (y) ? (x) : (y))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AudioFifo::AudioFifo() : | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 	m_fifo(nullptr), | 
					
						
							| 
									
										
										
										
											2018-03-27 09:23:42 +02:00
										 |  |  | 	m_sampleSize(sizeof(AudioSample)) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	m_size = 0; | 
					
						
							|  |  |  | 	m_fill = 0; | 
					
						
							|  |  |  | 	m_head = 0; | 
					
						
							|  |  |  | 	m_tail = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 00:02:49 +02:00
										 |  |  | AudioFifo::AudioFifo(uint32_t numSamples) : | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 	m_fifo(nullptr), | 
					
						
							| 
									
										
										
										
											2018-03-27 09:23:42 +02:00
										 |  |  |     m_sampleSize(sizeof(AudioSample)) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 00:02:49 +02:00
										 |  |  | 	create(numSamples); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AudioFifo::~AudioFifo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 	if (m_fifo) | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		delete[] m_fifo; | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 		m_fifo = nullptr; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_size = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 00:02:49 +02:00
										 |  |  | bool AudioFifo::setSize(uint32_t numSamples) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 00:02:49 +02:00
										 |  |  | 	return create(numSamples); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 17:08:04 +01:00
										 |  |  | uint32_t AudioFifo::write(const quint8* data, uint32_t numSamples) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-24 11:49:47 +02:00
										 |  |  | 	uint32_t total; | 
					
						
							|  |  |  | 	uint32_t remaining; | 
					
						
							|  |  |  | 	uint32_t copyLen; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 	if (!m_fifo) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_mutex.lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 	total = MIN(numSamples, m_size - m_fill); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	remaining = total; | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 	while (remaining != 0) | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		if (isFull()) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 			m_mutex.unlock(); | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (total - remaining > 0) { | 
					
						
							|  |  |  | 				emit dataReady(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 			return total - remaining; // written so far
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		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_mutex.unlock(); | 
					
						
							| 
									
										
										
										
											2022-03-18 17:08:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 15:53:04 +01:00
										 |  |  | 	emit dataReady(); | 
					
						
							| 
									
										
										
										
											2022-03-18 17:08:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (total < numSamples) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		qCritical("AudioFifo::write: (%s) overflow %u samples", | 
					
						
							|  |  |  | 			qPrintable(m_label), numSamples - total); | 
					
						
							|  |  |  | 		emit overflow(numSamples - total); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	return total; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 17:08:04 +01:00
										 |  |  | uint32_t AudioFifo::read(quint8* data, uint32_t numSamples) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-24 11:49:47 +02:00
										 |  |  | 	uint32_t total; | 
					
						
							|  |  |  | 	uint32_t remaining; | 
					
						
							|  |  |  | 	uint32_t copyLen; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 	if (!m_fifo) { | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_mutex.lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 	total = MIN(numSamples, m_fill); | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	remaining = total; | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 	while (remaining != 0) | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 		if (isEmpty()) | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-09-12 15:30:53 +02:00
										 |  |  | 			m_mutex.unlock(); | 
					
						
							|  |  |  | 			return total - remaining; // read so far
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		copyLen = MIN(remaining, m_fill); | 
					
						
							|  |  |  | 		copyLen = MIN(copyLen, m_size - m_head); | 
					
						
							|  |  |  | 		memcpy(data, m_fifo + (m_head * m_sampleSize), copyLen * m_sampleSize); | 
					
						
							| 
									
										
										
										
											2018-03-09 06:54:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		m_head += copyLen; | 
					
						
							|  |  |  | 		m_head %= m_size; | 
					
						
							|  |  |  | 		m_fill -= copyLen; | 
					
						
							|  |  |  | 		data += copyLen * m_sampleSize; | 
					
						
							|  |  |  | 		remaining -= copyLen; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_mutex.unlock(); | 
					
						
							|  |  |  | 	return total; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-24 11:49:47 +02:00
										 |  |  | uint AudioFifo::drain(uint32_t numSamples) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(numSamples > m_fill) | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		numSamples = m_fill; | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	m_head = (m_head + numSamples) % m_size; | 
					
						
							|  |  |  | 	m_fill -= numSamples; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return numSamples; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioFifo::clear() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_fill = 0; | 
					
						
							|  |  |  | 	m_head = 0; | 
					
						
							|  |  |  | 	m_tail = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 00:02:49 +02:00
										 |  |  | bool AudioFifo::create(uint32_t numSamples) | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 	if (m_fifo) | 
					
						
							| 
									
										
										
										
											2015-08-20 03:38:31 +02:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 		delete[] m_fifo; | 
					
						
							| 
									
										
										
										
											2020-11-21 11:15:06 +01:00
										 |  |  | 		m_fifo = nullptr; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_fill = 0; | 
					
						
							|  |  |  | 	m_head = 0; | 
					
						
							|  |  |  | 	m_tail = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 03:04:42 +01:00
										 |  |  | 	m_fifo = new qint8[numSamples * m_sampleSize]; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | 	m_size = numSamples; | 
					
						
							| 
									
										
										
										
											2018-02-22 03:04:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-21 19:28:11 +02:00
										 |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2014-05-18 16:52:39 +01:00
										 |  |  | } |