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