MCPcopy Create free account
hub / github.com/StrangeLoopsAudio/gRainbow / process

Method process

Source/DSP/HPCP.cpp:17–68  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

15}
16
17Utils::SpecBuffer* HPCP::process(Utils::SpecBuffer* spec, double sampleRate) {
18 if (!spec) return nullptr;
19 mHPCP.clear();
20 mSampleRate = sampleRate;
21
22 for (size_t frame = 0; frame < spec->size(); ++frame) {
23// updateProgress(mStartProgress + (mDiffProgress * (static_cast<double>(frame) / static_cast<double>(spec->size()))));
24 mHPCP.emplace_back(std::vector<float>(NUM_HPCP_BINS, 0.0f));
25
26 std::vector<float>& specFrame = (*spec)[frame];
27
28 // Find local peaks to compute HPCP with
29 std::vector<Peak> peaks = getPeaks(MAX_SPEC_PEAKS, specFrame);
30
31 float curMax = 0.0;
32 for (size_t i = 0; i < peaks.size(); ++i) {
33 float peakFreq = ((peaks[i].binNum / (specFrame.size() - 1)) * mSampleRate) / 2;
34 if (peakFreq < MIN_FREQ || peakFreq > MAX_FREQ) continue;
35
36 // Create sum for each pitch class
37 for (int pc = 0; pc < NUM_HPCP_BINS; ++pc) {
38 int pcIdx = (pc + PITCH_CLASS_OFFSET_BINS) % NUM_HPCP_BINS;
39 float centerFreq = REF_FREQ * std::pow(2.0f, pc / (float)NUM_HPCP_BINS);
40
41 // Add contribution from each harmonic
42 for (size_t hIdx = 0; hIdx < mHarmonicWeights.size(); ++hIdx) {
43 float freq = peakFreq * pow(2., -mHarmonicWeights[hIdx].semitone / 12.0);
44 float harmonicWeight = mHarmonicWeights[hIdx].gain;
45 float d = std::fmod(12.0f * std::log2(freq / centerFreq), 12.0f);
46 if (std::abs(d) <= (0.5f * HPCP_WINDOW_LEN)) {
47 float w = std::pow(std::cos((juce::MathConstants<float>::pi * d) / HPCP_WINDOW_LEN), 2.0f);
48 mHPCP[frame][pcIdx] += (w * std::pow(peaks[i].gain, 2) * harmonicWeight * harmonicWeight);
49 if (mHPCP[frame][pcIdx] > curMax) curMax = mHPCP[frame][pcIdx];
50 }
51 }
52 }
53 }
54
55 // Normalize HPCP frame and clear low energy frames
56 float totalEnergy = 0.0f;
57 if (curMax > 0.0f) {
58 for (int pc = 0; pc < NUM_HPCP_BINS; ++pc) {
59 totalEnergy += mHPCP[frame][pc];
60 mHPCP[frame][pc] /= curMax;
61 }
62 }
63 if (totalEnergy / NUM_HPCP_BINS < MIN_AVG_FRAME_ENERGY) {
64 std::fill(mHPCP[frame].begin(), mHPCP[frame].end(), 0.0f);
65 }
66 }
67 return &mHPCP;
68}
69
70// From essentia:
71// Builds a weighting table of harmonic contribution. Higher harmonics

Callers

nothing calls this directly

Calls 1

clearMethod · 0.45

Tested by

no test coverage detected