diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | setup.py | 24 | ||||
-rw-r--r-- | simpl/__init__.py | 2 | ||||
-rw-r--r-- | simpl/base.pyx | 90 | ||||
-rw-r--r-- | src/simpl/base.cpp | 119 | ||||
-rw-r--r-- | src/simpl/base.h | 33 | ||||
-rw-r--r-- | tests/test_base.py | 25 |
7 files changed, 207 insertions, 89 deletions
@@ -22,6 +22,9 @@ simpl/simplsndobj.py simpl/simplsms.py simpl/simplloris.py +# Files generated by Cython +simpl/base.cpp + # Test files tests/audio tests/testbase @@ -8,7 +8,9 @@ many of which have yet to be released in software. Simpl is primarily intended as a tool for other researchers in the field, allowing them to easily combine, compare and contrast many of the published analysis/synthesis algorithms. """ -from setuptools import setup, Extension +from distutils.core import setup +from distutils.extension import Extension +from Cython.Distutils import build_ext import os from glob import glob @@ -39,6 +41,11 @@ simpl_sources = glob('src/simpl/*.cpp') simpl_include_dirs = ['src/simpl'] simpl_include_dirs.extend(include_dirs) +base = Extension("simpl.base", + sources=["simpl/base.pyx", "src/simpl/base.cpp"], + include_dirs=["simpl"] + simpl_include_dirs, + language="c++") + # ----------------------------------------------------------------------------- # SndObj Library # ----------------------------------------------------------------------------- @@ -115,13 +122,13 @@ sms = Extension("simpl/_simplsms", # Loris # ----------------------------------------------------------------------------- -simplloris_sources = ['simpl/simplloris.i'] -simplloris_sources.extend(simpl_sources) +# simplloris_sources = ['simpl/simplloris.i'] +# simplloris_sources.extend(simpl_sources) -simplloris = Extension("simpl/_simplloris", - sources=simplloris_sources, - include_dirs=simpl_include_dirs, - swig_opts=swig_opts) +# simplloris = Extension("simpl/_simplloris", +# sources=simplloris_sources, +# include_dirs=simpl_include_dirs, +# swig_opts=swig_opts) # ----------------------------------------------------------------------------- # Package @@ -140,6 +147,7 @@ setup( author_email='j@johnglover.net', platforms=["Linux", "Mac OS-X", "Unix", "Windows"], version='0.3', - ext_modules=[sndobj, sms, simplloris], + ext_modules=[base, sndobj, sms], + cmdclass={'build_ext': build_ext}, packages=['simpl', 'simpl.plot'] ) diff --git a/simpl/__init__.py b/simpl/__init__.py index 9a1742b..66e5bfe 100644 --- a/simpl/__init__.py +++ b/simpl/__init__.py @@ -3,7 +3,7 @@ from basetypes import PeakDetection, PartialTracking, Synthesis, Residual from basetypes import compare_peak_amps, compare_peak_freqs from sndobj import SndObjPeakDetection, SndObjPartialTracking, SndObjSynthesis from sms import SMSPeakDetection, SMSPartialTracking, SMSSynthesis, SMSResidual -from loris import LorisPeakDetection, LorisPartialTracking, LorisSynthesis +# from loris import LorisPeakDetection, LorisPartialTracking, LorisSynthesis from mq import MQPeakDetection, MQPartialTracking, MQSynthesis from plot import plot_peaks, plot_partials from audio import read_wav diff --git a/simpl/base.pyx b/simpl/base.pyx new file mode 100644 index 0000000..d33951b --- /dev/null +++ b/simpl/base.pyx @@ -0,0 +1,90 @@ +import numpy as np +cimport numpy as np +np.import_array() + +dtype = np.float64 +ctypedef np.double_t dtype_t + +cdef extern from "../src/simpl/base.h" namespace "simpl": + cdef cppclass c_Frame "simpl::Frame": + c_Frame() + c_Frame(int frame_size) + + # peaks + # int num_peaks() + # int max_peaks() + # void max_peaks(int new_max_peaks) + # void add_peak(Peak peak) + # void add_peaks(Peaks* peaks) + # Peak peak(int peak_number) + # void clear_peaks() + # Peaks::iterator peaks_begin() + # Peaks::iterator peaks_end() + + # partials + # int num_partials() + # int max_partials() + # void max_partials(int new_max_partials) + # void add_partial(Partial partial) + # Partials::iterator partials() + + # audio buffers + int size() + void size(int new_size) + void audio(double* new_audio) + double* audio() + void synth(double* new_synth) + double* synth() + void residual(double* new_residual) + double* residual() + void synth_residual(double* new_synth_residual) + double* synth_residual() + +cdef class Frame: + cdef c_Frame *thisptr + + def __cinit__(self, size=None): + if size: + self.thisptr = new c_Frame(size) + else: + self.thisptr = new c_Frame() + + def __dealloc__(self): + del self.thisptr + + property size: + def __get__(self): return self.thisptr.size() + def __set__(self, int n): self.thisptr.size(n) + + property audio: + def __get__(self): + cdef np.npy_intp shape[1] + shape[0] = <np.npy_intp> self.thisptr.size() + return np.PyArray_SimpleNewFromData(1, shape, np.NPY_DOUBLE, self.thisptr.audio()) + def __set__(self, np.ndarray[dtype_t, ndim=1] a): + self.thisptr.audio(<double*> a.data) + + property synth: + def __get__(self): + cdef np.npy_intp shape[1] + shape[0] = <np.npy_intp> self.thisptr.size() + return np.PyArray_SimpleNewFromData(1, shape, np.NPY_DOUBLE, self.thisptr.synth()) + def __set__(self, np.ndarray[dtype_t, ndim=1] a): + self.thisptr.synth(<double*> a.data) + + property residual: + def __get__(self): + cdef np.npy_intp shape[1] + shape[0] = <np.npy_intp> self.thisptr.size() + return np.PyArray_SimpleNewFromData(1, shape, np.NPY_DOUBLE, self.thisptr.residual()) + def __set__(self, np.ndarray[dtype_t, ndim=1] a): + self.thisptr.residual(<double*> a.data) + + property synth_residual: + def __get__(self): + cdef np.npy_intp shape[1] + shape[0] = <np.npy_intp> self.thisptr.size() + return np.PyArray_SimpleNewFromData(1, shape, np.NPY_DOUBLE, self.thisptr.synth_residual()) + def __set__(self, np.ndarray[dtype_t, ndim=1] a): + self.thisptr.synth_residual(<double*> a.data) + diff --git a/src/simpl/base.cpp b/src/simpl/base.cpp index 2ec670e..f5a42b0 100644 --- a/src/simpl/base.cpp +++ b/src/simpl/base.cpp @@ -2,8 +2,7 @@ #include "base.h" using namespace std; - -namespace Simpl { +using namespace simpl; // --------------------------------------------------------------------------- // Peak @@ -48,7 +47,9 @@ bool Peak::is_free(const string direction) } else { - Throw(InvalidArgument, "Invalid direction"); + // Throw(InvalidArgument, "Invalid direction"); + // TODO: fix this + printf("ERROR: InvalidArgument\n"); } return true; @@ -80,9 +81,9 @@ void Frame::init() _max_peaks = 100; _max_partials = 100; _audio = NULL; - // _synth = NULL; - // _residual = NULL; - // _synth_residual = NULL; + _synth = NULL; + _residual = NULL; + _synth_residual = NULL; } // Frame - peaks @@ -190,50 +191,45 @@ void Frame::size(int new_size) _size = new_size; } -// void Frame::audio(const number* new_audio) -// { -// _audio = new_audio; -// } - -void Frame::audio(const samples& new_audio, const int offset) +void Frame::audio(number* new_audio) { - _audio = &new_audio + offset; + _audio = new_audio; } -const samples* Frame::audio() +number* Frame::audio() { return _audio; } -// void Frame::synth(const number* new_synth) -// { -// _synth = new_synth; -// } +void Frame::synth(number* new_synth) +{ + _synth = new_synth; +} -// const number* Frame::synth() -// { -// return _synth; -// } +number* Frame::synth() +{ + return _synth; +} -// void Frame::residual(const number* new_residual) -// { -// _residual = new_residual; -// } +void Frame::residual(number* new_residual) +{ + _residual = new_residual; +} -// const number* Frame::residual() -// { -// return _residual; -// } +number* Frame::residual() +{ + return _residual; +} -// void Frame::synth_residual(const number* new_synth_residual) -// { -// _synth_residual = new_synth_residual; -// } +void Frame::synth_residual(number* new_synth_residual) +{ + _synth_residual = new_synth_residual; +} -// const number* Frame::synth_residual() -// { -// return _synth_residual; -// } +number* Frame::synth_residual() +{ + return _synth_residual; +} // --------------------------------------------------------------------------- // PeakDetection @@ -355,32 +351,31 @@ Peaks* PeakDetection::find_peaks_in_frame(const 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, each containing a std::vector of peaks. -Frames* PeakDetection::find_peaks(const samples& 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(); - } +// 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); + // // 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; + // // find peaks + // Peaks* peaks = find_peaks_in_frame(f); + // f.add_peaks(peaks); + // delete peaks; - _frames.push_back(f); - pos += _hop_size; - } + // _frames.push_back(f); + // pos += _hop_size; + // } - return &_frames; + // return &_frames; } - -} // end of namespace Simpl diff --git a/src/simpl/base.h b/src/simpl/base.h index 2657cf1..12df565 100644 --- a/src/simpl/base.h +++ b/src/simpl/base.h @@ -7,11 +7,10 @@ using namespace std; -namespace Simpl +namespace simpl { typedef double number; -typedef std::vector<number> samples; // --------------------------------------------------------------------------- // Peak @@ -68,10 +67,10 @@ private: int _max_partials; Peaks _peaks; Partials _partials; - const samples* _audio; - // const number* _synth; - // const number* _residual; - // const number* _synth_residual; + number* _audio; + number* _synth; + number* _residual; + number* _synth_residual; void init(); public: @@ -100,16 +99,14 @@ public: // audio buffers int size(); void size(int new_size); - // void audio(const number* new_audio); - void audio(const samples& new_audio, const int offset = 0); - const samples* audio(); - - // void synth(const number* new_synth); - // const number* synth(); - // void residual(const number* new_residual); - // const number* residual(); - // void synth_residual(const number* new_synth_residual); - // const number* synth_residual(); + void audio(number* new_audio); + number* audio(); + void synth(number* new_synth); + number* synth(); + void residual(number* new_residual); + number* residual(); + void synth_residual(number* new_synth_residual); + number* synth_residual(); }; typedef std::vector<Frame> Frames; @@ -161,8 +158,8 @@ public: // 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 a std::vector of peaks returned for each frame. - virtual Frames* find_peaks(const samples& audio); + // up into separate frames, with an array of peaks returned for each frame. + virtual Frames* find_peaks(number* audio); }; } // end of namespace Simpl diff --git a/tests/test_base.py b/tests/test_base.py new file mode 100644 index 0000000..c906f31 --- /dev/null +++ b/tests/test_base.py @@ -0,0 +1,25 @@ +import simpl.base as base +import numpy as np + + +class TestFrame(object): + def test_buffers(self): + N = 256 + f = base.Frame(N) + assert f.size == N + + a = np.random.rand(N) + f.audio = a + assert np.all(f.audio == a) + + a = np.random.rand(N) + f.synth = a + assert np.all(f.synth == a) + + a = np.random.rand(N) + f.residual = a + assert np.all(f.residual == a) + + a = np.random.rand(N) + f.synth_residual = a + assert np.all(f.synth_residual == a) |