diff options
Diffstat (limited to 'tests/test_sms.py')
-rw-r--r-- | tests/test_sms.py | 1266 |
1 files changed, 1266 insertions, 0 deletions
diff --git a/tests/test_sms.py b/tests/test_sms.py new file mode 100644 index 0000000..ca51f3f --- /dev/null +++ b/tests/test_sms.py @@ -0,0 +1,1266 @@ +# Copyright (c) 2009 John Glover, National University of Ireland, Maynooth +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import simpl +from simpl import simplsms +import pysms +import numpy as np +from scipy.io.wavfile import read +from nose.tools import assert_almost_equals + +class TestSimplSMS(object): + FLOAT_PRECISION = 2 # number of decimal places to check for accuracy + input_file = 'audio/flute.wav' + hop_size = 512 + num_frames = 50 + num_samples = num_frames * hop_size + max_peaks = 10 + max_partials = 10 + + def get_audio(self): + audio_data = read(self.input_file) + audio = simpl.asarray(audio_data[1]) / 32768.0 + sampling_rate = audio_data[0] + return audio[0:self.num_samples], sampling_rate + + def pysms_analysis_params(self, sampling_rate): + analysis_params = pysms.SMS_AnalParams() + pysms.sms_initAnalParams(analysis_params) + analysis_params.iSamplingRate = sampling_rate + analysis_params.iFrameRate = sampling_rate / self.hop_size + analysis_params.iWindowType = pysms.SMS_WIN_HAMMING + analysis_params.fDefaultFundamental = 100 + analysis_params.fHighestFreq = 20000 + analysis_params.iFormat = pysms.SMS_FORMAT_HP + analysis_params.nTracks = self.max_peaks + analysis_params.peakParams.iMaxPeaks = self.max_peaks + analysis_params.nGuides = self.max_peaks + analysis_params.iMaxDelayFrames = 4 + analysis_params.analDelay = 0 + analysis_params.minGoodFrames = 1 + analysis_params.iCleanTracks = 0 + analysis_params.iStochasticType = pysms.SMS_STOC_NONE + analysis_params.preEmphasis = 0 + return analysis_params + + def simplsms_analysis_params(self, sampling_rate): + analysis_params = simplsms.SMS_AnalParams() + simplsms.sms_initAnalParams(analysis_params) + analysis_params.iSamplingRate = sampling_rate + analysis_params.iFrameRate = sampling_rate / self.hop_size + analysis_params.iWindowType = simplsms.SMS_WIN_HAMMING + analysis_params.fDefaultFundamental = 100 + analysis_params.fHighestFreq = 20000 + analysis_params.iFormat = simplsms.SMS_FORMAT_HP + analysis_params.nTracks = self.max_peaks + analysis_params.maxPeaks = self.max_peaks + analysis_params.nGuides = self.max_peaks + analysis_params.iMaxDelayFrames = 4 + analysis_params.analDelay = 0 + analysis_params.minGoodFrames = 1 + analysis_params.iCleanTracks = 0 + analysis_params.iStochasticType = simplsms.SMS_STOC_NONE + analysis_params.preEmphasis = 0 + return analysis_params + + def pysms_synthesis_params(self, sampling_rate): + synth_params = pysms.SMS_SynthParams() + pysms.sms_initSynthParams(synth_params) + synth_params.iSamplingRate = sampling_rate + synth_params.iSynthesisType = pysms.SMS_STYPE_DET + synth_params.iStochasticType = pysms.SMS_STOC_NONE + synth_params.sizeHop = self.hop_size + synth_params.nTracks = self.max_peaks + synth_params.deEmphasis = 0 + return synth_params + + def test_size_next_read(self): + """test_size_next_read + Make sure pysms PeakDetection is calculating + the correct value for the size of the next frame.""" + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + analysis_params.iMaxDelayFrames = self.num_frames + 1 + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.nFrames = self.num_frames + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + sample_offset = 0 + pysms_size_new_data = 0 + current_frame = 0 + sms_next_read_sizes = [] + + while current_frame < self.num_frames: + sms_next_read_sizes.append(analysis_params.sizeNextRead) + sample_offset += pysms_size_new_data + pysms_size_new_data = analysis_params.sizeNextRead + # convert frame to floats for libsms + frame = audio[sample_offset:sample_offset + pysms_size_new_data] + frame = np.array(frame, dtype=np.float32) + if len(frame) < pysms_size_new_data: + frame = np.hstack((frame, np.zeros(pysms_size_new_data - len(frame), + dtype=np.float32))) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + status = pysms.sms_analyze(frame, analysis_data, analysis_params) + # as the no. of frames of delay is > num_frames, sms_analyze should + # never get around to performing partial tracking, and so the return + # value should be 0 + assert status == 0 + pysms.sms_freeFrame(analysis_data) + current_frame += 1 + + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_free() + + pd = simpl.SMSPeakDetection() + pd.hop_size = self.hop_size + pd.max_peaks = self.max_peaks + current_frame = 0 + sample_offset = 0 + + while current_frame < self.num_frames: + pd.frame_size = pd.get_next_frame_size() + #print current_frame, sms_next_read_sizes[current_frame], pd.frame_size + assert sms_next_read_sizes[current_frame] == pd.frame_size + frame = simpl.Frame() + frame.size = pd.frame_size + frame.audio = audio[sample_offset:sample_offset + pd.frame_size] + pd.find_peaks_in_frame(frame) + sample_offset += pd.frame_size + current_frame += 1 + + def test_sms_analyze(self): + """test_sms_analyze + Make sure that the simplsms.sms_analyze function does the same thing + as the sms_analyze function from libsms.""" + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.nFrames = self.num_frames + analysis_params.iSizeSound = self.num_samples + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + sms_frames = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + # convert frame to floats for libsms + frame = simpl.Frame() + frame.size = size_new_data + frame.audio = np.array(audio[sample_offset:sample_offset + size_new_data], + dtype=np.float32) + if len(frame.audio) < size_new_data: + frame.audio = np.hstack((frame.audio, np.zeros(size_new_data - len(frame.audio), + dtype=np.float32))) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + status = pysms.sms_analyze(frame.audio, analysis_data, analysis_params) + num_partials = analysis_data.nTracks + peaks = [] + + if status == 1: + sms_amps = np.zeros(num_partials, dtype=np.float32) + sms_freqs = np.zeros(num_partials, dtype=np.float32) + sms_phases = np.zeros(num_partials, dtype=np.float32) + analysis_data.getSinFreq(sms_freqs) + analysis_data.getSinAmp(sms_amps) + analysis_data.getSinPhase(sms_phases) + for i in range(num_partials): + p = simpl.Peak() + p.amplitude = sms_amps[i] + p.frequency = sms_freqs[i] + p.phase = sms_phases[i] + peaks.append(p) + else: + for i in range(num_partials): + p = simpl.Peak() + p.amplitude = 0.0 + p.frequency = 0.0 + p.phase = 0.0 + peaks.append(p) + + if status == -1: + do_analysis = False + + frame.partials = peaks + sms_frames.append(frame) + pysms.sms_freeFrame(analysis_data) + current_frame += 1 + + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_free() + + audio, sampling_rate = self.get_audio() + simplsms.sms_init() + simpl_analysis_params = self.simplsms_analysis_params(sampling_rate) + if simplsms.sms_initAnalysis(simpl_analysis_params) != 0: + raise Exception("Error allocating memory for analysis_params") + simpl_analysis_params.nFrames = self.num_frames + simpl_analysis_params.iSizeSound = self.num_samples + simpl_sms_header = simplsms.SMS_Header() + simplsms.sms_fillHeader(simpl_sms_header, simpl_analysis_params, "simplsms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + simplsms_frames = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = simpl_analysis_params.sizeNextRead + frame = simpl.Frame() + frame.size = size_new_data + frame.audio = audio[sample_offset:sample_offset + size_new_data] + if len(frame.audio) < size_new_data: + frame.audio = np.hstack((frame.audio, simpl.zeros(size_new_data - len(frame.audio)))) + analysis_data = simplsms.SMS_Data() + simplsms.sms_allocFrameH(simpl_sms_header, analysis_data) + status = simplsms.sms_analyze(frame.audio, analysis_data, simpl_analysis_params) + num_partials = analysis_data.nTracks + peaks = [] + + if status == 1: + freqs = simpl.zeros(num_partials) + amps = simpl.zeros(num_partials) + phases = simpl.zeros(num_partials) + analysis_data.getSinAmp(amps) + analysis_data.getSinFreq(freqs) + analysis_data.getSinPhase(phases) + for i in range(num_partials): + p = simpl.Peak() + p.amplitude = amps[i] + p.frequency = freqs[i] + p.phase = phases[i] + peaks.append(p) + else: + for i in range(num_partials): + p = simpl.Peak() + p.amplitude = 0.0 + p.frequency = 0.0 + p.phase = 0.0 + peaks.append(p) + + if status == -1: + do_analysis = False + + frame.partials = peaks + simplsms_frames.append(frame) + simplsms.sms_freeFrame(analysis_data) + current_frame += 1 + + simplsms.sms_freeAnalysis(simpl_analysis_params) + simplsms.sms_free() + + # make sure both have the same number of partials + assert len(sms_frames) == len(simplsms_frames) + + # make sure each partial is the same + for i in range(len(sms_frames)): + assert len(sms_frames[i].partials) == len(simplsms_frames[i].partials) + for p in range(len(sms_frames[i].partials)): + assert_almost_equals(sms_frames[i].partials[p].amplitude, + simplsms_frames[i].partials[p].amplitude, + self.FLOAT_PRECISION) + assert_almost_equals(sms_frames[i].partials[p].frequency, + simplsms_frames[i].partials[p].frequency, + self.FLOAT_PRECISION) + assert_almost_equals(sms_frames[i].partials[p].phase, + simplsms_frames[i].partials[p].phase, + self.FLOAT_PRECISION) + + def test_multi_sms_peak_detection(self): + """test_multi_sms_peak_detection + Test that running the same peak detection process twice in a row + produces the same results each time. This makes sure that results + are independent, and also helps to highlight any memory errors.""" + audio, sampling_rate = self.get_audio() + simplsms.sms_init() + analysis_params = self.simplsms_analysis_params(sampling_rate) + analysis_params.iMaxDelayFrames = self.num_frames + 1 + if simplsms.sms_initAnalysis(analysis_params) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.nFrames = self.num_frames + sms_header = simplsms.SMS_Header() + simplsms.sms_fillHeader(sms_header, analysis_params, "simplsms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + peaks1 = [] + + while current_frame < self.num_frames: + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + frame = audio[sample_offset:sample_offset + size_new_data] + analysis_data = simplsms.SMS_Data() + simplsms.sms_allocFrameH(sms_header, analysis_data) + status = simplsms.sms_analyze(frame, analysis_data, analysis_params) + # as the no. of frames of delay is > num_frames, sms_analyze should + # never get around to performing partial tracking, and so the return + # value should be 0 + assert status == 0 + num_peaks = analysis_data.nTracks + frame_peaks = [] + simplsms_freqs = simpl.zeros(num_peaks) + simplsms_amps = simpl.zeros(num_peaks) + simplsms_phases = simpl.zeros(num_peaks) + analysis_data.getSinFreq(simplsms_freqs) + analysis_data.getSinAmp(simplsms_amps) + analysis_data.getSinPhase(simplsms_phases) + for i in range(num_peaks): + if simplsms_amps[i]: + p = simpl.Peak() + # convert amplitude back to linear + p.amplitude = 10**(simplsms_amps[i]/20.0) + p.frequency = simplsms_freqs[i] + p.phase = simplsms_phases[i] + frame_peaks.append(p) + peaks1.append(frame_peaks) + pysms.sms_freeFrame(analysis_data) + current_frame += 1 + + simplsms.sms_freeAnalysis(analysis_params) + simplsms.sms_free() + + # Second run + audio, sampling_rate = self.get_audio() + simplsms.sms_init() + analysis_params = self.simplsms_analysis_params(sampling_rate) + analysis_params.iMaxDelayFrames = self.num_frames + 1 + if simplsms.sms_initAnalysis(analysis_params) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.nFrames = self.num_frames + sms_header = simplsms.SMS_Header() + simplsms.sms_fillHeader(sms_header, analysis_params, "simplsms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + peaks2 = [] + + while current_frame < self.num_frames: + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + frame = audio[sample_offset:sample_offset + size_new_data] + analysis_data = simplsms.SMS_Data() + simplsms.sms_allocFrameH(sms_header, analysis_data) + status = simplsms.sms_analyze(frame, analysis_data, analysis_params) + # as the no. of frames of delay is > num_frames, sms_analyze should + # never get around to performing partial tracking, and so the return + # value should be 0 + assert status == 0 + num_peaks = analysis_data.nTracks + frame_peaks = [] + simplsms_freqs = simpl.zeros(num_peaks) + simplsms_amps = simpl.zeros(num_peaks) + simplsms_phases = simpl.zeros(num_peaks) + analysis_data.getSinFreq(simplsms_freqs) + analysis_data.getSinAmp(simplsms_amps) + analysis_data.getSinPhase(simplsms_phases) + for i in range(num_peaks): + if simplsms_amps[i]: + p = simpl.Peak() + # convert amplitude back to linear + p.amplitude = 10**(simplsms_amps[i]/20.0) + p.frequency = simplsms_freqs[i] + p.phase = simplsms_phases[i] + frame_peaks.append(p) + peaks2.append(frame_peaks) + pysms.sms_freeFrame(analysis_data) + current_frame += 1 + + simplsms.sms_freeAnalysis(analysis_params) + simplsms.sms_free() + + # make sure we have the same number of frames in each run + assert len(peaks1) == len(peaks2) + for f in range(len(peaks1)): + # in each frame, make sure that we have the same number of peaks + assert len(peaks1[f]) == len(peaks2[f]) + # make sure that each peak has the same value + for p in range(len(peaks1[f])): + assert_almost_equals(peaks1[f][p].frequency, + peaks2[f][p].frequency, + self.FLOAT_PRECISION) + assert_almost_equals(peaks1[f][p].amplitude, + peaks2[f][p].amplitude, + self.FLOAT_PRECISION) + assert_almost_equals(peaks1[f][p].phase, + peaks2[f][p].phase, + self.FLOAT_PRECISION) + + def test_multi_simpl_peak_detection(self): + """test_multi_simpl_peak_detection + Test that running the simpl peak detection process twice in a row + produces the same results each time. This makes sure that results + are independent, and also helps to highlight any memory errors.""" + audio, sampling_rate = self.get_audio() + pd = simpl.SMSPeakDetection() + pd.max_peaks = self.max_peaks + pd.hop_size = self.hop_size + frames1 = pd.find_peaks(audio)[0:self.num_frames] + del pd + # second run + audio, sampling_rate = self.get_audio() + pd = simpl.SMSPeakDetection() + pd.max_peaks = self.max_peaks + pd.hop_size = self.hop_size + frames2 = pd.find_peaks(audio)[0:self.num_frames] + + # make sure we have the same number of frames in each run + assert len(frames1) == len(frames2) + for f in range(len(frames1)): + # in each frame, make sure that we have the same number of peaks + assert len(frames1[f].peaks) == len(frames2[f].peaks) + # make sure that each peak has the same value + for p in range(len(frames1[f].peaks)): + assert_almost_equals(frames1[f].peaks[p].frequency, + frames2[f].peaks[p].frequency, + self.FLOAT_PRECISION) + assert_almost_equals(frames1[f].peaks[p].amplitude, + frames2[f].peaks[p].amplitude, + self.FLOAT_PRECISION) + assert_almost_equals(frames1[f].peaks[p].phase, + frames2[f].peaks[p].phase, + self.FLOAT_PRECISION) + + def test_peak_detection(self): + """test_peak_detection + Compare simplsms Peaks with SMS peaks. Exact peak + information cannot be retrieved using libsms. Basic peak detection + is performed by sms_detectPeaks, but this is called multiple times + with different frame sizes by sms_analyze. This peak data cannot + be returned from sms_analyze without modifying it, so here + we compare the peaks to a slightly modified version of sms_analyze + from simplsms. The peak values should be the same as those found by + the simplsms find_peaks function. Analyses have to be performed + separately due to libsms implementation issues.""" + audio, sampling_rate = self.get_audio() + simplsms.sms_init() + analysis_params = self.simplsms_analysis_params(sampling_rate) + analysis_params.iMaxDelayFrames = self.num_frames + 1 + if simplsms.sms_initAnalysis(analysis_params) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.nFrames = self.num_frames + sms_header = simplsms.SMS_Header() + simplsms.sms_fillHeader(sms_header, analysis_params, "simplsms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + sms_peaks = [] + + while current_frame < self.num_frames: + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + frame = audio[sample_offset:sample_offset + size_new_data] + if len(frame) < size_new_data: + frame = np.hstack((frame, simpl.zeros(size_new_data - len(frame)))) + analysis_data = simplsms.SMS_Data() + simplsms.sms_allocFrameH(sms_header, analysis_data) + status = simplsms.sms_analyze(frame, analysis_data, analysis_params) + # as the no. of frames of delay is > num_frames, sms_analyze should + # never get around to performing partial tracking, and so the return + # value should be 0 + assert status == 0 + num_peaks = analysis_data.nTracks + frame_peaks = [] + simplsms_freqs = simpl.zeros(num_peaks) + simplsms_amps = simpl.zeros(num_peaks) + simplsms_phases = simpl.zeros(num_peaks) + analysis_data.getSinFreq(simplsms_freqs) + analysis_data.getSinAmp(simplsms_amps) + analysis_data.getSinPhase(simplsms_phases) + for i in range(num_peaks): + if simplsms_amps[i]: + p = simpl.Peak() + # convert amplitude back to linear + p.amplitude = simplsms_amps[i] + p.frequency = simplsms_freqs[i] + p.phase = simplsms_phases[i] + frame_peaks.append(p) + sms_peaks.append(frame_peaks) + pysms.sms_freeFrame(analysis_data) + current_frame += 1 + + simplsms.sms_freeAnalysis(analysis_params) + simplsms.sms_free() + + # get simpl peaks + pd = simpl.SMSPeakDetection() + pd.hop_size = self.hop_size + pd.max_peaks = self.max_peaks + current_frame = 0 + sample_offset = 0 + simpl_peaks = [] + + while current_frame < self.num_frames: + pd.frame_size = pd.get_next_frame_size() + frame = simpl.Frame() + frame.size = pd.frame_size + frame.audio = audio[sample_offset:sample_offset + pd.frame_size] + if len(frame.audio) < pd.frame_size: + frame.audio = np.hstack((frame.audio, simpl.zeros(pd.frame_size - len(frame.audio)))) + simpl_peaks.append(pd.find_peaks_in_frame(frame)) + sample_offset += pd.frame_size + current_frame += 1 + + # make sure we have the same number of frames + assert len(sms_peaks) == len(simpl_peaks) + + # compare data for each frame + for frame_number in range(len(sms_peaks)): + sms_frame = sms_peaks[frame_number] + simpl_frame = simpl_peaks[frame_number] + # make sure we have the same number of peaks in each frame + assert len(sms_frame) == len(simpl_frame) + # check peak values + for peak_number in range(len(sms_frame)): + sms_peak = sms_frame[peak_number] + simpl_peak = simpl_frame[peak_number] + assert_almost_equals(sms_peak.amplitude, simpl_peak.amplitude, + self.FLOAT_PRECISION) + assert_almost_equals(sms_peak.frequency, simpl_peak.frequency, + self.FLOAT_PRECISION) + assert_almost_equals(sms_peak.phase, simpl_peak.phase, + self.FLOAT_PRECISION) + + def test_multi_pysms_analyze(self): + """test_multi_pysms_analyze + Test that running the pysms sms_analyze function twice in a row + produces the same results each time. This makes sure that results + are independent, and also helps to highlight any memory errors.""" + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.iSizeSound = self.num_samples + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + freqs1 = [] + amps1 = [] + phases1 = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + # convert frame to floats for libsms + frame = audio[sample_offset:sample_offset + size_new_data] + frame = np.array(frame, dtype=np.float32) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + status = pysms.sms_analyze(frame, analysis_data, analysis_params) + if status == 1: + num_partials = analysis_data.nTracks + freqs = np.zeros(num_partials, dtype=np.float32) + amps = np.zeros(num_partials, dtype=np.float32) + phases = np.zeros(num_partials, dtype=np.float32) + analysis_data.getSinFreq(freqs) + analysis_data.getSinAmp(amps) + analysis_data.getSinPhase(phases) + amps1.append(amps) + freqs1.append(freqs) + phases1.append(phases) + elif status == -1: + do_analysis = False + pysms.sms_freeFrame(analysis_data) + current_frame += 1 + + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_free() + + # second run + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.iSizeSound = self.num_samples + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + freqs2 = [] + amps2 = [] + phases2 = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + # convert frame to floats for libsms + frame = audio[sample_offset:sample_offset + size_new_data] + frame = np.array(frame, dtype=np.float32) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + status = pysms.sms_analyze(frame, analysis_data, analysis_params) + if status == 1: + num_partials = analysis_data.nTracks + freqs = np.zeros(num_partials, dtype=np.float32) + amps = np.zeros(num_partials, dtype=np.float32) + phases = np.zeros(num_partials, dtype=np.float32) + analysis_data.getSinFreq(freqs) + analysis_data.getSinAmp(amps) + analysis_data.getSinPhase(phases) + amps2.append(amps) + freqs2.append(freqs) + phases2.append(phases) + elif status == -1: + do_analysis = False + pysms.sms_freeFrame(analysis_data) + current_frame += 1 + + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_free() + + # make sure we have the same number of results in each run + assert len(freqs1) == len(freqs2) + assert len(amps1) == len(amps2) + assert len(phases1) == len(phases2) + + for r in range(len(freqs1)): + # in each result, make sure that we have the same number amps, freqs and phases + assert len(freqs1[r]) == len(freqs2[r]) + assert len(amps1[r]) == len(amps2[r]) + assert len(phases1[r]) == len(phases2[r]) + # make sure that each partial has the same value + for p in range(len(freqs1[r])): + assert_almost_equals(freqs1[r][p], freqs2[r][p], self.FLOAT_PRECISION) + assert_almost_equals(amps1[r][p], amps2[r][p], self.FLOAT_PRECISION) + assert_almost_equals(phases1[r][p], phases2[r][p], self.FLOAT_PRECISION) + + def test_multi_simpl_partial_tracking(self): + """test_multi_simpl_partial_tracking + Test that running the simpl peak detection process twice in a row + produces the same results each time. This makes sure that results + are independent, and also helps to highlight any memory errors.""" + audio, sampling_rate = self.get_audio() + pd = simpl.SMSPeakDetection() + pd.max_peaks = self.max_peaks + pd.hop_size = self.hop_size + peaks = pd.find_peaks(audio)[0:self.num_frames] + pt = simpl.SMSPartialTracking() + pt.max_partials = self.max_peaks + frames1 = pt.find_partials(peaks) + del pd + del pt + # second run + audio, sampling_rate = self.get_audio() + pd = simpl.SMSPeakDetection() + pd.max_peaks = self.max_peaks + pd.hop_size = self.hop_size + peaks = pd.find_peaks(audio)[0:self.num_frames] + pt = simpl.SMSPartialTracking() + pt.max_partials = self.max_peaks + frames2 = pt.find_partials(peaks) + + # make sure we have the same number of partials in each run + assert len(frames1) == len(frames2) + for i in range(len(frames1)): + # make sure each partial is the same length + assert len(frames1[i].partials) == len(frames2[i].partials) + # make sure that the peaks in each partial have the same values + for p in range(len(frames1[i].partials)): + assert_almost_equals(frames1[i].partials[p].frequency, + frames2[i].partials[p].frequency, + self.FLOAT_PRECISION) + assert_almost_equals(frames1[i].partials[p].amplitude, + frames2[i].partials[p].amplitude, + self.FLOAT_PRECISION) + assert_almost_equals(frames1[i].partials[p].phase, + frames2[i].partials[p].phase, + self.FLOAT_PRECISION) + + def test_partial_tracking(self): + """test_partial_tracking + Compare pysms Partials with SMS partials.""" + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.iSizeSound = self.num_samples + analysis_params.nFrames = self.num_frames + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + sms_frames = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + # convert frame to floats for libsms + frame = simpl.Frame() + frame.size = size_new_data + frame.audio = np.array(audio[sample_offset:sample_offset + size_new_data], + dtype=np.float32) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + num_partials = analysis_data.nTracks + peaks = [] + status = pysms.sms_analyze(frame.audio, analysis_data, analysis_params) + + if status == 1: + sms_freqs = np.zeros(num_partials, dtype=np.float32) + sms_amps = np.zeros(num_partials, dtype=np.float32) + sms_phases = np.zeros(num_partials, dtype=np.float32) + analysis_data.getSinFreq(sms_freqs) + analysis_data.getSinAmp(sms_amps) + analysis_data.getSinPhase(sms_phases) + for i in range(num_partials): + p = simpl.Peak() + p.amplitude = sms_amps[i] + p.frequency = sms_freqs[i] + p.phase = sms_phases[i] + peaks.append(p) + frame.partials = peaks + sms_frames.append(frame) + current_frame += 1 + + if status == -1: + do_analysis = False + + pysms.sms_freeFrame(analysis_data) + + # first frame is blank + sms_frames = sms_frames[1:] + + # free sms memory + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_free() + + pd = simpl.SMSPeakDetection() + pd.max_peaks = self.max_peaks + pd.hop_size = self.hop_size + peaks = pd.find_peaks(audio) + pt = simpl.SMSPartialTracking() + pt.max_partials = self.max_partials + simpl_frames = pt.find_partials(peaks) + + # make sure both have the same number of partials + assert len(sms_frames) == len(simpl_frames) + + # make sure each partial is the same + for i in range(len(sms_frames)): + assert len(sms_frames[i].partials) == len(simpl_frames[i].partials) + for p in range(len(sms_frames[i].partials)): + assert_almost_equals(sms_frames[i].partials[p].amplitude, + simpl_frames[i].partials[p].amplitude, + self.FLOAT_PRECISION) + assert_almost_equals(sms_frames[i].partials[p].frequency, + simpl_frames[i].partials[p].frequency, + self.FLOAT_PRECISION) + assert_almost_equals(sms_frames[i].partials[p].phase, + simpl_frames[i].partials[p].phase, + self.FLOAT_PRECISION) + + def test_sms_interpolate_frames(self): + """test_sms_interpolate_frames + Make sure that sms_interpolateFrames returns the expected values + with interpolation factors of 0 and 1.""" + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + analysis_params.nFrames = self.num_frames + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.iSizeSound = self.num_samples + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + interp_frame = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, interp_frame) + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + analysis_frames = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + frame = audio[sample_offset:sample_offset + size_new_data] + # convert frame to floats for libsms + frame = np.array(frame, dtype=np.float32) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + status = pysms.sms_analyze(frame, analysis_data, analysis_params) + + if status == 1: + analysis_frames.append(analysis_data) + # test interpolateFrames on the last two analysis frames + if current_frame == self.num_frames - 1: + left_frame = analysis_frames[-2] + right_frame = analysis_frames[-1] + pysms.sms_interpolateFrames(left_frame, right_frame, interp_frame, 0) + # make sure that interp_frame == left_frame + # interpolateFrames doesn't interpolate phases so ignore + left_amps = np.zeros(self.max_partials, dtype=np.float32) + left_freqs = np.zeros(self.max_partials, dtype=np.float32) + left_frame.getSinAmp(left_amps) + left_frame.getSinFreq(left_freqs) + right_amps = np.zeros(self.max_partials, dtype=np.float32) + right_freqs = np.zeros(self.max_partials, dtype=np.float32) + right_frame.getSinAmp(right_amps) + right_frame.getSinFreq(right_freqs) + interp_amps = np.zeros(self.max_partials, dtype=np.float32) + interp_freqs = np.zeros(self.max_partials, dtype=np.float32) + interp_frame.getSinAmp(interp_amps) + interp_frame.getSinFreq(interp_freqs) + for i in range(self.max_partials): + assert_almost_equals(left_amps[i], interp_amps[i], + self.FLOAT_PRECISION) + if left_freqs[i] != 0: + assert_almost_equals(left_freqs[i], interp_freqs[i], + self.FLOAT_PRECISION) + else: + assert_almost_equals(right_freqs[i], interp_freqs[i], + self.FLOAT_PRECISION) + pysms.sms_interpolateFrames(left_frame, right_frame, interp_frame, 1) + interp_amps = np.zeros(self.max_partials, dtype=np.float32) + interp_freqs = np.zeros(self.max_partials, dtype=np.float32) + interp_frame.getSinAmp(interp_amps) + interp_frame.getSinFreq(interp_freqs) + for i in range(self.max_partials): + assert_almost_equals(right_amps[i], interp_amps[i], + self.FLOAT_PRECISION) + if right_freqs[i] != 0: + assert_almost_equals(right_freqs[i], interp_freqs[i], + self.FLOAT_PRECISION) + else: + assert_almost_equals(left_freqs[i], interp_freqs[i], + self.FLOAT_PRECISION) + elif status == -1: + raise Exception("AnalysisStoppedEarly") + else: + pysms.sms_freeFrame(analysis_data) + current_frame += 1 + + for frame in analysis_frames: + pysms.sms_freeFrame(frame) + pysms.sms_freeFrame(interp_frame) + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_free() + + def test_simplsms_interpolate_frames(self): + """test_simplsms_interpolate_frames + Make sure that sms_interpolateFrames returns the expected values + with interpolation factors of 0 and 1.""" + audio, sampling_rate = self.get_audio() + simplsms.sms_init() + analysis_params = self.simplsms_analysis_params(sampling_rate) + analysis_params.nFrames = self.num_frames + if simplsms.sms_initAnalysis(analysis_params) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.iSizeSound = self.num_samples + sms_header = simplsms.SMS_Header() + simplsms.sms_fillHeader(sms_header, analysis_params, "simplsms") + + interp_frame = simplsms.SMS_Data() + simplsms.sms_allocFrameH(sms_header, interp_frame) + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + analysis_frames = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + frame = audio[sample_offset:sample_offset + size_new_data] + analysis_data = simplsms.SMS_Data() + simplsms.sms_allocFrameH(sms_header, analysis_data) + status = simplsms.sms_analyze(frame, analysis_data, analysis_params) + + if status == 1: + analysis_frames.append(analysis_data) + # test interpolateFrames on the last two analysis frames + if current_frame == self.num_frames - 1: + left_frame = analysis_frames[-2] + right_frame = analysis_frames[-1] + simplsms.sms_interpolateFrames(left_frame, right_frame, interp_frame, 0) + # make sure that interp_frame == left_frame + # interpolateFrames doesn't interpolate phases so ignore + left_amps = simpl.zeros(self.max_partials) + left_freqs = simpl.zeros(self.max_partials) + left_frame.getSinAmp(left_amps) + left_frame.getSinFreq(left_freqs) + right_amps = simpl.zeros(self.max_partials) + right_freqs = simpl.zeros(self.max_partials) + right_frame.getSinAmp(right_amps) + right_frame.getSinFreq(right_freqs) + interp_amps = simpl.zeros(self.max_partials) + interp_freqs = simpl.zeros(self.max_partials) + interp_frame.getSinAmp(interp_amps) + interp_frame.getSinFreq(interp_freqs) + for i in range(self.max_partials): + assert_almost_equals(left_amps[i], interp_amps[i], + self.FLOAT_PRECISION) + if left_freqs[i] != 0: + assert_almost_equals(left_freqs[i], interp_freqs[i], + self.FLOAT_PRECISION) + else: + assert_almost_equals(right_freqs[i], interp_freqs[i], + self.FLOAT_PRECISION) + simplsms.sms_interpolateFrames(left_frame, right_frame, interp_frame, 1) + interp_amps = simpl.zeros(self.max_partials) + interp_freqs = simpl.zeros(self.max_partials) + interp_frame.getSinAmp(interp_amps) + interp_frame.getSinFreq(interp_freqs) + for i in range(self.max_partials): + assert_almost_equals(right_amps[i], interp_amps[i], + self.FLOAT_PRECISION) + if right_freqs[i] != 0: + assert_almost_equals(right_freqs[i], interp_freqs[i], + self.FLOAT_PRECISION) + else: + assert_almost_equals(left_freqs[i], interp_freqs[i], + self.FLOAT_PRECISION) + elif status == -1: + raise Exception("AnalysisStoppedEarly") + else: + simplsms.sms_freeFrame(analysis_data) + current_frame += 1 + + for frame in analysis_frames: + simplsms.sms_freeFrame(frame) + simplsms.sms_freeFrame(interp_frame) + simplsms.sms_freeAnalysis(analysis_params) + simplsms.sms_free() + + def test_harmonic_synthesis(self): + """test_harmonic_synthesis + Compare pysms synthesised harmonic component with SMS synthesised + harmonic component.""" + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + analysis_params.nFrames = self.num_frames + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.iSizeSound = self.num_samples + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + analysis_frames = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + frame = audio[sample_offset:sample_offset + size_new_data] + # convert frame to floats for libsms + frame = np.array(frame, dtype=np.float32) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + status = pysms.sms_analyze(frame, analysis_data, analysis_params) + if status == 1: + analysis_frames.append(analysis_data) + current_frame += 1 + elif status == 0: + pysms.sms_freeFrame(analysis_data) + elif status == -1: + do_analysis = False + pysms.sms_freeFrame(analysis_data) + + # remove the first frame, it's blank + blank_frame = analysis_frames[0] + analysis_frames = analysis_frames[1:] + pysms.sms_freeFrame(blank_frame) + + synth_params = self.pysms_synthesis_params(sampling_rate) + pysms.sms_initSynth(sms_header, synth_params) + + synth_samples = np.zeros(synth_params.sizeHop, dtype=np.float32) + sms_audio = np.array([], dtype=np.float32) + current_frame = 0 + + while current_frame < len(analysis_frames): + pysms.sms_synthesize(analysis_frames[current_frame], synth_samples, synth_params) + sms_audio = np.hstack((sms_audio, synth_samples)) + current_frame += 1 + + for frame in analysis_frames: + pysms.sms_freeFrame(frame) + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_freeSynth(synth_params) + pysms.sms_free() + + pd = simpl.SMSPeakDetection() + pd.max_peaks = self.max_peaks + pd.hop_size = self.hop_size + peaks = pd.find_peaks(audio) + pt = simpl.SMSPartialTracking() + pt.max_partials = self.max_partials + partials = pt.find_partials(peaks) + synth = simpl.SMSSynthesis() + synth.hop_size = self.hop_size + synth.max_partials = self.max_partials + synth.det_synthesis_type = simplsms.SMS_DET_IFFT + simpl_audio = synth.synth(partials) + + assert len(sms_audio) == len(simpl_audio) + for i in range(simpl_audio.size): + assert_almost_equals(sms_audio[i], simpl_audio[i], self.FLOAT_PRECISION) + + def test_harmonic_synthesis_sin(self): + """test_harmonic_synthesis_sin + Compare pysms synthesised harmonic component with SMS synthesised + harmonic component.""" + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.iSizeSound = self.num_samples + analysis_params.nFrames = self.num_frames + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + analysis_frames = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + frame = audio[sample_offset:sample_offset + size_new_data] + # convert frame to floats for libsms + frame = np.array(frame, dtype=np.float32) + if len(frame) < size_new_data: + frame = np.hstack((frame, np.zeros(size_new_data - len(frame), + dtype=np.float32))) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + status = pysms.sms_analyze(frame, analysis_data, analysis_params) + if status == 1: + analysis_frames.append(analysis_data) + current_frame += 1 + elif status == 0: + pysms.sms_freeFrame(analysis_data) + elif status == -1: + do_analysis = False + pysms.sms_freeFrame(analysis_data) + + # remove the first frame, it's blank + blank_frame = analysis_frames[0] + analysis_frames = analysis_frames[1:] + pysms.sms_freeFrame(blank_frame) + + synth_params = self.pysms_synthesis_params(sampling_rate) + synth_params.iDetSynthType = pysms.SMS_DET_SIN + pysms.sms_initSynth(sms_header, synth_params) + + synth_samples = np.zeros(synth_params.sizeHop, dtype=np.float32) + sms_audio = np.array([], dtype=np.float32) + current_frame = 0 + + while current_frame < len(analysis_frames): + pysms.sms_synthesize(analysis_frames[current_frame], synth_samples, synth_params) + sms_audio = np.hstack((sms_audio, synth_samples)) + current_frame += 1 + + for frame in analysis_frames: + pysms.sms_freeFrame(frame) + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_freeSynth(synth_params) + pysms.sms_free() + + pd = simpl.SMSPeakDetection() + pd.max_peaks = self.max_peaks + pd.hop_size = self.hop_size + peaks = pd.find_peaks(audio) + pt = simpl.SMSPartialTracking() + pt.max_partials = self.max_partials + partials = pt.find_partials(peaks) + synth = simpl.SMSSynthesis() + synth.hop_size = self.hop_size + synth.max_partials = self.max_partials + synth.det_synthesis_type = simplsms.SMS_DET_SIN + simpl_audio = synth.synth(partials) + + assert len(sms_audio) == len(simpl_audio) + for i in range(simpl_audio.size): + assert_almost_equals(sms_audio[i], simpl_audio[i], self.FLOAT_PRECISION) + + def test_residual_synthesis(self): + """test_residual_synthesis + Compare pysms residual signal with SMS residual""" + + # ------------------------------------------- + # This test is not finished yet. Skip for now + from nose.plugins.skip import SkipTest + raise SkipTest + # ------------------------------------------- + + audio, sampling_rate = self.get_audio() + pysms.sms_init() + snd_header = pysms.SMS_SndHeader() + # Try to open the input file to fill snd_header + if(pysms.sms_openSF(self.input_file, snd_header)): + raise NameError("error opening sound file: " + pysms.sms_errorString()) + analysis_params = self.pysms_analysis_params(sampling_rate) + analysis_params.nFrames = self.num_frames + analysis_params.nStochasticCoeff = 128 + analysis_params.iStochasticType = pysms.SMS_STOC_APPROX + if pysms.sms_initAnalysis(analysis_params, snd_header) != 0: + raise Exception("Error allocating memory for analysis_params") + analysis_params.iSizeSound = self.num_samples + sms_header = pysms.SMS_Header() + pysms.sms_fillHeader(sms_header, analysis_params, "pysms") + + sample_offset = 0 + size_new_data = 0 + current_frame = 0 + analysis_frames = [] + do_analysis = True + + while do_analysis and (current_frame < self.num_frames): + sample_offset += size_new_data + size_new_data = analysis_params.sizeNextRead + # convert frame to floats for libsms + frame = audio[sample_offset:sample_offset + size_new_data] + frame = np.array(frame, dtype=np.float32) + analysis_data = pysms.SMS_Data() + pysms.sms_allocFrameH(sms_header, analysis_data) + status = pysms.sms_analyze(frame, analysis_data, analysis_params) + analysis_frames.append(analysis_data) + if status == -1: + do_analysis = False + current_frame += 1 + + sms_header.nFrames = len(analysis_frames) + synth_params = self.pysms_synthesis_params(sampling_rate) + synth_params.iStochasticType = pysms.SMS_STOC_APPROX + synth_params.iSynthesisType = pysms.SMS_STYPE_STOC + pysms.sms_initSynth(sms_header, synth_params) + synth_samples = np.zeros(synth_params.sizeHop, dtype=np.float32) + sms_residual = np.array([], dtype=np.float32) + current_frame = 0 + + while current_frame < len(analysis_frames): + pysms.sms_synthesize(analysis_frames[current_frame], synth_samples, synth_params) + sms_residual = np.hstack((sms_residual, synth_samples)) + current_frame += 1 + + for frame in analysis_frames: + pysms.sms_freeFrame(frame) + pysms.sms_freeAnalysis(analysis_params) + pysms.sms_closeSF() + pysms.sms_freeSynth(synth_params) + pysms.sms_free() + + pd = simpl.SMSPeakDetection() + pd.max_peaks = self.max_peaks + pd.hop_size = self.hop_size + peaks = pd.find_peaks(audio)[0:self.num_frames] + pt = simpl.SMSPartialTracking() + pt.max_partials = self.max_partials + partials = pt.find_partials(peaks) + synth = simpl.SMSSynthesis() + synth.hop_size = self.hop_size + synth.max_partials = self.max_partials + simpl_harmonic = synth.synth(partials) + res = simpl.SMSResidual() + simpl_residual = res.synth(simpl_harmonic, audio[0:simpl_harmonic.size]) + + assert len(simpl_residual) == len(sms_residual) + for i in range(len(simpl_residual)): + assert_almost_equals(simpl_residual[i], sms_residual[i], + self.FLOAT_PRECISION) + + +if __name__ == "__main__": + # run individual tests programatically + # useful for debugging, particularly with GDB + import nose + argv = [__file__, + "--nocapture", + #__file__ + ":TestSimplSMS.test_residual_synthesis"] + __file__ + ":TestSimplSMS.test_harmonic_synthesis_sin"] + nose.run(argv=argv) |