Mercurial > hg > nnls-chroma
changeset 86:e5c16976513d consonance
implemented note output for estimated chords
author | matthiasm |
---|---|
date | Sun, 28 Nov 2010 23:10:57 +0900 |
parents | ccc0d4b3f867 |
children | f568555390f1 |
files | Chordino.cpp Chordino.h NNLSBase.cpp NNLSBase.h NNLSChroma.cpp chromamethods.cpp chromamethods.h nnls-chroma.n3 |
diffstat | 8 files changed, 101 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/Chordino.cpp Thu Nov 25 02:26:52 2010 +0900 +++ b/Chordino.cpp Sun Nov 28 23:10:57 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 Thu Nov 25 02:26:52 2010 +0900 +++ b/Chordino.h Sun Nov 28 23:10:57 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 Thu Nov 25 02:26:52 2010 +0900 +++ b/NNLSBase.cpp Sun Nov 28 23:10:57 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 Thu Nov 25 02:26:52 2010 +0900 +++ b/NNLSBase.h Sun Nov 28 23:10:57 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 Thu Nov 25 02:26:52 2010 +0900 +++ b/NNLSChroma.cpp Sun Nov 28 23:10:57 2010 +0900 @@ -430,14 +430,14 @@ consonance.values.push_back(0); for (int iSemitone = 0; iSemitone < 84-24; ++iSemitone) { - notesum += f3.values[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 * notesum); + if (notesum > 0) consonance.values[0] /= notesum; f4.values = chroma; f5.values = basschroma;
--- a/chromamethods.cpp Thu Nov 25 02:26:52 2010 +0900 +++ b/chromamethods.cpp Sun Nov 28 23:10:57 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++) { @@ -346,6 +347,7 @@ 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; } @@ -353,6 +355,7 @@ } 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()) { @@ -362,6 +365,11 @@ } // cerr << os.str() << endl; 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 +377,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 Thu Nov 25 02:26:52 2010 +0900 +++ b/chromamethods.h Sun Nov 28 23:10:57 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 Thu Nov 25 02:26:52 2010 +0900 +++ b/nnls-chroma.n3 Sun Nov 28 23:10:57 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" ;