QString chromaprinter::calcFingerPrint(SoundSourceProxy& soundSource){ soundSource.open(); m_SampleRate = soundSource.getSampleRate(); unsigned int length = soundSource.length(); if (m_SampleRate == 0 ){ qDebug() << "Skipping invalid file:" << soundSource.getFilename(); return QString(); } // this is worth 2min of audio, multiply by 2 because we have 2 channels // AcoustID only stores a fingerprint for the first two minutes of a song // on their server so we need only a fingerprint of the first two minutes // --kain88 July 2012 m_NumSamples = 120*2*m_SampleRate; // check that the song is actually longer then the amount of audio we use if (m_NumSamples > length) { m_NumSamples = length; } SAMPLE *pData = new SAMPLE[m_NumSamples]; QTime timerReadingFile; timerReadingFile.start(); unsigned int read = soundSource.read(m_NumSamples, pData); if (read!=m_NumSamples) { qDebug() << "oh that's embarrasing I couldn't read the track"; return QString(); } qDebug("reading file took: %d ms" , timerReadingFile.elapsed()); ChromaprintContext* ctx = chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT); // we have 2 channels in mixxx always chromaprint_start(ctx, m_SampleRate, 2); QTime timerGeneratingFingerPrint; timerGeneratingFingerPrint.start(); int success = chromaprint_feed(ctx, pData, m_NumSamples); if (!success) { qDebug() << "could not generate fingerprint"; delete [] pData; return QString(); } chromaprint_finish(ctx); void* fprint = NULL; int size = 0; int ret = chromaprint_get_raw_fingerprint(ctx, &fprint, &size); QByteArray fingerprint; if (ret == 1) { void* encoded = NULL; int encoded_size = 0; chromaprint_encode_fingerprint(fprint, size, CHROMAPRINT_ALGORITHM_DEFAULT, &encoded, &encoded_size, 1); fingerprint.append(reinterpret_cast<char*>(encoded), encoded_size); chromaprint_dealloc(fprint); chromaprint_dealloc(encoded); } chromaprint_free(ctx); delete [] pData; qDebug("generating fingerprint took: %d ms" , timerGeneratingFingerPrint.elapsed()); return fingerprint; }
void AnalyserQueue::run() { unsigned static id = 0; //the id of this thread, for debugging purposes QThread::currentThread()->setObjectName(QString("AnalyserQueue %1").arg(++id)); // If there are no analyzers, don't waste time running. if (m_aq.size() == 0) return; m_progressInfo.current_track = TrackPointer(); m_progressInfo.track_progress = 0; m_progressInfo.queue_size = 0; m_progressInfo.sema.release(); // Initalise with one while (!m_exit) { TrackPointer nextTrack = dequeueNextBlocking(); // It's important to check for m_exit here in case we decided to exit // while blocking for a new track. if (m_exit) return; // If the track is NULL, try to get the next one. // Could happen if the track was queued but then deleted. // Or if dequeueNextBlocking is unblocked by exit == true if (!nextTrack) { continue; } // Get the audio SoundSourceProxy* pSoundSource = new SoundSourceProxy(nextTrack); pSoundSource->open(); //Open the file for reading int iNumSamples = pSoundSource->length(); int iSampleRate = pSoundSource->getSampleRate(); if (iNumSamples == 0 || iSampleRate == 0) { qDebug() << "Skipping invalid file:" << nextTrack->getLocation(); continue; } QListIterator<Analyser*> it(m_aq); bool processTrack = false; while (it.hasNext()) { // Make sure not to short-circuit initialise(...) if (it.next()->initialise(nextTrack, iSampleRate, iNumSamples)) { processTrack = true; } } m_qm.lock(); m_queue_size = m_tioq.size(); m_qm.unlock(); if (processTrack) { emitUpdateProgress(nextTrack, 0); bool completed = doAnalysis(nextTrack, pSoundSource); if (!completed) { //This track was cancelled QListIterator<Analyser*> itf(m_aq); while (itf.hasNext()) { itf.next()->cleanup(nextTrack); } queueAnalyseTrack(nextTrack); emitUpdateProgress(nextTrack, 0); } else { // 100% - FINALIZE_PERCENT finished emitUpdateProgress(nextTrack, 1000 - FINALIZE_PERCENT); // This takes around 3 sec on a Atom Netbook QListIterator<Analyser*> itf(m_aq); while (itf.hasNext()) { itf.next()->finalise(nextTrack); } emit(trackDone(nextTrack)); emitUpdateProgress(nextTrack, 1000); // 100% } } else { emitUpdateProgress(nextTrack, 1000); // 100% qDebug() << "Skipping track analysis because no analyzer initialized."; } delete pSoundSource; m_qm.lock(); m_queue_size = m_tioq.size(); m_qm.unlock(); if (m_queue_size == 0) { emit(queueEmpty()); // emit asynchrony for no deadlock } } emit(queueEmpty()); // emit in case of exit; }