void KeyAnalysisThread::analyzeSingleKey() { DBG("Thread: " << this->getThreadName() << " analyzing single key of: " << fileToAnalyze->getUUID()); //skip already-analyzed files if (fileToAnalyze->isFileAnalyzed() == "Yes") { DBG("Skipping analysis of " << fileToAnalyze->getFileName() << " : Already analyzed."); return; } //DBG("File being analyzed: " << fileToAnalyze.getFileToBeAnalyzed().getFileName()); // r> audioFormatReader = audioFormatManager.createReaderFor(fileToAnalyze.getFileToBeAnalyzed()); size_t numSamples = audioFormatReader->lengthInSamples; size_t numChannels = audioFormatReader->numChannels; size_t sampleRate = audioFormatReader->sampleRate; //size_t numFrames = numSamples / numChannels; //DBG("Samples:" + String(numSamples) + " Channels:" + String(numChannels) + " Frames:" + String(numFrames)); audioData.addToSampleCount(numSamples*numChannels); audioData.setChannels(numChannels); audioData.setFrameRate(sampleRate); AudioBuffer<float> audioBuffer(numChannels, numSamples); // #TODO(Casey): Fix either audiobuffer or audioData to allow direct move of sample array (Performance) // #TODO(Casey): integrate libsndfile as primary choice //DBG("Reading wav to buffer"); audioFormatReader->read(&audioBuffer, 0, numSamples, 0, true, true); //DBG("Copying buffer samples to audioData"); for (size_t i = 0; i < numSamples; ++i) { //DBG("On sample " + String(i) + " of " + String(numSamples)); for (size_t currChannel = 0; currChannel < numChannels; ++currChannel) { audioData.setSampleByFrame(i, currChannel, audioBuffer.getSample(currChannel, i)); } //audioData.setSampleByFrame(i, 1, audioBuffer.getSample(1, i)); } //DBG("Detecting key..."); static KeyFinder::KeyFinder keyFinder; KeyFinder::key_t key = keyFinder.keyOfAudio(audioData); //KeyFinder::key_t key = KeyFinder::key_t::C_MAJOR; fileToAnalyze->setDetectedKey(key); String foundKey(fileToAnalyze->getDetectedKeyAsString()); DBG("Detected key in analyzeAudioFiles: " + foundKey); }
const char* kfinder_get_key(short signed int *samples, unsigned int nb_samples, short unsigned int frame_rate, short unsigned int nb_channels) { // Check input parameter. if ((samples == NULL) || (nb_samples == 0) || (frame_rate == 0) || (nb_channels == 0)) { return ""; } // Build the main computing object. KeyFinder::KeyFinder k; // Build an empty audio object KeyFinder::AudioData a; // Prepare the object for your audio stream a.setFrameRate(frame_rate); a.setChannels(nb_channels); a.addToSampleCount(nb_samples); // Copy your audio into the object (as float). for (unsigned int i = 0; i < nb_samples; i++) { a.setSample(i, (float)samples[i]); } // Run the analysis KeyFinder::key_t r; try { r = k.keyOfAudio(a); } catch(const std::exception& e) { cerr << "libKeyFinder: exception: " << e.what() << endl; return ""; } catch(...) { cerr << "libKeyFinder: unknown exception" << endl; return ""; } // And do something with the result! switch(r) { case KeyFinder::A_MAJOR: return "AM"; case KeyFinder::A_MINOR: return "Am"; case KeyFinder::B_FLAT_MAJOR: return "BbM"; case KeyFinder::B_FLAT_MINOR: return "Bbm"; case KeyFinder::B_MAJOR: return "BM"; case KeyFinder::B_MINOR: return "Bm"; case KeyFinder::C_MAJOR: return "CM"; case KeyFinder::C_MINOR: return "Cm"; case KeyFinder::D_FLAT_MAJOR: return "DbM"; case KeyFinder::D_FLAT_MINOR: return "Dbm"; case KeyFinder::D_MAJOR: return "DM"; case KeyFinder::D_MINOR: return "Dm"; case KeyFinder::E_FLAT_MAJOR: return "EbM"; case KeyFinder::E_FLAT_MINOR: return "Ebm"; case KeyFinder::E_MAJOR: return "EM"; case KeyFinder::E_MINOR: return "Em"; case KeyFinder::F_MAJOR: return "FM"; case KeyFinder::F_MINOR: return "Fm"; case KeyFinder::G_FLAT_MAJOR: return "GbM"; case KeyFinder::G_FLAT_MINOR: return "Gbm"; case KeyFinder::G_MAJOR: return "GM"; case KeyFinder::G_MINOR: return "Gm"; case KeyFinder::A_FLAT_MAJOR: return "AbM"; case KeyFinder::A_FLAT_MINOR: return "Abm"; case KeyFinder::SILENCE: return ""; default: return ""; } }