Mercurial > hg > silvet
comparison src/Silvet.cpp @ 297:d6ab1b4918bd livemode
Thinking about a "live" mode...
author | Chris Cannam |
---|---|
date | Fri, 28 Nov 2014 09:42:56 +0000 |
parents | aa7be9d8112e |
children | ebe5e0942bb8 |
comparison
equal
deleted
inserted
replaced
296:a3229b972463 | 297:d6ab1b4918bd |
---|---|
42 Plugin(inputSampleRate), | 42 Plugin(inputSampleRate), |
43 m_instruments(InstrumentPack::listInstrumentPacks()), | 43 m_instruments(InstrumentPack::listInstrumentPacks()), |
44 m_resampler(0), | 44 m_resampler(0), |
45 m_flattener(0), | 45 m_flattener(0), |
46 m_cq(0), | 46 m_cq(0), |
47 m_hqMode(true), | 47 m_mode(HighQualityMode), |
48 m_fineTuning(false), | 48 m_fineTuning(false), |
49 m_instrument(0), | 49 m_instrument(0), |
50 m_colsPerSec(50) | 50 m_colsPerSec(50) |
51 { | 51 { |
52 } | 52 } |
134 | 134 |
135 ParameterDescriptor desc; | 135 ParameterDescriptor desc; |
136 desc.identifier = "mode"; | 136 desc.identifier = "mode"; |
137 desc.name = "Processing mode"; | 137 desc.name = "Processing mode"; |
138 desc.unit = ""; | 138 desc.unit = ""; |
139 desc.description = "Sets the tradeoff of processing speed against transcription quality. Draft mode modifies a number of internal parameters in favour of speed. Intensive mode (the default) will almost always produce better results."; | 139 desc.description = "Sets the tradeoff of processing speed against transcription quality. Draft mode is tuned in favour of overall speed; Live mode is tuned in favour of lower latency; while Intensive mode (the default) will almost always produce the best results."; |
140 desc.minValue = 0; | 140 desc.minValue = 0; |
141 desc.maxValue = 1; | 141 desc.maxValue = 2; |
142 desc.defaultValue = 1; | 142 desc.defaultValue = 1; |
143 desc.isQuantized = true; | 143 desc.isQuantized = true; |
144 desc.quantizeStep = 1; | 144 desc.quantizeStep = 1; |
145 desc.valueNames.push_back("Draft (faster)"); | 145 desc.valueNames.push_back("Draft (faster)"); |
146 desc.valueNames.push_back("Intensive (higher quality)"); | 146 desc.valueNames.push_back("Intensive (higher quality)"); |
147 desc.valueNames.push_back("Live (lower latency)"); | |
147 list.push_back(desc); | 148 list.push_back(desc); |
148 | 149 |
149 desc.identifier = "instrument"; | 150 desc.identifier = "instrument"; |
150 desc.name = "Instrument"; | 151 desc.name = "Instrument"; |
151 desc.unit = ""; | 152 desc.unit = ""; |
178 | 179 |
179 float | 180 float |
180 Silvet::getParameter(string identifier) const | 181 Silvet::getParameter(string identifier) const |
181 { | 182 { |
182 if (identifier == "mode") { | 183 if (identifier == "mode") { |
183 return m_hqMode ? 1.f : 0.f; | 184 return (float)(int)m_mode; |
184 } else if (identifier == "finetune") { | 185 } else if (identifier == "finetune") { |
185 return m_fineTuning ? 1.f : 0.f; | 186 return m_fineTuning ? 1.f : 0.f; |
186 } else if (identifier == "instrument") { | 187 } else if (identifier == "instrument") { |
187 return m_instrument; | 188 return m_instrument; |
188 } | 189 } |
191 | 192 |
192 void | 193 void |
193 Silvet::setParameter(string identifier, float value) | 194 Silvet::setParameter(string identifier, float value) |
194 { | 195 { |
195 if (identifier == "mode") { | 196 if (identifier == "mode") { |
196 m_hqMode = (value > 0.5); | 197 m_mode = (ProcessingMode)(int)(value + 0.5); |
197 } else if (identifier == "finetune") { | 198 } else if (identifier == "finetune") { |
198 m_fineTuning = (value > 0.5); | 199 m_fineTuning = (value > 0.5); |
199 } else if (identifier == "instrument") { | 200 } else if (identifier == "instrument") { |
200 m_instrument = lrintf(value); | 201 m_instrument = lrintf(value); |
201 } | 202 } |
397 m_flattener = new FlattenDynamics(m_inputSampleRate); // before resampling | 398 m_flattener = new FlattenDynamics(m_inputSampleRate); // before resampling |
398 m_flattener->reset(); | 399 m_flattener->reset(); |
399 | 400 |
400 double minFreq = 27.5; | 401 double minFreq = 27.5; |
401 | 402 |
402 if (!m_hqMode) { | 403 if (m_mode != HighQualityMode) { |
403 // We don't actually return any notes from the bottom octave, | 404 // We don't actually return any notes from the bottom octave, |
404 // so we can just pad with zeros | 405 // so we can just pad with zeros |
405 minFreq *= 2; | 406 minFreq *= 2; |
406 } | 407 } |
407 | 408 |
419 params.threshold = 0.0005; | 420 params.threshold = 0.0005; |
420 params.window = CQParameters::Hann; | 421 params.window = CQParameters::Hann; |
421 | 422 |
422 m_cq = new CQSpectrogram(params, CQSpectrogram::InterpolateLinear); | 423 m_cq = new CQSpectrogram(params, CQSpectrogram::InterpolateLinear); |
423 | 424 |
424 m_colsPerSec = m_hqMode ? 50 : 25; | 425 cerr << "cq latency = " << m_cq->getLatency() << endl; |
426 | |
427 m_colsPerSec = (m_mode == DraftMode ? 25 : 50); | |
425 | 428 |
426 for (int i = 0; i < (int)m_postFilter.size(); ++i) { | 429 for (int i = 0; i < (int)m_postFilter.size(); ++i) { |
427 delete m_postFilter[i]; | 430 delete m_postFilter[i]; |
428 } | 431 } |
429 m_postFilter.clear(); | 432 m_postFilter.clear(); |
513 fs[m_fcqOutputNo].push_back(f); | 516 fs[m_fcqOutputNo].push_back(f); |
514 } | 517 } |
515 | 518 |
516 int width = filtered.size(); | 519 int width = filtered.size(); |
517 | 520 |
518 int iterations = m_hqMode ? 20 : 10; | 521 int iterations = (m_mode == HighQualityMode ? 20 : 10); |
519 | 522 |
520 Grid localPitches(width, vector<double>(pack.templateNoteCount, 0.0)); | 523 Grid localPitches(width, vector<double>(pack.templateNoteCount, 0.0)); |
521 | 524 |
522 bool wantShifts = m_hqMode && m_fineTuning; | 525 bool wantShifts = (m_mode == HighQualityMode) && m_fineTuning; |
523 int shiftCount = 1; | 526 int shiftCount = 1; |
524 if (wantShifts) { | 527 if (wantShifts) { |
525 shiftCount = pack.templateMaxShift * 2 + 1; | 528 shiftCount = pack.templateMaxShift * 2 + 1; |
526 } | 529 } |
527 | 530 |
542 } | 545 } |
543 if (sum < 1e-5) continue; | 546 if (sum < 1e-5) continue; |
544 | 547 |
545 present[i] = true; | 548 present[i] = true; |
546 | 549 |
547 EM em(&pack, m_hqMode); | 550 EM em(&pack, m_mode == HighQualityMode); |
548 | 551 |
549 em.setPitchSparsity(pack.pitchSparsity); | 552 em.setPitchSparsity(pack.pitchSparsity); |
550 em.setSourceSparsity(pack.sourceSparsity); | 553 em.setSourceSparsity(pack.sourceSparsity); |
551 | 554 |
552 for (int j = 0; j < iterations; ++j) { | 555 for (int j = 0; j < iterations; ++j) { |
649 vector<double> outCol(pack.templateHeight); | 652 vector<double> outCol(pack.templateHeight); |
650 | 653 |
651 // In HQ mode, the CQ returns 600 bins and we ignore the | 654 // In HQ mode, the CQ returns 600 bins and we ignore the |
652 // lowest 55 of them. | 655 // lowest 55 of them. |
653 // | 656 // |
654 // In draft mode the CQ is an octave shorter, returning | 657 // In draft and live mode the CQ is an octave shorter, |
655 // 540 bins, so we instead pad them with an additional 5 | 658 // returning 540 bins, so we instead pad them with an |
656 // zeros. | 659 // additional 5 zeros. |
657 // | 660 // |
658 // We also need to reverse the column as we go, since the | 661 // We also need to reverse the column as we go, since the |
659 // raw CQ has the high frequencies first and we need it | 662 // raw CQ has the high frequencies first and we need it |
660 // the other way around. | 663 // the other way around. |
661 | 664 |
662 if (m_hqMode) { | 665 if (m_mode == HighQualityMode) { |
663 for (int j = 0; j < pack.templateHeight; ++j) { | 666 for (int j = 0; j < pack.templateHeight; ++j) { |
664 int ix = inCol.size() - j - 55; | 667 int ix = inCol.size() - j - 55; |
665 outCol[j] = inCol[ix]; | 668 outCol[j] = inCol[ix]; |
666 } | 669 } |
667 } else { | 670 } else { |