diff options
-rw-r--r-- | basetypes.py | 2 | ||||
-rw-r--r-- | sms.py | 32 | ||||
-rw-r--r-- | sms/synthesis.c | 6 | ||||
-rw-r--r-- | tests/sms.py | 15 |
4 files changed, 40 insertions, 15 deletions
diff --git a/basetypes.py b/basetypes.py index dd0da26..2a25688 100644 --- a/basetypes.py +++ b/basetypes.py @@ -80,6 +80,7 @@ class Partial(object): "Initialise peaks list and increment partial_id" self.peaks = [] self.starting_frame = 0 + self.partial_number = -1 self.partial_id = Partial._num_partials Partial._num_partials += 1 @@ -93,6 +94,7 @@ class Partial(object): peak.previous_peak = last_peak peak.partial_position = partial_position peak.partial_id = self.partial_id + peak.partial_number = self.partial_number def get_length(self): "Return the length of this partial (as a number of frames)" @@ -235,6 +235,8 @@ class SMSPartialTracking(simpl.PartialTracking): self._analysis_frame = simplsms.SMS_Data() simplsms.sms_allocFrameH(self._sms_header, self._analysis_frame) self.live_partials = [None for i in range(self.max_partials)] + #self._analysis_params.iDebugMode = simplsms.SMS_DBG_PEAK_CONT + self._analysis_params.nFrames = 20 def __del__(self): simplsms.sms_freeAnalysis(self._analysis_params) @@ -242,10 +244,16 @@ class SMSPartialTracking(simpl.PartialTracking): simplsms.sms_free() def set_max_partials(self, max_partials): + simplsms.sms_freeAnalysis(self._analysis_params) + simplsms.sms_freeFrame(self._analysis_frame) self._max_partials = max_partials self._analysis_params.maxPeaks = max_partials self._analysis_params.nTracks = max_partials self._analysis_params.nGuides = max_partials + if simplsms.sms_initAnalysis(self._analysis_params) != 0: + raise Exception("Error allocating memory for analysis_params") + simplsms.sms_fillHeader(self._sms_header, self._analysis_params, "simpl") + simplsms.sms_allocFrameH(self._sms_header, self._analysis_frame) def update_partials(self, frame, frame_number): "Streamable (real-time) partial-tracking." @@ -285,6 +293,7 @@ class SMSPartialTracking(simpl.PartialTracking): if not self.live_partials[i]: self.live_partials[i] = simpl.Partial() self.live_partials[i].starting_frame = frame_number + self.live_partials[i].partial_number = i self.partials.append(self.live_partials[i]) self.live_partials[i].add_peak(p) # if the mag is 0 and this partial was alive, kill it @@ -301,6 +310,7 @@ class SMSSynthesis(simpl.Synthesis): simpl.Synthesis.__init__(self) simplsms.sms_init() self._synth_params = simplsms.SMS_SynthParams() + simplsms.sms_initSynthParams(self._synth_params) self._synth_params.iDetSynthType = simplsms.SMS_DET_IFFT # use the default simpl hop size instead of the default SMS hop size self._synth_params.sizeHop = self._hop_size @@ -331,15 +341,19 @@ class SMSSynthesis(simpl.Synthesis): return self._synth_params.sizeHop def set_hop_size(self, hop_size): + simplsms.sms_freeSynth(self._synth_params) self._synth_params.sizeHop = hop_size + simplsms.sms_initSynth(self._synth_params) self._current_frame = simpl.zeros(self.hop_size) def get_max_partials(self): return self._synth_params.nTracks def set_max_partials(self, max_partials): - self._synth_params.nTracks = max_partials + simplsms.sms_freeSynth(self._synth_params) simplsms.sms_freeFrame(self._analysis_frame) + self._synth_params.nTracks = max_partials + simplsms.sms_initSynth(self._synth_params) simplsms.sms_allocFrame(self._analysis_frame, max_partials, self.num_stochastic_coeffs, 1, self.stochastic_type, 0) @@ -368,8 +382,10 @@ class SMSSynthesis(simpl.Synthesis): return self._synth_params.iStochasticType def set_stochastic_type(self, stochastic_type): - self._synth_params.iStochasticType = stochastic_type + simplsms.sms_freeSynth(self._synth_params) simplsms.sms_freeFrame(self._analysis_frame) + self._synth_params.iStochasticType = stochastic_type + simplsms.sms_initSynth(self._synth_params) simplsms.sms_allocFrame(self._analysis_frame, self.max_partials, self.num_stochastic_coeffs, 1, stochastic_type, 0) @@ -390,11 +406,13 @@ class SMSSynthesis(simpl.Synthesis): amps = simpl.zeros(self.max_partials) freqs = simpl.zeros(self.max_partials) phases = simpl.zeros(self.max_partials) - for i in range(self.max_partials): - if i < len(peaks): - amps[i] = peaks[i].amplitude - freqs[i] = peaks[i].frequency - phases[i] = peaks[i].phase + for i in range(len(peaks)): + p = peaks[i].partial_number + if p < 0: + p = i + amps[p] = peaks[i].amplitude + freqs[p] = peaks[i].frequency + phases[p] = peaks[i].phase self._analysis_frame.setSinAmp(amps) self._analysis_frame.setSinFreq(freqs) self._analysis_frame.setSinPha(phases) diff --git a/sms/synthesis.c b/sms/synthesis.c index 3a7682a..8a679ca 100644 --- a/sms/synthesis.c +++ b/sms/synthesis.c @@ -39,8 +39,8 @@ static void SineSynthIFFT(SMS_Data *pSmsData, SMS_SynthParams *pSynthParams) sfloat fMag=0.0, fFreq=0.0, fPhase=0.0, fLoc, fSin, fCos, fBinRemainder, fTmp, fNewMag, fIndex; sfloat fSamplingPeriod = 1.0 / pSynthParams->iSamplingRate; - memset (pSynthParams->pSpectra, 0, sizeFft * sizeof(sfloat)); - for (i = 0; i < nTracks; i++) + memset(pSynthParams->pSpectra, 0, sizeFft * sizeof(sfloat)); + for(i = 0; i < nTracks; i++) { if(((fMag = pSmsData->pFSinAmp[i]) > 0) && ((fFreq = (pSmsData->pFSinFreq[i])) < iHalfSamplingRate)) @@ -52,7 +52,7 @@ static void SineSynthIFFT(SMS_Data *pSmsData, SMS_SynthParams *pSynthParams) fMag = sms_dBToMag(fMag); fTmp = pSynthParams->prevFrame.pFSinPha[i] + - TWO_PI * fFreq * fSamplingPeriod * sizeMag; + TWO_PI * fFreq * fSamplingPeriod * sizeMag; fPhase = fTmp - floor(fTmp * INV_TWO_PI) * TWO_PI; fLoc = sizeFft * fFreq * fSamplingPeriod; iFirstBin = (int) fLoc - 3; diff --git a/tests/sms.py b/tests/sms.py index 76ad4ad..856ae88 100644 --- a/tests/sms.py +++ b/tests/sms.py @@ -26,7 +26,7 @@ class TestSimplSMS(object): input_file = 'audio/flute.wav' frame_size = 2048 hop_size = 512 - num_frames = 9 + num_frames = 20 num_samples = frame_size + ((num_frames - 1) * hop_size) max_peaks = 10 max_partials = 10 @@ -54,6 +54,7 @@ class TestSimplSMS(object): analysis_params.minGoodFrames = 1 analysis_params.iCleanTracks = 0 analysis_params.iStochasticType = pysms.SMS_STOC_NONE + #analysis_params.iDebugMode = pysms.SMS_DBG_PEAK_CONT return analysis_params def simplsms_analysis_params(self, sampling_rate): @@ -80,7 +81,9 @@ class TestSimplSMS(object): 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 return synth_params def test_size_next_read(self): @@ -466,7 +469,6 @@ class TestSimplSMS(object): 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 @@ -728,6 +730,7 @@ class TestSimplSMS(object): 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") @@ -769,6 +772,7 @@ class TestSimplSMS(object): if not live_partials[i]: live_partials[i] = simpl.Partial() live_partials[i].starting_frame = current_frame + live_partials[i].partial_number = i sms_partials.append(live_partials[i]) live_partials[i].add_peak(p) # if the mag is 0 and this partial was alive, kill it @@ -1056,9 +1060,9 @@ class TestSimplSMS(object): partials = pt.find_partials(peaks) synth = simpl.SMSSynthesis() synth.hop_size = self.hop_size - synth.stochastic_type = pysms.SMS_STOC_NONE - synth.synthesis_type = pysms.SMS_STYPE_DET synth.max_partials = self.max_partials + synth.stochastic_type = simplsms.SMS_STOC_NONE + synth.synthesis_type = simplsms.SMS_STYPE_DET simpl_audio = synth.synth(partials) assert len(sms_audio) == len(simpl_audio) @@ -1132,6 +1136,7 @@ if __name__ == "__main__": # useful for debugging, particularly with GDB import nose argv = [__file__, - __file__ + ":TestSimplSMS.test_residual_synthesis"] + __file__ + ":TestSimplSMS.test_partial_tracking"] + #__file__ + ":TestSimplSMS.test_residual_synthesis"] nose.run(argv=argv) |