Mercurial > hg > silvet
diff src/Silvet.cpp @ 267:a8c05709e486
Merge from branch "norm"
author | Chris Cannam |
---|---|
date | Wed, 23 Jul 2014 17:51:58 +0100 |
parents | 34e69544691b |
children | 10d8bd634a77 |
line wrap: on
line diff
--- a/src/Silvet.cpp Tue Jul 22 18:32:00 2014 +0100 +++ b/src/Silvet.cpp Wed Jul 23 17:51:58 2014 +0100 @@ -20,6 +20,7 @@ #include "MedianFilter.h" #include "constant-q-cpp/src/dsp/Resampler.h" +#include "flattendynamics-ladspa.h" #include <vector> @@ -38,6 +39,7 @@ Plugin(inputSampleRate), m_instruments(InstrumentPack::listInstrumentPacks()), m_resampler(0), + m_flattener(0), m_cq(0), m_hqMode(true), m_fineTuning(false), @@ -49,6 +51,7 @@ Silvet::~Silvet() { delete m_resampler; + delete m_flattener; delete m_cq; for (int i = 0; i < (int)m_postFilter.size(); ++i) { delete m_postFilter[i]; @@ -230,7 +233,7 @@ d.hasKnownExtents = false; d.isQuantized = false; d.sampleType = OutputDescriptor::VariableSampleRate; - d.sampleRate = m_inputSampleRate / (m_cq ? m_cq->getColumnHop() : 62); + d.sampleRate = processingSampleRate / (m_cq ? m_cq->getColumnHop() : 62); d.hasDuration = true; m_notesOutputNo = list.size(); list.push_back(d); @@ -346,6 +349,7 @@ Silvet::reset() { delete m_resampler; + delete m_flattener; delete m_cq; if (m_inputSampleRate != processingSampleRate) { @@ -354,6 +358,9 @@ m_resampler = 0; } + m_flattener = new FlattenDynamics(m_inputSampleRate); // before resampling + m_flattener->reset(); + double minFreq = 27.5; if (!m_hqMode) { @@ -388,6 +395,7 @@ m_postFilter.push_back(new MedianFilter<double>(3)); } m_pianoRoll.clear(); + m_inputGains.clear(); m_columnCount = 0; m_startTime = RealTime::zeroTime; } @@ -398,16 +406,29 @@ if (m_columnCount == 0) { m_startTime = timestamp; } + + vector<float> flattened(m_blockSize); + float gain = 1.f; + m_flattener->connectInputPort + (FlattenDynamics::AudioInputPort, inputBuffers[0]); + m_flattener->connectOutputPort + (FlattenDynamics::AudioOutputPort, &flattened[0]); + m_flattener->connectOutputPort + (FlattenDynamics::GainOutputPort, &gain); + m_flattener->process(m_blockSize); + + m_inputGains[timestamp] = gain; vector<double> data; for (int i = 0; i < m_blockSize; ++i) { - data.push_back(inputBuffers[0][i]); + double d = flattened[i]; + data.push_back(d); } if (m_resampler) { data = m_resampler->process(data.data(), data.size()); } - + Grid cqout = m_cq->process(data); FeatureSet fs = transcribe(cqout); return fs; @@ -733,13 +754,7 @@ int partShift = 0; int partVelocity = 0; - Feature f; - f.hasTimestamp = true; - f.hasDuration = true; - - double columnDuration = 1.0 / m_colsPerSec; - int postFilterLatency = int(m_postFilter[0]->getSize() / 2); - int partThreshold = floor(0.05 / columnDuration); + int partThreshold = floor(0.05 * m_colsPerSec); for (int i = start; i != end; ++i) { @@ -760,40 +775,87 @@ // cerr << "i = " << i << ", partStart = " << partStart << ", shift = " << shift << ", partShift = " << partShift << endl; // pitch has changed, emit an intermediate note - f.timestamp = RealTime::fromSeconds - (columnDuration * (partStart - postFilterLatency) + 0.02); - f.duration = RealTime::fromSeconds - (columnDuration * (i - partStart)); - f.values.clear(); - f.values.push_back - (noteFrequency(note, partShift, shiftCount)); - f.values.push_back(partVelocity); - f.label = noteName(note, partShift, shiftCount); - noteFeatures.push_back(f); + noteFeatures.push_back(makeNoteFeature(partStart, + i, + note, + partShift, + shiftCount, + partVelocity)); partStart = i; partShift = shift; partVelocity = 0; } } - int v = strength * 2; - if (v > 127) v = 127; - + int v = round(strength * 2); if (v > partVelocity) { partVelocity = v; } } if (end >= partStart + partThreshold) { - f.timestamp = RealTime::fromSeconds - (columnDuration * (partStart - postFilterLatency) + 0.02); - f.duration = RealTime::fromSeconds - (columnDuration * (end - partStart)); - f.values.clear(); - f.values.push_back - (noteFrequency(note, partShift, shiftCount)); - f.values.push_back(partVelocity); - f.label = noteName(note, partShift, shiftCount); - noteFeatures.push_back(f); + noteFeatures.push_back(makeNoteFeature(partStart, + end, + note, + partShift, + shiftCount, + partVelocity)); } } + +Silvet::Feature +Silvet::makeNoteFeature(int start, + int end, + int note, + int shift, + int shiftCount, + int velocity) +{ + double columnDuration = 1.0 / m_colsPerSec; + int postFilterLatency = int(m_postFilter[0]->getSize() / 2); + + Feature f; + + f.hasTimestamp = true; + f.timestamp = RealTime::fromSeconds + (columnDuration * (start - postFilterLatency) + 0.02); + + f.hasDuration = true; + f.duration = RealTime::fromSeconds + (columnDuration * (end - start)); + + f.values.clear(); + + f.values.push_back + (noteFrequency(note, shift, shiftCount)); + + float inputGain = getInputGainAt(f.timestamp); +// cerr << "adjusting velocity from " << velocity << " to " << round(velocity/inputGain) << endl; + velocity = round(velocity / inputGain); + if (velocity > 127) velocity = 127; + if (velocity < 1) velocity = 1; + f.values.push_back(velocity); + + f.label = noteName(note, shift, shiftCount); + + return f; +} + +float +Silvet::getInputGainAt(RealTime t) +{ + map<RealTime, float>::const_iterator i = m_inputGains.lower_bound(t); + + if (i == m_inputGains.end()) { + if (i != m_inputGains.begin()) { + --i; + } else { + return 1.f; // no data + } + } + +// cerr << "gain at time " << t << " = " << i->second << endl; + + return i->second; +} +