summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--simpl/base.pyx30
-rw-r--r--src/simpl/base.cpp78
-rw-r--r--src/simpl/base.h13
-rw-r--r--tests/test_base.py25
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