Mercurial > hg > nnls-chroma
changeset 88:fc28c50caace matthiasm-plugin
merge
author | Matthias Mauch <mail@matthiasmauch.net> |
---|---|
date | Wed, 01 Dec 2010 21:18:49 +0900 |
parents | e8ceb7d3bd4f (current diff) f568555390f1 (diff) |
children | 7af5312e66f8 |
files | |
diffstat | 9 files changed, 143 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/Chordino.cpp Mon Nov 15 11:01:56 2010 +0900 +++ b/Chordino.cpp Wed Dec 01 21:18:49 2010 +0900 @@ -30,9 +30,15 @@ const bool debug_on = false; Chordino::Chordino(float inputSampleRate) : - NNLSBase(inputSampleRate) + NNLSBase(inputSampleRate), + m_chorddict(0), + m_chordnotes(0), + m_chordnames(0) { if (debug_on) cerr << "--> Chordino" << endl; + // get the *chord* dictionary from file (if the file exists) + m_chordnames = chordDictionary(&m_chorddict, &m_chordnotes); + } Chordino::~Chordino() @@ -182,6 +188,24 @@ list.push_back(d7); m_outputChords = index++; + OutputDescriptor chordnotes; + chordnotes.identifier = "chordnotes"; + chordnotes.name = "Note Representation of Chord Estimate"; + chordnotes.description = "A simple represenation of the estimated chord with bass note (if applicable) and chord notes."; + chordnotes.unit = "MIDI units"; + chordnotes.hasFixedBinCount = true; + chordnotes.binCount = 1; + chordnotes.hasKnownExtents = true; + chordnotes.minValue = 0; + chordnotes.maxValue = 127; + chordnotes.isQuantized = true; + chordnotes.quantizeStep = 1; + chordnotes.sampleType = OutputDescriptor::VariableSampleRate; + chordnotes.hasDuration = true; + chordnotes.sampleRate = (m_stepSize == 0) ? m_inputSampleRate/2048 : m_inputSampleRate/m_stepSize; + list.push_back(chordnotes); + m_outputChordnotes = index++; + OutputDescriptor d8; d8.identifier = "harmonicchange"; d8.name = "Harmonic Change Value"; @@ -488,6 +512,7 @@ } cerr << "done." << endl; + vector<Feature> oldnotes; // bool m_useHMM = true; // this will go into the chordino header file. if (m_useHMM == 1.0) { @@ -520,12 +545,28 @@ for (int iFrame = 1; iFrame < chordpath.size(); ++iFrame) { // cerr << chordpath[iFrame] << endl; if (chordpath[iFrame] != oldchord ) { + // chord Feature chord_feature; // chord estimate chord_feature.hasTimestamp = true; chord_feature.timestamp = timestamps[iFrame]; chord_feature.label = m_chordnames[chordpath[iFrame]]; fsOut[m_outputChords].push_back(chord_feature); oldchord = chordpath[iFrame]; + // chord notes + for (int iNote = 0; iNote < oldnotes.size(); ++iNote) { // finish duration of old chord + oldnotes[iNote].duration = oldnotes[iNote].duration + timestamps[iFrame]; + fsOut[m_outputChordnotes].push_back(oldnotes[iNote]); + } + oldnotes.clear(); + for (int iNote = 0; iNote < m_chordnotes[chordpath[iFrame]].size(); ++iNote) { // prepare notes of current chord + Feature chordnote_feature; + chordnote_feature.hasTimestamp = true; + chordnote_feature.timestamp = timestamps[iFrame]; + chordnote_feature.values.push_back(m_chordnotes[chordpath[iFrame]][iNote]); + chordnote_feature.hasDuration = true; + chordnote_feature.duration = -timestamps[iFrame]; // this will be corrected at the next chord + oldnotes.push_back(chordnote_feature); + } } /* calculating simple chord change prob */ for (int iChord = 0; iChord < nChord; iChord++) { @@ -678,6 +719,20 @@ oldChord = maxChord; chord_feature.label = m_chordnames[maxChordIndex]; fsOut[m_outputChords].push_back(chord_feature); + for (int iNote = 0; iNote < oldnotes.size(); ++iNote) { // finish duration of old chord + oldnotes[iNote].duration = oldnotes[iNote].duration + chord_feature.timestamp; + fsOut[m_outputChordnotes].push_back(oldnotes[iNote]); + } + oldnotes.clear(); + for (int iNote = 0; iNote < m_chordnotes[maxChordIndex].size(); ++iNote) { // prepare notes of current chord + Feature chordnote_feature; + chordnote_feature.hasTimestamp = true; + chordnote_feature.timestamp = chord_feature.timestamp; + chordnote_feature.values.push_back(m_chordnotes[maxChordIndex][iNote]); + chordnote_feature.hasDuration = true; + chordnote_feature.duration = -chord_feature.timestamp; // this will be corrected at the next chord + oldnotes.push_back(chordnote_feature); + } } count++; } @@ -687,6 +742,12 @@ chord_feature.timestamp = timestamps[timestamps.size()-1]; chord_feature.label = "N"; fsOut[m_outputChords].push_back(chord_feature); + + for (int iNote = 0; iNote < oldnotes.size(); ++iNote) { // finish duration of old chord + oldnotes[iNote].duration = oldnotes[iNote].duration + timestamps[timestamps.size()-1]; + fsOut[m_outputChordnotes].push_back(oldnotes[iNote]); + } + cerr << "done." << endl; for (int iFrame = 0; iFrame < nFrame; iFrame++) {
--- a/Chordino.h Mon Nov 15 11:01:56 2010 +0900 +++ b/Chordino.h Wed Dec 01 21:18:49 2010 +0900 @@ -46,7 +46,11 @@ protected: mutable int m_outputChords; + mutable int m_outputChordnotes; mutable int m_outputHarmonicChange; + vector<float> m_chorddict; + vector<vector<int> > m_chordnotes; + vector<string> m_chordnames; };
--- a/NNLSBase.cpp Mon Nov 15 11:01:56 2010 +0900 +++ b/NNLSBase.cpp Wed Dec 01 21:18:49 2010 +0900 @@ -44,8 +44,6 @@ m_kernelNoteIndex(0), m_dict(0), m_tuneLocal(0), - m_chorddict(0), - m_chordnames(0), m_doNormalizeChroma(0), m_rollon(0), m_s(0.7), @@ -60,9 +58,6 @@ m_dict = new float[nNote * 84]; for (unsigned i = 0; i < nNote * 84; ++i) m_dict[i] = 0.0; dictionaryMatrix(m_dict, 0.7); - - // get the *chord* dictionary from file (if the file exists) - m_chordnames = chordDictionary(&m_chorddict); }
--- a/NNLSBase.h Mon Nov 15 11:01:56 2010 +0900 +++ b/NNLSBase.h Wed Dec 01 21:18:49 2010 +0900 @@ -73,8 +73,6 @@ vector<int> m_kernelNoteIndex; float *m_dict; bool m_tuneLocal; - vector<float> m_chorddict; - vector<string> m_chordnames; float m_doNormalizeChroma; float m_rollon; vector<float> hw;
--- a/NNLSChroma.cpp Mon Nov 15 11:01:56 2010 +0900 +++ b/NNLSChroma.cpp Wed Dec 01 21:18:49 2010 +0900 @@ -171,6 +171,21 @@ list.push_back(d6); m_outputBothChroma = index++; + OutputDescriptor d7; + d7.identifier = "consonance"; + d7.name = "Consonance estimate."; + d7.description = "A simple consonance value based on the convolution of a consonance profile with the semitone spectrum."; + d7.unit = ""; + d7.hasFixedBinCount = true; + d7.binCount = 1; + d7.hasKnownExtents = false; + d7.isQuantized = false; + d7.sampleType = OutputDescriptor::FixedSampleRate; + d7.hasDuration = false; + d7.sampleRate = (m_stepSize == 0) ? m_inputSampleRate/2048 : m_inputSampleRate/m_stepSize; + list.push_back(d7); + m_outputConsonance = index++; + return list; } @@ -211,6 +226,9 @@ NNLSChroma::FeatureSet NNLSChroma::getRemainingFeatures() { + + float consonancepattern[24] = {0,-1,-1,1,1,1,-1,1,1,1,-1,-1,1,-1,-1,1,1,1,-1,1,1,1,-1,-1}; + for (int i = 0; i< 12; ++i) cerr << consonancepattern[i]<< endl; if (debug_on) cerr << "--> getRemainingFeatures" << endl; FeatureSet fsOut; if (m_logSpectrum.size() == 0) return fsOut; @@ -256,6 +274,7 @@ f2.timestamp = f1.timestamp; f2.values.push_back(0.0); f2.values.push_back(0.0); // set lower edge to zero + if (m_tuneLocal) { intShift = floor(m_localTuning[count] * 3); floatShift = m_localTuning[count] * 3 - intShift; // floatShift is a really bad name for this @@ -316,7 +335,8 @@ Feature f4; // treble chromagram Feature f5; // bass chromagram Feature f6; // treble and bass chromagram - + Feature consonance; + f3.hasTimestamp = true; f3.timestamp = f2.timestamp; @@ -329,6 +349,9 @@ f6.hasTimestamp = true; f6.timestamp = f2.timestamp; + consonance.hasTimestamp = true; + consonance.timestamp = f2.timestamp; + float b[nNote]; bool some_b_greater_zero = false; @@ -402,7 +425,20 @@ } else { for (int i = 0; i < 84; ++i) f3.values.push_back(0); } - + + float notesum = 0; + + consonance.values.push_back(0); + for (int iSemitone = 0; iSemitone < 84-24; ++iSemitone) { + notesum += f3.values[iSemitone] * f3.values[iSemitone]; + float tempconsonance = 0; + for (int jSemitone = 1; jSemitone < 24; ++jSemitone) { + tempconsonance += f3.values[iSemitone+jSemitone] * (consonancepattern[jSemitone]); + } + consonance.values[0] += (f3.values[iSemitone] * tempconsonance); + } + if (notesum > 0) consonance.values[0] /= notesum; + f4.values = chroma; f5.values = basschroma; chroma.insert(chroma.begin(), basschroma.begin(), basschroma.end()); // just stack the both chromas @@ -465,6 +501,7 @@ fsOut[m_outputChroma].push_back(f4); fsOut[m_outputBassChroma].push_back(f5); fsOut[m_outputBothChroma].push_back(f6); + fsOut[m_outputConsonance].push_back(consonance); count++; } cerr << "done." << endl;
--- a/NNLSChroma.h Mon Nov 15 11:01:56 2010 +0900 +++ b/NNLSChroma.h Wed Dec 01 21:18:49 2010 +0900 @@ -50,6 +50,7 @@ mutable int m_outputChroma; mutable int m_outputBassChroma; mutable int m_outputBothChroma; + mutable int m_outputConsonance; };
--- a/chromamethods.cpp Mon Nov 15 11:01:56 2010 +0900 +++ b/chromamethods.cpp Wed Dec 01 21:18:49 2010 +0900 @@ -277,8 +277,8 @@ return path; } -vector<string> chordDictionary(vector<float> *mchorddict) { - +vector<string> chordDictionary(vector<float> *mchorddict, vector<vector<int> > *m_chordnotes) { + typedef tokenizer<char_separator<char> > Tok; char_separator<char> sep(",; ","="); @@ -310,7 +310,7 @@ vector<string> loadedChordNames; vector<float> loadedChordDict; if (chordDictFile.is_open()) { - while (std::getline(chordDictFile, line)) { // loop over lines in chord.dict file + while (std::getline(chordDictFile, line)) { // loop over lines in chord.dict file // first, get the chord definition string chordType; vector<float> tempPCVector; @@ -333,7 +333,8 @@ } // now make all 12 chords of every type - for (unsigned iSemitone = 0; iSemitone < 12; iSemitone++) { + for (unsigned iSemitone = 0; iSemitone < 12; iSemitone++) { + vector<int> tempchordnotes; // add bass slash notation string slashNotation = ""; for (unsigned kSemitone = 1; kSemitone < 12; kSemitone++) { @@ -341,18 +342,21 @@ slashNotation = bassnames[iSemitone][kSemitone]; } } + if (slashNotation=="") tempchordnotes.push_back(MIDI_basenote + (iSemitone+12) % 12); for (unsigned kSemitone = 0; kSemitone < 12; kSemitone++) { // bass pitch classes // cerr << ((kSemitone - iSemitone + 12) % 12) << endl; float bassValue = 0; if (tempPCVector[(kSemitone - iSemitone + 12) % 12]==1) { bassValue = 1; + tempchordnotes.push_back(MIDI_basenote + (kSemitone+12) % 12); } else { if (tempPCVector[((kSemitone - iSemitone + 12) % 12) + 12] == 1) bassValue = 0.5; } - loadedChordDict.push_back(bassValue); + loadedChordDict.push_back(bassValue); } for (unsigned kSemitone = 0; kSemitone < 12; kSemitone++) { // chord pitch classes loadedChordDict.push_back(tempPCVector[((kSemitone - iSemitone + 12) % 12) + 12]); + if (tempPCVector[((kSemitone - iSemitone + 12) % 12) + 12] > 0) tempchordnotes.push_back(MIDI_basenote + (kSemitone+12+6) % 12 - 6 + 24); } ostringstream os; if (slashNotation.empty()) { @@ -361,7 +365,13 @@ os << notenames[12+iSemitone] << chordType << "/" << slashNotation; } // cerr << os.str() << endl; - loadedChordNames.push_back(os.str()); + loadedChordNames.push_back(os.str()); + + m_chordnotes->push_back(tempchordnotes); + for (int iNote = 0; iNote < tempchordnotes.size(); ++iNote) { + cerr << tempchordnotes[iNote] << " "; + } + cerr << endl; } } } @@ -369,7 +379,8 @@ loadedChordNames.push_back("N"); for (unsigned kSemitone = 0; kSemitone < 12; kSemitone++) loadedChordDict.push_back(0.5); for (unsigned kSemitone = 0; kSemitone < 12; kSemitone++) loadedChordDict.push_back(1.0); - + vector<int> tempchordvector; + m_chordnotes->push_back(tempchordvector); float exponent = 2.0; float boostN = 1.1;
--- a/chromamethods.h Mon Nov 15 11:01:56 2010 +0900 +++ b/chromamethods.h Wed Dec 01 21:18:49 2010 +0900 @@ -22,13 +22,14 @@ #include <vector> #include <string> -const int nBPS = 5; // bins per semitone +const int nBPS = 3; // bins per semitone const int nOctave = 7; const int nNote = nOctave * 12 * nBPS + 2 * (nBPS/2+1); // a core over all octaves, plus some overlap at top and bottom +const int MIDI_basenote = 45; extern std::vector<float> SpecialConvolution(std::vector<float> convolvee, std::vector<float> kernel); extern void dictionaryMatrix(float* dm, float s_param); -extern std::vector<std::string> chordDictionary(std::vector<float> *mchorddict); +extern std::vector<std::string> chordDictionary(std::vector<float> *mchorddict, std::vector<std::vector<int> > *m_chordnotes); extern bool logFreqMatrix(int fs, int blocksize, float *outmatrix); static const char* notenames[24] = {
--- a/nnls-chroma.n3 Mon Nov 15 11:01:56 2010 +0900 +++ b/nnls-chroma.n3 Wed Dec 01 21:18:49 2010 +0900 @@ -44,6 +44,7 @@ vamp:parameter plugbase:chordino_param_s ; vamp:output plugbase:chordino_output_simplechord ; + vamp:output plugbase:chordino_output_chordnotes ; vamp:output plugbase:chordino_output_harmonicchange ; . plugbase:chordino_param_useNNLS a vamp:QuantizedParameter ; @@ -122,6 +123,21 @@ vamp:sample_type vamp:VariableSampleRate ; vamp:sample_rate 21.5332 ; vamp:computes_event_type af:ChordSegment ; + +plugbase:chordino_output_chordnotes a vamp:SparseOutput ; + vamp:identifier "chordnotes" ; + dc:title "Note Representation of Chord Estimate" ; + dc:description """A simple represenation of the estimated chord with bass note (if applicable) and chord notes.""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "MIDI units" ; + a vamp:QuantizedOutput ; + vamp:quantize_step 1 ; + a vamp:KnownExtentsOutput ; + vamp:min_value 0 ; + vamp:max_value 127 ; + vamp:bin_count 1 ; + vamp:sample_type vamp:VariableSampleRate ; + vamp:computes_event_type af:Note ; . plugbase:chordino_output_harmonicchange a vamp:DenseOutput ; vamp:identifier "harmonicchange" ;