File indexing completed on 2024-05-12 04:55:35
0001 /** 0002 * \file fingerprintcalculator.cpp 0003 * Chromaprint fingerprint calculator. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 21 Jan 2012 0008 * 0009 * Copyright (C) 2012-2018 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 #define __STDC_CONSTANT_MACROS 0028 #include "fingerprintcalculator.h" 0029 #include "config.h" 0030 #include "abstractfingerprintdecoder.h" 0031 0032 /** 0033 * Constructor. 0034 */ 0035 FingerprintCalculator::FingerprintCalculator(QObject* parent) : QObject(parent), 0036 m_chromaprintCtx(nullptr), 0037 m_decoder(AbstractFingerprintDecoder::createFingerprintDecoder(this)) 0038 { 0039 connect(m_decoder, &AbstractFingerprintDecoder::started, 0040 this, &FingerprintCalculator::startChromaprint); 0041 connect(m_decoder, &AbstractFingerprintDecoder::bufferReady, 0042 this, &FingerprintCalculator::feedChromaprint); 0043 connect(m_decoder, &AbstractFingerprintDecoder::error, 0044 this, &FingerprintCalculator::receiveError); 0045 connect(m_decoder, &AbstractFingerprintDecoder::finished, 0046 this, &FingerprintCalculator::finishChromaprint); 0047 } 0048 0049 /** 0050 * Destructor. 0051 */ 0052 FingerprintCalculator::~FingerprintCalculator() 0053 { 0054 if (m_chromaprintCtx) { 0055 ::chromaprint_free(m_chromaprintCtx); 0056 } 0057 } 0058 0059 /** 0060 * Calculate audio fingerprint for audio file. 0061 * When the calculation is finished, finished() is emitted. 0062 * 0063 * @param fileName path to audio file 0064 */ 0065 void FingerprintCalculator::start(const QString& fileName) { 0066 if (!m_chromaprintCtx) { 0067 // Lazy initialization to save resources if not used 0068 m_chromaprintCtx = ::chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT); 0069 } 0070 m_decoder->start(fileName); 0071 } 0072 0073 /** 0074 * Stop decoder. 0075 */ 0076 void FingerprintCalculator::stop() { 0077 m_decoder->stop(); 0078 } 0079 0080 /** 0081 * Called when decoding starts. 0082 * @param sampleRate sample rate of the audio stream (in Hz) 0083 * @param channelCount numbers of channels in the audio stream (1 or 2) 0084 */ 0085 void FingerprintCalculator::startChromaprint(int sampleRate, int channelCount) 0086 { 0087 ::chromaprint_start(m_chromaprintCtx, sampleRate, channelCount); 0088 } 0089 0090 /** 0091 * Called when decoded data is available. 0092 * @param data 16-bit signed integers in native byte-order 0093 */ 0094 void FingerprintCalculator::feedChromaprint(QByteArray data) 0095 { 0096 if (!::chromaprint_feed(m_chromaprintCtx, 0097 reinterpret_cast<qint16*>(data.data()), 0098 data.size() / 2)) { 0099 m_decoder->stop(); 0100 emit finished(QString(), 0, FingerprintCalculationFailed); 0101 } 0102 } 0103 0104 /** 0105 * Called when an error occurs. 0106 * @param err error code, enum FingerprintCalculator::Error 0107 */ 0108 void FingerprintCalculator::receiveError(int err) 0109 { 0110 emit finished(QString(), 0, err); 0111 } 0112 0113 /** 0114 * Called when decoding finished successfully. 0115 * @param duration duration of stream in seconds 0116 */ 0117 void FingerprintCalculator::finishChromaprint(int duration) 0118 { 0119 int err = Ok; 0120 QString fingerprint; 0121 char* fp; 0122 if (::chromaprint_finish(m_chromaprintCtx) && 0123 ::chromaprint_get_fingerprint(m_chromaprintCtx, &fp)) { 0124 fingerprint = QString::fromLatin1(fp); 0125 ::chromaprint_dealloc(fp); 0126 } else { 0127 err = FingerprintCalculationFailed; 0128 } 0129 emit finished(fingerprint, duration, err); 0130 }