summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--basetypes.py2
-rw-r--r--sms.py32
-rw-r--r--sms/synthesis.c6
-rw-r--r--tests/sms.py15
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)"
diff --git a/sms.py b/sms.py
index 1c0f794..77f8721 100644
--- a/sms.py
+++ b/sms.py
@@ -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)