120 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "AudioDecoder.h"
 | |
| 
 | |
| AudioDecoder::AudioDecoder(QObject *parent) :
 | |
|     QIODevice(parent),
 | |
|     m_state { AudioDecoder::Stopped },
 | |
|     m_input { &m_data, this },
 | |
|     m_output { &m_data, this },
 | |
|     m_init { false },
 | |
|     m_isDecodingFinished { false }
 | |
| {
 | |
|     setOpenMode(QIODevice::ReadOnly);
 | |
| 
 | |
|     m_decoder = new QAudioDecoder(this);
 | |
|     connect(m_decoder, &QAudioDecoder::bufferReady, this, &AudioDecoder::bufferReady);
 | |
|     connect(m_decoder, static_cast<void(QAudioDecoder::*)(QAudioDecoder::Error)>(&QAudioDecoder::error), this, &AudioDecoder::errored);
 | |
|     connect(m_decoder, &QAudioDecoder::finished, this, &AudioDecoder::finished);
 | |
| }
 | |
| 
 | |
| AudioDecoder::~AudioDecoder(){
 | |
|     stop();
 | |
| }
 | |
| 
 | |
| // initialize an audio device
 | |
| void AudioDecoder::init(const QAudioFormat &format) {
 | |
|     m_decoder->setAudioFormat(format);
 | |
| 
 | |
|     if (!m_output.open(QIODevice::ReadOnly) || !m_input.open(QIODevice::WriteOnly)){
 | |
|         m_init = false;
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     m_init = true;
 | |
|     emit initialized();
 | |
| }
 | |
| 
 | |
| // play an audio file
 | |
| void AudioDecoder::start(const QString &filePath){
 | |
|     if(!m_init){
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if(m_state == AudioDecoder::Decoding){
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     m_state = AudioDecoder::Decoding;
 | |
|     m_decoder->setSourceFilename(filePath);
 | |
|     m_decoder->start();
 | |
| }
 | |
| 
 | |
| // Stop playing audio
 | |
| void AudioDecoder::stop() {
 | |
|     m_state = AudioDecoder::Stopped;
 | |
|     m_decoder->stop();
 | |
|     m_data.clear();
 | |
|     m_isDecodingFinished = false;
 | |
| }
 | |
| 
 | |
| 
 | |
| // io device, read into buffer.
 | |
| qint64 AudioDecoder::readData(char* data, qint64 maxlen) {
 | |
|     memset(data, 0, maxlen);
 | |
| 
 | |
|     if (m_state == AudioDecoder::Decoding){
 | |
|         m_output.read(data, maxlen);
 | |
| 
 | |
|         // Emulate QAudioProbe behaviour for audio data that is sent to output device
 | |
|         if (maxlen > 0){
 | |
|             QByteArray buff(data, maxlen);
 | |
|             emit newData(buff);
 | |
|         }
 | |
| 
 | |
|         // Is finish of file
 | |
|         if (atEnd()){
 | |
|             stop();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return maxlen;
 | |
| }
 | |
| 
 | |
| // io device, unused.
 | |
| qint64 AudioDecoder::writeData(const char* data, qint64 len) {
 | |
|     Q_UNUSED(data);
 | |
|     Q_UNUSED(len);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| // io device, at end of device
 | |
| bool AudioDecoder::atEnd() const {
 | |
|     bool value = m_output.size()
 | |
|         && m_output.atEnd()
 | |
|         && m_isDecodingFinished;
 | |
|     return value;
 | |
| }
 | |
| 
 | |
| // handle buffered data ready
 | |
| void AudioDecoder::bufferReady() {
 | |
|     const QAudioBuffer &buffer = m_decoder->read();
 | |
|     if(!buffer.isValid()){
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     const int length = buffer.byteCount();
 | |
|     const char *data = buffer.constData<char>();
 | |
| 
 | |
|     m_input.write(data, length);
 | |
| }
 | |
| 
 | |
| // handle buffered data decoding is finished
 | |
| void AudioDecoder::finished() {
 | |
|     m_isDecodingFinished = true;
 | |
| }
 | |
| 
 | |
| // handle buffered data decoding error
 | |
| void AudioDecoder::errored(QAudioDecoder::Error /*error*/) {
 | |
|     stop();
 | |
| }
 | 
