File indexing completed on 2024-05-19 04:56:25
0001 /** 0002 * \file qtfingerprintdecoder.cpp 0003 * Chromaprint fingerprint decoder using QAudioDecoder. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 15 Feb 2013 0008 * 0009 * Copyright (C) 2013 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #include "qtfingerprintdecoder.h" 0028 #include <QAudioDecoder> 0029 #include <QTimer> 0030 #if QT_VERSION >= 0x060200 0031 #include <QUrl> 0032 #endif 0033 #include "fingerprintcalculator.h" 0034 0035 /** 0036 * Constructor. 0037 * @param parent parent object 0038 */ 0039 QtFingerprintDecoder::QtFingerprintDecoder(QObject* parent) : 0040 AbstractFingerprintDecoder(parent), 0041 m_decoder(new QAudioDecoder(this)), m_timer(new QTimer(this)) 0042 { 0043 QAudioFormat desiredFormat; 0044 desiredFormat.setChannelCount(2); 0045 desiredFormat.setSampleRate(44100); 0046 #if QT_VERSION >= 0x060200 0047 desiredFormat.setSampleFormat(QAudioFormat::Int16); 0048 #else 0049 desiredFormat.setCodec(QLatin1String("audio/x-raw-int")); 0050 desiredFormat.setSampleType(QAudioFormat::SignedInt); 0051 desiredFormat.setSampleSize(16); 0052 #endif 0053 0054 m_decoder->setAudioFormat(desiredFormat); 0055 connect(m_decoder, SIGNAL(bufferReady()), this, SLOT(receiveBuffer())); 0056 connect(m_decoder, SIGNAL(error(QAudioDecoder::Error)), 0057 this, SLOT(receiveError())); 0058 connect(m_decoder, SIGNAL(finished()), this, SLOT(finishDecoding())); 0059 0060 m_timer->setSingleShot(true); 0061 m_timer->setInterval(5000); 0062 connect(m_timer, SIGNAL(timeout()), this, SLOT(receiveTimeout())); 0063 } 0064 0065 /** 0066 * Destructor. 0067 */ 0068 QtFingerprintDecoder::~QtFingerprintDecoder() 0069 { 0070 } 0071 0072 /** 0073 * Run decoder on audio file. 0074 * @param filePath path to audio file 0075 */ 0076 void QtFingerprintDecoder::start(const QString& filePath) 0077 { 0078 AbstractFingerprintDecoder::start(filePath); 0079 #if QT_VERSION >= 0x060200 0080 m_decoder->setSource(QUrl::fromLocalFile(filePath)); 0081 #else 0082 m_decoder->setSourceFilename(filePath); 0083 #endif 0084 0085 QAudioFormat format = m_decoder->audioFormat(); 0086 emit started(format.sampleRate(), format.channelCount()); 0087 m_timer->start(); 0088 m_decoder->start(); 0089 } 0090 0091 /** 0092 * Stop decoder. 0093 * Can be used to stop the decoder when an error is found after 0094 * getting bufferReady() data. 0095 */ 0096 void QtFingerprintDecoder::stop() 0097 { 0098 AbstractFingerprintDecoder::stop(); 0099 m_timer->stop(); 0100 m_decoder->stop(); 0101 } 0102 0103 /** 0104 * Receive a buffer with decoded audio data. 0105 */ 0106 void QtFingerprintDecoder::receiveBuffer() 0107 { 0108 m_timer->stop(); 0109 QAudioBuffer buffer = m_decoder->read(); 0110 if (!buffer.isValid()) { 0111 return; 0112 } 0113 if (buffer.startTime() > 120000000LL) { 0114 finishDecoding(); 0115 return; 0116 } 0117 emit bufferReady(QByteArray(buffer.constData<char>(), buffer.byteCount())); 0118 m_timer->start(); 0119 } 0120 0121 /** 0122 * Receive an error from the decoder. 0123 */ 0124 void QtFingerprintDecoder::receiveError() 0125 { 0126 m_timer->stop(); 0127 m_decoder->stop(); 0128 emit error(FingerprintCalculator::DecoderError); 0129 } 0130 0131 /** 0132 * Receive a timeout. 0133 */ 0134 void QtFingerprintDecoder::receiveTimeout() 0135 { 0136 m_decoder->stop(); 0137 emit error(FingerprintCalculator::Timeout); 0138 } 0139 0140 /** 0141 * Finish decoding. 0142 */ 0143 void QtFingerprintDecoder::finishDecoding() 0144 { 0145 m_timer->stop(); 0146 int duration = m_decoder->duration() / 1000LL; 0147 m_decoder->stop(); 0148 emit finished(duration); 0149 } 0150 0151 0152 /** 0153 * Create concrete fingerprint decoder. 0154 * @param parent parent object 0155 * @return fingerprint decoder instance. 0156 * @remarks This static method will be implemented by the concrete 0157 * fingerprint decoder which is used. 0158 */ 0159 AbstractFingerprintDecoder* 0160 AbstractFingerprintDecoder::createFingerprintDecoder(QObject* parent) { 0161 return new QtFingerprintDecoder(parent); 0162 }