annotate src/Chromagram.cpp @ 196:da283326bcd3 tip master

Update plugin versions in RDF
author Chris Cannam <cannam@all-day-breakfast.com>
date Fri, 28 Feb 2020 09:43:02 +0000
parents 6e4de8beb6b2
children
rev   line source
c@170 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@170 2 /*
c@170 3 Constant-Q library
c@170 4 Copyright (c) 2013-2015 Queen Mary, University of London
c@170 5
c@170 6 Permission is hereby granted, free of charge, to any person
c@170 7 obtaining a copy of this software and associated documentation
c@170 8 files (the "Software"), to deal in the Software without
c@170 9 restriction, including without limitation the rights to use, copy,
c@170 10 modify, merge, publish, distribute, sublicense, and/or sell copies
c@170 11 of the Software, and to permit persons to whom the Software is
c@170 12 furnished to do so, subject to the following conditions:
c@170 13
c@170 14 The above copyright notice and this permission notice shall be
c@170 15 included in all copies or substantial portions of the Software.
c@170 16
c@170 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
c@170 18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
c@170 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
c@170 20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
c@170 21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
c@170 22 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
c@170 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
c@170 24
c@170 25 Except as contained in this notice, the names of the Centre for
c@170 26 Digital Music; Queen Mary, University of London; and Chris Cannam
c@170 27 shall not be used in advertising or otherwise to promote the sale,
c@170 28 use or other dealings in this Software without prior written
c@170 29 authorization.
c@170 30 */
c@170 31
c@170 32 #include "Chromagram.h"
c@170 33 #include "CQSpectrogram.h"
c@170 34 #include "Pitch.h"
c@170 35
c@170 36 #include <cstdio>
c@170 37
c@170 38 using namespace std;
c@170 39
c@170 40 Chromagram::Chromagram(Parameters params) :
c@170 41 m_params(params),
c@170 42 m_cq(0)
c@170 43 {
c@171 44 int highestOctave = m_params.lowestOctave + m_params.octaveCount - 1;
c@170 45
c@170 46 int midiPitchLimit = (1 + highestOctave) * 12 + 12; // C just beyond top
c@170 47 double midiPitchLimitFreq = Pitch::getFrequencyForPitch
c@170 48 (midiPitchLimit, 0, m_params.tuningFrequency);
c@170 49
c@170 50 // Max frequency is frequency of the MIDI pitch just beyond the
c@170 51 // top octave range (midiPitchLimit) minus one bin, then minus
c@170 52 // floor(bins per semitone / 2)
c@171 53 int bps = m_params.binsPerOctave / 12;
c@170 54 m_maxFrequency = midiPitchLimitFreq /
c@180 55 pow(2.0, (1.0 + floor(bps/2)) / m_params.binsPerOctave);
c@170 56
c@170 57 // Min frequency is frequency of midiPitchLimit lowered by the
c@171 58 // appropriate number of octaveCount.
c@170 59 m_minFrequency = midiPitchLimitFreq /
c@180 60 pow(2.0, m_params.octaveCount + 1);
c@170 61
c@170 62 CQParameters p
c@171 63 (params.sampleRate, m_minFrequency, m_maxFrequency, params.binsPerOctave);
c@171 64
c@171 65 p.q = params.q;
c@171 66 p.atomHopFactor = params.atomHopFactor;
c@171 67 p.threshold = params.threshold;
c@171 68 p.window = params.window;
c@170 69
c@170 70 m_cq = new CQSpectrogram(p, CQSpectrogram::InterpolateLinear);
c@170 71 }
c@170 72
c@170 73 Chromagram::~Chromagram()
c@170 74 {
c@170 75 delete m_cq;
c@170 76 }
c@170 77
c@170 78 bool
c@170 79 Chromagram::isValid() const
c@170 80 {
c@170 81 return m_cq->isValid();
c@170 82 }
c@170 83
c@170 84 int
c@170 85 Chromagram::getColumnHop() const
c@170 86 {
c@170 87 return m_cq->getColumnHop();
c@170 88 }
c@170 89
c@170 90 int
c@170 91 Chromagram::getLatency() const
c@170 92 {
c@170 93 return m_cq->getLatency();
c@170 94 }
c@170 95
c@170 96 string
c@170 97 Chromagram::getBinName(int bin) const
c@170 98 {
c@170 99 static const char *names[] = {
c@170 100 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
c@170 101 };
c@170 102
c@171 103 float freq = m_cq->getBinFrequency(m_params.binsPerOctave - bin - 1);
c@170 104 int note = Pitch::getPitchForFrequency(freq, 0, m_params.tuningFrequency);
c@170 105 float nearestFreq =
c@170 106 Pitch::getFrequencyForPitch(note, 0, m_params.tuningFrequency);
c@170 107
c@170 108 char name[40];
c@170 109 sprintf(name, "%d", bin);
c@170 110 if (fabs(freq - nearestFreq) < 0.01) {
c@170 111 return (name + std::string(" ") + names[note % 12]);
c@170 112 } else {
c@170 113 return (name);
c@170 114 }
c@170 115 }
c@170 116
c@170 117 CQBase::RealBlock
c@170 118 Chromagram::process(const CQBase::RealSequence &data)
c@170 119 {
c@170 120 return convert(m_cq->process(data));
c@170 121 }
c@170 122
c@170 123 CQBase::RealBlock
c@170 124 Chromagram::getRemainingOutput()
c@170 125 {
c@170 126 return convert(m_cq->getRemainingOutput());
c@170 127 }
c@170 128
c@170 129 CQBase::RealBlock
c@170 130 Chromagram::convert(const CQBase::RealBlock &cqout)
c@170 131 {
c@170 132 CQBase::RealBlock chroma;
c@170 133
c@170 134 int width = cqout.size();
c@170 135
c@170 136 for (int i = 0; i < width; ++i) {
c@170 137
c@171 138 CQBase::RealSequence column(m_params.binsPerOctave, 0.);
c@170 139
c@170 140 // fold and invert to put low frequencies at the start
c@170 141
c@170 142 int thisHeight = cqout[i].size();
c@170 143
c@170 144 for (int j = 0; j < thisHeight; ++j) {
c@171 145 column[m_params.binsPerOctave - (j % m_params.binsPerOctave) - 1]
c@171 146 += cqout[i][j];
c@170 147 }
c@170 148
c@170 149 chroma.push_back(column);
c@170 150 }
c@170 151
c@170 152 return chroma;
c@170 153 }
c@170 154