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 }