Mercurial > hg > silvet
comparison src/Silvet.cpp @ 252:34e69544691b norm
Make use of input gain information to adjust output note velocities back to original levels
author | Chris Cannam |
---|---|
date | Wed, 23 Jul 2014 10:20:07 +0100 |
parents | 6b7e78cf96c9 |
children | 10d8bd634a77 |
comparison
equal
deleted
inserted
replaced
251:ea37df6305a8 | 252:34e69544691b |
---|---|
415 (FlattenDynamics::AudioOutputPort, &flattened[0]); | 415 (FlattenDynamics::AudioOutputPort, &flattened[0]); |
416 m_flattener->connectOutputPort | 416 m_flattener->connectOutputPort |
417 (FlattenDynamics::GainOutputPort, &gain); | 417 (FlattenDynamics::GainOutputPort, &gain); |
418 m_flattener->process(m_blockSize); | 418 m_flattener->process(m_blockSize); |
419 | 419 |
420 m_inputGains.push_back(gain); | 420 m_inputGains[timestamp] = gain; |
421 | 421 |
422 vector<double> data; | 422 vector<double> data; |
423 for (int i = 0; i < m_blockSize; ++i) { | 423 for (int i = 0; i < m_blockSize; ++i) { |
424 double d = flattened[i]; | 424 double d = flattened[i]; |
425 data.push_back(d); | 425 data.push_back(d); |
752 { | 752 { |
753 int partStart = start; | 753 int partStart = start; |
754 int partShift = 0; | 754 int partShift = 0; |
755 int partVelocity = 0; | 755 int partVelocity = 0; |
756 | 756 |
757 Feature f; | 757 int partThreshold = floor(0.05 * m_colsPerSec); |
758 f.hasTimestamp = true; | |
759 f.hasDuration = true; | |
760 | |
761 double columnDuration = 1.0 / m_colsPerSec; | |
762 int postFilterLatency = int(m_postFilter[0]->getSize() / 2); | |
763 int partThreshold = floor(0.05 / columnDuration); | |
764 | 758 |
765 for (int i = start; i != end; ++i) { | 759 for (int i = start; i != end; ++i) { |
766 | 760 |
767 double strength = m_pianoRoll[i][note]; | 761 double strength = m_pianoRoll[i][note]; |
768 | 762 |
779 if (i > partStart + partThreshold && shift != partShift) { | 773 if (i > partStart + partThreshold && shift != partShift) { |
780 | 774 |
781 // cerr << "i = " << i << ", partStart = " << partStart << ", shift = " << shift << ", partShift = " << partShift << endl; | 775 // cerr << "i = " << i << ", partStart = " << partStart << ", shift = " << shift << ", partShift = " << partShift << endl; |
782 | 776 |
783 // pitch has changed, emit an intermediate note | 777 // pitch has changed, emit an intermediate note |
784 f.timestamp = RealTime::fromSeconds | 778 noteFeatures.push_back(makeNoteFeature(partStart, |
785 (columnDuration * (partStart - postFilterLatency) + 0.02); | 779 i, |
786 f.duration = RealTime::fromSeconds | 780 note, |
787 (columnDuration * (i - partStart)); | 781 partShift, |
788 f.values.clear(); | 782 shiftCount, |
789 f.values.push_back | 783 partVelocity)); |
790 (noteFrequency(note, partShift, shiftCount)); | |
791 f.values.push_back(partVelocity); | |
792 f.label = noteName(note, partShift, shiftCount); | |
793 noteFeatures.push_back(f); | |
794 partStart = i; | 784 partStart = i; |
795 partShift = shift; | 785 partShift = shift; |
796 partVelocity = 0; | 786 partVelocity = 0; |
797 } | 787 } |
798 } | 788 } |
799 | 789 |
800 //!!! todo: do something with input gain. Presumably we need | |
801 //!!! to index it by something close to, but not actually, i | |
802 //!!! (depending on cq latency) | |
803 /* | |
804 cerr << "i = " << i << ", gain length = " << m_inputGains.size() | |
805 << ", cq latency = " << m_cq->getLatency() << " (as columns = " | |
806 << m_cq->getLatency() / m_cq->getColumnHop() << ", as input blocks = " | |
807 << m_cq->getLatency() / m_blockSize << ")" << endl; | |
808 */ | |
809 int v = round(strength * 2); | 790 int v = round(strength * 2); |
810 if (v > 127) v = 127; | |
811 | |
812 if (v > partVelocity) { | 791 if (v > partVelocity) { |
813 partVelocity = v; | 792 partVelocity = v; |
814 } | 793 } |
815 } | 794 } |
816 | 795 |
817 if (end >= partStart + partThreshold) { | 796 if (end >= partStart + partThreshold) { |
818 f.timestamp = RealTime::fromSeconds | 797 noteFeatures.push_back(makeNoteFeature(partStart, |
819 (columnDuration * (partStart - postFilterLatency) + 0.02); | 798 end, |
820 f.duration = RealTime::fromSeconds | 799 note, |
821 (columnDuration * (end - partStart)); | 800 partShift, |
822 f.values.clear(); | 801 shiftCount, |
823 f.values.push_back | 802 partVelocity)); |
824 (noteFrequency(note, partShift, shiftCount)); | 803 } |
825 f.values.push_back(partVelocity); | 804 } |
826 f.label = noteName(note, partShift, shiftCount); | 805 |
827 noteFeatures.push_back(f); | 806 Silvet::Feature |
828 } | 807 Silvet::makeNoteFeature(int start, |
829 } | 808 int end, |
809 int note, | |
810 int shift, | |
811 int shiftCount, | |
812 int velocity) | |
813 { | |
814 double columnDuration = 1.0 / m_colsPerSec; | |
815 int postFilterLatency = int(m_postFilter[0]->getSize() / 2); | |
816 | |
817 Feature f; | |
818 | |
819 f.hasTimestamp = true; | |
820 f.timestamp = RealTime::fromSeconds | |
821 (columnDuration * (start - postFilterLatency) + 0.02); | |
822 | |
823 f.hasDuration = true; | |
824 f.duration = RealTime::fromSeconds | |
825 (columnDuration * (end - start)); | |
826 | |
827 f.values.clear(); | |
828 | |
829 f.values.push_back | |
830 (noteFrequency(note, shift, shiftCount)); | |
831 | |
832 float inputGain = getInputGainAt(f.timestamp); | |
833 // cerr << "adjusting velocity from " << velocity << " to " << round(velocity/inputGain) << endl; | |
834 velocity = round(velocity / inputGain); | |
835 if (velocity > 127) velocity = 127; | |
836 if (velocity < 1) velocity = 1; | |
837 f.values.push_back(velocity); | |
838 | |
839 f.label = noteName(note, shift, shiftCount); | |
840 | |
841 return f; | |
842 } | |
843 | |
844 float | |
845 Silvet::getInputGainAt(RealTime t) | |
846 { | |
847 map<RealTime, float>::const_iterator i = m_inputGains.lower_bound(t); | |
848 | |
849 if (i == m_inputGains.end()) { | |
850 if (i != m_inputGains.begin()) { | |
851 --i; | |
852 } else { | |
853 return 1.f; // no data | |
854 } | |
855 } | |
856 | |
857 // cerr << "gain at time " << t << " = " << i->second << endl; | |
858 | |
859 return i->second; | |
860 } | |
861 |