From 9f6de8863954715f930f937568ed274ee66d33db Mon Sep 17 00:00:00 2001 From: John Glover Date: Mon, 24 Sep 2012 11:18:09 +0200 Subject: [partial_tracking] Default to inharmonic partial tracking mode in SMSPartialTracking. Add methods to SMSPartialTracking to allow realtime mode and harmonic mode to be switched on/off. --- src/simpl/partial_tracking.cpp | 40 ++++++++++++++++- src/simpl/partial_tracking.h | 5 +++ tests/test_partial_tracking.cpp | 97 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 139 insertions(+), 3 deletions(-) diff --git a/src/simpl/partial_tracking.cpp b/src/simpl/partial_tracking.cpp index 99a8f34..5bb08b3 100644 --- a/src/simpl/partial_tracking.cpp +++ b/src/simpl/partial_tracking.cpp @@ -92,11 +92,12 @@ SMSPartialTracking::SMSPartialTracking() { _analysis_params.analDelay = 0; _analysis_params.minGoodFrames = 1; _analysis_params.iCleanTracks = 0; - _analysis_params.iFormat = SMS_FORMAT_HP; + _analysis_params.iFormat = SMS_FORMAT_IHP; _analysis_params.nTracks = _max_partials; _analysis_params.maxPeaks = _max_partials; _analysis_params.nGuides = _max_partials; _analysis_params.preEmphasis = 0; + _analysis_params.realtime = 0; sms_initAnalysis(&_analysis_params); sms_fillHeader(&_header, &_analysis_params); @@ -159,11 +160,48 @@ void SMSPartialTracking::max_partials(int new_max_partials) { init_peaks(); } +bool SMSPartialTracking::realtime() { + return _analysis_params.realtime == 1; +} + +void SMSPartialTracking::realtime(bool is_realtime) { + if(is_realtime) { + _analysis_params.realtime = 1; + } + else { + _analysis_params.realtime = 0; + } +} + +bool SMSPartialTracking::harmonic() { + return _analysis_params.iFormat == SMS_FORMAT_HP; +} + +void SMSPartialTracking::harmonic(bool is_harmonic) { + sms_freeAnalysis(&_analysis_params); + sms_freeFrame(&_data); + + if(is_harmonic) { + _analysis_params.iFormat = SMS_FORMAT_HP; + } + else { + _analysis_params.iFormat = SMS_FORMAT_IHP; + } + + sms_initAnalysis(&_analysis_params); + sms_fillHeader(&_header, &_analysis_params); + sms_allocFrameH(&_header, &_data); +} + +void SMSPartialTracking::reset() { +} + Peaks SMSPartialTracking::update_partials(Frame* frame) { int num_peaks = _max_partials; if(num_peaks > frame->num_peaks()) { num_peaks = frame->num_peaks(); } + frame->clear_partials(); // set peaks in SMSAnalysisParams object for(int i = 0; i < num_peaks; i++) { diff --git a/src/simpl/partial_tracking.h b/src/simpl/partial_tracking.h index 4f8d60e..324c348 100644 --- a/src/simpl/partial_tracking.h +++ b/src/simpl/partial_tracking.h @@ -78,6 +78,11 @@ class SMSPartialTracking : public PartialTracking { SMSPartialTracking(); ~SMSPartialTracking(); void max_partials(int new_max_partials); + bool realtime(); + void realtime(bool is_realtime); + bool harmonic(); + void harmonic(bool is_harmonic); + void reset(); Peaks update_partials(Frame* frame); }; diff --git a/tests/test_partial_tracking.cpp b/tests/test_partial_tracking.cpp index 71c5452..f5c1fff 100644 --- a/tests/test_partial_tracking.cpp +++ b/tests/test_partial_tracking.cpp @@ -14,13 +14,105 @@ namespace simpl { +// --------------------------------------------------------------------------- +// TestSMSPartialTracking +// --------------------------------------------------------------------------- +class TestSMSPartialTracking : public CPPUNIT_NS::TestCase { + CPPUNIT_TEST_SUITE(TestSMSPartialTracking); + CPPUNIT_TEST(test_basic); + CPPUNIT_TEST(test_peaks); + CPPUNIT_TEST_SUITE_END(); + +protected: + static const double PRECISION = 0.001; + SMSPeakDetection* pd; + SMSPartialTracking* pt; + SndfileHandle sf; + int num_samples; + + void test_basic() { + pt->reset(); + pd->hop_size(256); + pd->frame_size(2048); + + sample* audio = new sample[(int)sf.frames()]; + sf.read(audio, (int)sf.frames()); + + Frames frames = pd->find_peaks(num_samples, &(audio[(int)sf.frames() / 2])); + frames = pt->find_partials(frames); + + for(int i = 0; i < frames.size(); i++) { + CPPUNIT_ASSERT(frames[i]->num_peaks() > 0); + CPPUNIT_ASSERT(frames[i]->num_partials() > 0); + } + } + + void test_peaks() { + pt->reset(); + + Frames frames; + Peaks peaks; + int num_frames = 8; + + for(int i = 0; i < num_frames; i++) { + Peak* p = new Peak(); + p->amplitude = 0.2; + p->frequency = 220; + + Peak* p2 = new Peak(); + p2->amplitude = 0.2; + p2->frequency = 440; + + Frame* f = new Frame(); + f->add_peak(p); + f->add_peak(p2); + + frames.push_back(f); + peaks.push_back(p); + peaks.push_back(p2); + } + + pt->find_partials(frames); + for(int i = 0; i < num_frames; i++) { + CPPUNIT_ASSERT(frames[i]->num_peaks() > 0); + CPPUNIT_ASSERT(frames[i]->num_partials() > 0); + CPPUNIT_ASSERT(frames[i]->partial(0)->amplitude == 0.2); + CPPUNIT_ASSERT(frames[i]->partial(0)->frequency == 220); + CPPUNIT_ASSERT(frames[i]->partial(1)->amplitude == 0.2); + CPPUNIT_ASSERT(frames[i]->partial(1)->frequency == 440); + } + + for(int i = 0; i < num_frames * 2; i++) { + delete peaks[i]; + } + + for(int i = 0; i < num_frames; i++) { + delete frames[i]; + } + } + +public: + void setUp() { + pd = new SMSPeakDetection(); + pt = new SMSPartialTracking(); + pt->realtime(1); + sf = SndfileHandle("../tests/audio/flute.wav"); + num_samples = 4096; + } + + void tearDown() { + delete pd; + delete pt; + } +}; + // --------------------------------------------------------------------------- // TestLorisPartialTracking // --------------------------------------------------------------------------- class TestLorisPartialTracking : public CPPUNIT_NS::TestCase { CPPUNIT_TEST_SUITE(TestLorisPartialTracking); CPPUNIT_TEST(test_basic); - // CPPUNIT_TEST(test_simple_peaks); + CPPUNIT_TEST(test_peaks); CPPUNIT_TEST_SUITE_END(); protected: @@ -47,7 +139,7 @@ protected: } } - void test_simple_peaks() { + void test_peaks() { pt->reset(); Frames frames; @@ -107,6 +199,7 @@ public: } // end of namespace simpl +CPPUNIT_TEST_SUITE_REGISTRATION(simpl::TestSMSPartialTracking); CPPUNIT_TEST_SUITE_REGISTRATION(simpl::TestLorisPartialTracking); int main(int arg, char **argv) { -- cgit v1.2.3