diff options
| -rw-r--r-- | simpl/base.pyx | 30 | ||||
| -rw-r--r-- | src/simpl/base.cpp | 78 | ||||
| -rw-r--r-- | src/simpl/base.h | 13 | ||||
| -rw-r--r-- | tests/test_base.py | 25 | 
4 files changed, 98 insertions, 48 deletions
| diff --git a/simpl/base.pyx b/simpl/base.pyx index 2fab453..3f811a1 100644 --- a/simpl/base.pyx +++ b/simpl/base.pyx @@ -32,7 +32,7 @@ cdef extern from "../src/simpl/base.h" namespace "simpl":          void max_peaks(int new_max_peaks)          void add_peak(c_Peak* peak)          c_Peak* peak(int peak_number) -        void clear_peaks() +        void clear()          # partials          # int num_partials() @@ -74,9 +74,8 @@ cdef extern from "../src/simpl/base.h" namespace "simpl":          void min_peak_separation(double new_min_peak_separation)          int num_frames()          c_Frame* frame(int frame_number) -        vector[c_Frame*] frames() -        # Peaks* find_peaks_in_frame(const Frame& frame) -        # Frames* find_peaks(number* audio) +        vector[c_Peak*] find_peaks_in_frame(c_Frame* frame) +        vector[c_Frame*] find_peaks(int audio_size, double* audio)  cdef class Peak: @@ -122,7 +121,7 @@ cdef class Frame:                  self.thisptr = new c_Frame()              self.created = True          else: -            self.create = False +            self.created = False      def __dealloc__(self):          if self.created: @@ -158,8 +157,8 @@ cdef class Frame:          def __set__(self, peaks):              self.add_peaks(peaks) -    def clear_peaks(self): -        self.thisptr.clear_peaks() +    def clear(self): +        self.thisptr.clear()      # audio buffers      property size: @@ -242,11 +241,26 @@ cdef class PeakDetection:      def frame(self, int i):          cdef c_Frame* c_f = self.thisptr.frame(i) -        f = Frame(False) +        f = Frame(None, False)          f.set_frame(c_f) +        return f      property frames:          def __get__(self):              return [self.frame(i) for i in range(self.thisptr.num_frames())]          def __set__(self, f):              raise Exception("NotImplemented") + +    def find_peaks_in_frame(self, Frame frame not None): +        peaks = [] +        cdef vector[c_Peak*] c_peaks = self.thisptr.find_peaks_in_frame(frame.thisptr) +        for i in range(c_peaks.size()): +            peak = Peak(False) +            peak.set_peak(c_peaks[i]) +            peaks.append(peak) +        return peaks + +    def find_peaks(self, np.ndarray[dtype_t, ndim=1] audio): +        frames = [] +        cdef vector[c_Frame*] c_frames = self.thisptr.find_peaks(len(audio), <double*> audio.data) +        return frames diff --git a/src/simpl/base.cpp b/src/simpl/base.cpp index afffcbb..3f6c093 100644 --- a/src/simpl/base.cpp +++ b/src/simpl/base.cpp @@ -1,9 +1,9 @@ -#include <iostream>  #include "base.h"  using namespace std;  using namespace simpl; +  // ---------------------------------------------------------------------------  // Peak  // --------------------------------------------------------------------------- @@ -55,6 +55,7 @@ bool Peak::is_free(const string direction)      return true;  } +  // ---------------------------------------------------------------------------  // Frame  // --------------------------------------------------------------------------- @@ -103,7 +104,7 @@ void Frame::max_peaks(int new_max_peaks)  {      _max_peaks = new_max_peaks; -    // potentially losing data here but the user shouldn't really do this +    // TODO: potentially losing data here, should prevent or complain      if((int)_peaks.size() > _max_peaks)      {          _peaks.resize(_max_peaks); @@ -128,7 +129,7 @@ Peak* Frame::peak(int peak_number)      return _peaks[peak_number];  } -void Frame::clear_peaks() +void Frame::clear()  {      _peaks.clear();  } @@ -231,6 +232,7 @@ number* Frame::synth_residual()      return _synth_residual;  } +  // ---------------------------------------------------------------------------  // PeakDetection  // --------------------------------------------------------------------------- @@ -249,6 +251,16 @@ PeakDetection::PeakDetection()  PeakDetection::~PeakDetection()  { +    clear(); +} + +void PeakDetection::clear() +{ +    for(int i = 0; i < _frames.size(); i++) +    { +        delete _frames[i]; +    } +      _frames.clear();  } @@ -346,15 +358,15 @@ Frame* PeakDetection::frame(int frame_number)      return _frames[frame_number];  } -Frames* PeakDetection::frames() +Frames PeakDetection::frames()  { -    return &_frames; +    return _frames;  }  // Find and return all spectral peaks in a given frame of audio -Peaks* PeakDetection::find_peaks_in_frame(const Frame& frame) +Peaks PeakDetection::find_peaks_in_frame(Frame* frame)  { -    Peaks* peaks = new Peaks(); +    Peaks peaks;      return peaks;  } @@ -362,30 +374,30 @@ Peaks* PeakDetection::find_peaks_in_frame(const Frame& frame)  // If the signal contains more than 1 frame worth of audio, it will be broken  // up into separate frames, each containing a std::vector of peaks.  // Frames* PeakDetection::find_peaks(const samples& audio) -Frames* PeakDetection::find_peaks(number* audio) -{ -    // _frames.clear(); -    // unsigned int pos = 0; -    // while(pos < audio.size()) -    // { -    //     // get the next frame size -    //     if(!_static_frame_size) -    //     { -    //         _frame_size = next_frame_size(); -    //     } - -    //     // get the next frame -    //     Frame f = Frame(_frame_size); -    //     f.audio(audio, pos); - -    //     // find peaks -    //     Peaks* peaks = find_peaks_in_frame(f); -    //     f.add_peaks(peaks); -    //     delete peaks; - -    //     _frames.push_back(f); -    //     pos += _hop_size; -    // } - -    // return &_frames; +Frames PeakDetection::find_peaks(int audio_size, number* audio) +{ +    clear(); +    unsigned int pos = 0; + +    while(pos < audio_size - _hop_size) +    { +        // get the next frame size +        if(!_static_frame_size) +        { +            _frame_size = next_frame_size(); +        } + +        // get the next frame +        Frame* f = new Frame(_frame_size); +        f->audio(&audio[pos]); + +        // find peaks +        Peaks peaks = find_peaks_in_frame(f); +        f->add_peaks(&peaks); + +        _frames.push_back(f); +        pos += _hop_size; +    } + +    return _frames;  } diff --git a/src/simpl/base.h b/src/simpl/base.h index 9f12482..d460d0c 100644 --- a/src/simpl/base.h +++ b/src/simpl/base.h @@ -12,6 +12,7 @@ namespace simpl  typedef double number; +  // ---------------------------------------------------------------------------  // Peak  // @@ -41,6 +42,7 @@ public:  typedef std::vector<Peak*> Peaks; +  // ---------------------------------------------------------------------------  // Partial  // --------------------------------------------------------------------------- @@ -48,6 +50,7 @@ class Partial {};  typedef std::vector<Partial*> Partials; +  // ---------------------------------------------------------------------------  // Frame  //  @@ -85,7 +88,7 @@ public:      void add_peak(Peak* peak);      void add_peaks(Peaks* peaks);      Peak* peak(int peak_number); -    void clear_peaks(); +    void clear();      Peaks::iterator peaks_begin();      Peaks::iterator peaks_end(); @@ -111,6 +114,7 @@ public:  typedef std::vector<Frame*> Frames; +  // ---------------------------------------------------------------------------  // PeakDetection  //  @@ -133,6 +137,7 @@ private:  public:      PeakDetection();      virtual ~PeakDetection(); +    void clear();      int sampling_rate();      void sampling_rate(int new_sampling_rate); @@ -153,15 +158,15 @@ public:      void min_peak_separation(number new_min_peak_separation);      int num_frames();      Frame* frame(int frame_number); -    Frames* frames(); +    Frames frames();      // Find and return all spectral peaks in a given frame of audio -    virtual Peaks* find_peaks_in_frame(const Frame& frame); +    virtual Peaks find_peaks_in_frame(Frame* frame);      // Find and return all spectral peaks in a given audio signal.      // If the signal contains more than 1 frame worth of audio, it will be broken      // up into separate frames, with an array of peaks returned for each frame. -    virtual Frames* find_peaks(number* audio); +    virtual Frames find_peaks(int audio_size, number* audio);  };  } // end of namespace Simpl diff --git a/tests/test_base.py b/tests/test_base.py index 8b00d33..aade0df 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,5 +1,8 @@ -import simpl.base as base +import os  import numpy as np +import scipy.io.wavfile as wavfile +from nose.tools import assert_almost_equals +import simpl.base as base  class TestFrame(object): @@ -39,11 +42,27 @@ class TestFrame(object):          assert f.peak(0).amplitude == p.amplitude          assert f.peaks[0].amplitude == p.amplitude -        f.clear_peaks() +        f.clear()          assert f.num_peaks == 0  class TestPeakDetection(object): +    float_precision = 5 +    frame_size = 512 +    hop_size = 512 +    audio_path = os.path.join( +        os.path.dirname(__file__), 'audio/flute.wav' +    ) + +    @classmethod +    def setup_class(cls): +        cls.audio = wavfile.read(cls.audio_path)[1] +        cls.audio = np.asarray(cls.audio, dtype=np.double) +        cls.audio /= np.max(cls.audio) +      def test_peak_detection(self):          pd = base.PeakDetection() -        print pd.frames +        pd.find_peaks(self.audio) + +        assert len(pd.frames) == len(self.audio) / self.hop_size +        assert len(pd.frames[0].peaks) == 0 |