diff options
author | John Glover <j@johnglover.net> | 2012-08-22 16:44:52 +0100 |
---|---|---|
committer | John Glover <j@johnglover.net> | 2012-08-22 16:44:52 +0100 |
commit | e4ab5141d33d0c94a1c82091a02cfc7ecffc65fd (patch) | |
tree | 1279128c939768c209dbffb94419ec5c8e54cefb | |
parent | 5fb34d7d5451cefd88bb9d7a0d9c442d67caf143 (diff) | |
download | simpl-e4ab5141d33d0c94a1c82091a02cfc7ecffc65fd.tar.gz simpl-e4ab5141d33d0c94a1c82091a02cfc7ecffc65fd.tar.bz2 simpl-e4ab5141d33d0c94a1c82091a02cfc7ecffc65fd.zip |
[loris] Add C++ implementation of LorisPartialTracking.
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | simpl/__init__.py | 1 | ||||
-rw-r--r-- | simpl/partial_tracking.pxd | 3 | ||||
-rw-r--r-- | simpl/partial_tracking.pyx | 12 | ||||
-rw-r--r-- | src/simpl/partial_tracking.cpp | 98 | ||||
-rw-r--r-- | src/simpl/partial_tracking.h | 41 | ||||
-rw-r--r-- | src/simpl/peak_detection.h | 6 | ||||
-rw-r--r-- | tests/test_partial_tracking.cpp | 65 |
8 files changed, 228 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c5aa23..1a79a5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,8 +42,14 @@ install(FILES ${include_files} DESTINATION include/simpl) # tests set(test_base_src ${source_files} tests/test_base.cpp) set(test_peak_detection_src ${source_files} tests/test_peak_detection.cpp) +set(test_partial_tracking_src ${source_files} tests/test_partial_tracking.cpp) + LIST(APPEND libs cppunit sndfile) + add_executable(test_base ${test_base_src}) add_executable(test_peak_detection ${test_peak_detection_src}) +add_executable(test_partial_tracking ${test_partial_tracking_src}) + target_link_libraries(test_base ${libs}) target_link_libraries(test_peak_detection ${libs}) +target_link_libraries(test_partial_tracking ${libs}) diff --git a/simpl/__init__.py b/simpl/__init__.py index 915d2f6..798e31b 100644 --- a/simpl/__init__.py +++ b/simpl/__init__.py @@ -24,6 +24,7 @@ LorisPeakDetection = peak_detection.LorisPeakDetection PartialTracking = partial_tracking.PartialTracking SMSPartialTracking = partial_tracking.SMSPartialTracking SndObjPartialTracking = partial_tracking.SndObjPartialTracking +LorisPartialTracking = partial_tracking.LorisPartialTracking Synthesis = synthesis.Synthesis SMSSynthesis = synthesis.SMSSynthesis diff --git a/simpl/partial_tracking.pxd b/simpl/partial_tracking.pxd index bbe9893..69e9821 100644 --- a/simpl/partial_tracking.pxd +++ b/simpl/partial_tracking.pxd @@ -30,3 +30,6 @@ cdef extern from "../src/simpl/partial_tracking.h" namespace "simpl": cdef cppclass c_SndObjPartialTracking "simpl::SndObjPartialTracking"(c_PartialTracking): c_SndObjPartialTracking() + + cdef cppclass c_LorisPartialTracking "simpl::LorisPartialTracking"(c_PartialTracking): + c_LorisPartialTracking() diff --git a/simpl/partial_tracking.pyx b/simpl/partial_tracking.pyx index e0599f8..58a0a78 100644 --- a/simpl/partial_tracking.pyx +++ b/simpl/partial_tracking.pyx @@ -80,3 +80,15 @@ cdef class SndObjPartialTracking(PartialTracking): if self.thisptr: del self.thisptr self.thisptr = <c_PartialTracking*>0 + + +cdef class LorisPartialTracking(PartialTracking): + def __cinit__(self): + if self.thisptr: + del self.thisptr + self.thisptr = new c_LorisPartialTracking() + + def __dealloc__(self): + if self.thisptr: + del self.thisptr + self.thisptr = <c_PartialTracking*>0 diff --git a/src/simpl/partial_tracking.cpp b/src/simpl/partial_tracking.cpp index fdafb84..42df76b 100644 --- a/src/simpl/partial_tracking.cpp +++ b/src/simpl/partial_tracking.cpp @@ -304,3 +304,101 @@ Peaks SndObjPartialTracking::update_partials(Frame* frame) { return peaks; } + +// --------------------------------------------------------------------------- +// LorisPartialTracking +// --------------------------------------------------------------------------- +SimplLorisPTAnalyzer::SimplLorisPTAnalyzer() : + Loris::Analyzer(50, 100), + _env(1.0) { + buildFundamentalEnv(false); + _partial_builder = new Loris::PartialBuilder(m_freqDrift, _env); +} + +SimplLorisPTAnalyzer::~SimplLorisPTAnalyzer() { + delete _partial_builder; +} + +void SimplLorisPTAnalyzer::analyze() { + m_ampEnvBuilder->reset(); + m_f0Builder->reset(); + m_partials.clear(); + + // estimate the amplitude in this frame: + m_ampEnvBuilder->build(peaks, 0); + + // collect amplitudes and frequencies and try to + // estimate the fundamental + m_f0Builder->build(peaks, 0); + + // form Partials from the extracted Breakpoints: + _partial_builder->buildPartials(peaks, 0); + + // unwarp the Partial frequency envelopes: + _partial_builder->finishBuilding(m_partials); +} + +// --------------------------------------------------------------------------- + +LorisPartialTracking::LorisPartialTracking() { + _analyzer = NULL; + reset(); +} + +LorisPartialTracking::~LorisPartialTracking() { + if(_analyzer) { + delete _analyzer; + } +} + +void LorisPartialTracking::reset() { + if(_analyzer) { + delete _analyzer; + } + _analyzer = new SimplLorisPTAnalyzer(); +} + +void LorisPartialTracking::max_partials(int new_max_partials) { + _max_partials = new_max_partials; + reset(); +} + +Peaks LorisPartialTracking::update_partials(Frame* frame) { + int num_peaks = frame->num_peaks(); + if(num_peaks > _max_partials) { + num_peaks = _max_partials; + } + + Peaks peaks; + + _analyzer->peaks.clear(); + for(int i = 0; i < num_peaks; i++) { + Loris::Breakpoint bp = Loris::Breakpoint(frame->peak(i)->frequency, + frame->peak(i)->amplitude, + frame->peak(i)->bandwidth, + frame->peak(i)->phase); + _analyzer->peaks.push_back(Loris::SpectralPeak(1, bp)); + } + + _analyzer->analyze(); + _partials = _analyzer->partials(); + int num_partials = _partials.size(); + + for(Loris::PartialListIterator i = _partials.begin(); i != _partials.end(); ++i) { + Peak* p = new Peak(); + p->amplitude = i->amplitudeAt(1); + p->frequency = i->frequencyAt(1); + p->phase = i->phaseAt(1); + p->bandwidth = i->bandwidthAt(1); + peaks.push_back(p); + frame->add_partial(p); + } + + for(int i = num_partials; i < _max_partials; i++) { + Peak* p = new Peak(); + peaks.push_back(p); + frame->add_partial(p); + } + + return peaks; +} diff --git a/src/simpl/partial_tracking.h b/src/simpl/partial_tracking.h index 4491b42..b9f2d28 100644 --- a/src/simpl/partial_tracking.h +++ b/src/simpl/partial_tracking.h @@ -12,6 +12,15 @@ extern "C" { #include "IFGram.h" #include "SinAnal.h" +#include "Analyzer.h" +#include "AssociateBandwidth.h" +#include "BreakpointEnvelope.h" +#include "KaiserWindow.h" +#include "PartialBuilder.h" +#include "PartialList.h" +#include "ReassignedSpectrum.h" +#include "SpectralPeakSelector.h" + using namespace std; namespace simpl @@ -72,6 +81,7 @@ class SMSPartialTracking : public PartialTracking { Peaks update_partials(Frame* frame); }; + // --------------------------------------------------------------------------- // SndObjPartialTracking // --------------------------------------------------------------------------- @@ -93,7 +103,36 @@ class SndObjPartialTracking : public PartialTracking { Peaks update_partials(Frame* frame); }; +// --------------------------------------------------------------------------- +// LorisPartialTracking +// --------------------------------------------------------------------------- +class SimplLorisPTAnalyzer : public Loris::Analyzer { + protected: + Loris::BreakpointEnvelope _env; + Loris::PartialBuilder* _partial_builder; + + public: + SimplLorisPTAnalyzer(); + ~SimplLorisPTAnalyzer(); + Loris::Peaks peaks; + void analyze(); +}; + + +class LorisPartialTracking : public PartialTracking { + private: + SimplLorisPTAnalyzer* _analyzer; + Loris::PartialList _partials; + void reset(); + + public: + LorisPartialTracking(); + ~LorisPartialTracking(); + void max_partials(int new_max_partials); + Peaks update_partials(Frame* frame); +}; + -} // end of namespace Simpl +} // end of namespace simpl #endif diff --git a/src/simpl/peak_detection.h b/src/simpl/peak_detection.h index 30c9225..398c2bf 100644 --- a/src/simpl/peak_detection.h +++ b/src/simpl/peak_detection.h @@ -13,12 +13,12 @@ extern "C" { #include "SinAnal.h" #include "Analyzer.h" +#include "AssociateBandwidth.h" +#include "BreakpointEnvelope.h" #include "KaiserWindow.h" +#include "PartialBuilder.h" #include "ReassignedSpectrum.h" #include "SpectralPeakSelector.h" -#include "PartialBuilder.h" -#include "AssociateBandwidth.h" -#include "BreakpointEnvelope.h" using namespace std; diff --git a/tests/test_partial_tracking.cpp b/tests/test_partial_tracking.cpp new file mode 100644 index 0000000..25fcfff --- /dev/null +++ b/tests/test_partial_tracking.cpp @@ -0,0 +1,65 @@ +#include <iostream> +#include <cppunit/ui/text/TextTestRunner.h> +#include <cppunit/TestResult.h> +#include <cppunit/TestResultCollector.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/BriefTestProgressListener.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <sndfile.hh> + +#include "../src/simpl/base.h" +#include "../src/simpl/peak_detection.h" +#include "../src/simpl/partial_tracking.h" + +namespace simpl +{ + +// --------------------------------------------------------------------------- +// TestLorisPartialTracking +// --------------------------------------------------------------------------- +class TestLorisPartialTracking : public CPPUNIT_NS::TestCase { + CPPUNIT_TEST_SUITE(TestLorisPartialTracking); + CPPUNIT_TEST(test_basic); + CPPUNIT_TEST_SUITE_END(); + +protected: + static const double PRECISION = 0.001; + LorisPeakDetection* pd; + LorisPartialTracking* pt; + SndfileHandle sf; + int num_samples; + + void test_basic() { + 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); + } + } + +public: + void setUp() { + pd = new LorisPeakDetection(); + pt = new LorisPartialTracking(); + sf = SndfileHandle("../tests/audio/flute.wav"); + num_samples = 4096; + } + + void tearDown() { + delete pd; + } +}; + +} // end of namespace simpl + +CPPUNIT_TEST_SUITE_REGISTRATION(simpl::TestLorisPartialTracking); + +int main(int arg, char **argv) { + CppUnit::TextTestRunner runner; + runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); + return runner.run("", false); +} |