示例#1
0
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;
}
示例#2
0
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;
}