Skip to content

Commit

Permalink
Merge pull request #278 from shorepine/piano_retrigger
Browse files Browse the repository at this point in the history
amy.c, oscillators.c: Avoid clicks when retriggering PARTIALs.
  • Loading branch information
dpwe authored Jan 17, 2025
2 parents 5799277 + c28b7ef commit 8207248
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 9 deletions.
8 changes: 5 additions & 3 deletions src/amy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,9 +1045,8 @@ void play_event(struct delta d) {

// if there was a filter active for this voice, reset it
if(synth[d.osc].filter_type != FILTER_NONE) reset_filter(d.osc);
// For repeatability, start at zero phase.
synth[d.osc].phase = 0;

// We no longer reset the phase here; instead, we reset phase when an oscillator falls silent.

// restart the waveforms
// Guess at the initial frequency depending only on const & note. Envelopes not "developed" yet.
float initial_logfreq = synth[d.osc].logfreq_coefs[COEF_CONST];
Expand Down Expand Up @@ -1306,7 +1305,10 @@ SAMPLE render_osc_wave(uint16_t osc, uint8_t core, SAMPLE* buf) {
} else {
if ( (total_samples - synth[osc].zero_amp_clock) >= MIN_ZERO_AMP_TIME_SAMPS) {
//printf("h&m: time %f osc %d OFF\n", total_samples/(float)AMY_SAMPLE_RATE, osc);
// Oscillator has fallen silent, stop executing it.
synth[osc].status = SYNTH_AUDIBLE_SUSPENDED; // It *could* come back...
// .. but force it to start at zero phase next time.
synth[osc].phase = 0;
}
}
} else if (max_val == 0) {
Expand Down
2 changes: 0 additions & 2 deletions src/oscillators.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,6 @@ void partial_note_on(uint16_t osc) {
float freq = freq_of_logfreq(msynth[osc].logfreq);
float period_samples = (float)AMY_SAMPLE_RATE / freq;
synth[osc].lut = choose_from_lutset(period_samples, sine_fxpt_lutset);
// Partials ramp up from zero.
msynth[osc].amp = 0;
}

void partial_note_off(uint16_t osc) {
Expand Down
25 changes: 21 additions & 4 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,30 @@ def run(self):
num_partials = 20
amy.send(time=0, osc=base_osc, wave=amy.INTERP_PARTIALS, patch=0)
for i in range(1, num_partials + 1):
# Set up each partial as the corresponding harmonic of the base_freq, with an amplitude of 1/N, 50ms attack, and a decay of 1 sec / N
amy.send(osc=base_osc + i, wave=amy.PARTIAL)
amy.send(time=50, osc=0, note=60, vel=0.1)
amy.send(time=300, osc=0, note=67, vel=0.6)
amy.send(time=550, osc=0, note=72, vel=1)
amy.send(time=800, osc=0, vel=0)

class TestInterpPartialsRetrigger(AmyTest):

def run(self):
# PARTIALS but each partial is interpolated from a table of pre-analyzed harmonic-sets.
base_osc = 0
num_partials = 20
amy.send(time=0, osc=base_osc, wave=amy.INTERP_PARTIALS, patch=0)
for i in range(1, num_partials + 1):
amy.send(osc=base_osc + i, wave=amy.PARTIAL)
amy.send(time=50, osc=0, note=52, vel=0.7)
amy.send(time=200, osc=0, note=52, vel=0.8)
amy.send(time=350, osc=0, note=52, vel=0.9)
amy.send(time=500, osc=0, vel=0)
amy.send(time=510, osc=40, wave=amy.SINE, bp0='3,1,500,0,50,0')
amy.send(time=550, osc=40, note=76, vel=1)
amy.send(time=700, osc=40, note=76, vel=1)
amy.send(time=850, osc=40, vel=0)

class TestSineEnv(AmyTest):

def run(self):
Expand Down Expand Up @@ -476,9 +493,9 @@ def run(self):
# Uses a 0.25Hz sine wave at 0.5 phase (going down) to modify frequency of another sine wave
amy.send(time=0, osc=1, wave=amy.SINE, amp=1, freq=0.25, phase=0.5)
amy.send(time=0, osc=0, wave=amy.SINE, bp0="0,1,500,0,0,0", freq="261.63,1,0,0,0,2", mod_source=1)
amy.send(time=100, osc=0, note=84, vel=1)
amy.send(time=350, osc=0, note=84, vel=1)
amy.send(time=600, osc=0, note=84, vel=1)
amy.send(time=100, osc=0, note=84, vel=1, phase=0)
amy.send(time=350, osc=0, note=84, vel=1, phase=0)
amy.send(time=600, osc=0, note=84, vel=1, phase=0)

class TestChainedOsc(AmyTest):
"""Two oscillators chained together."""
Expand Down
Binary file modified tests/ref/TestBuildYourOwnPartials.wav
Binary file not shown.
Binary file added tests/ref/TestInterpPartials.wav
Binary file not shown.
Binary file added tests/ref/TestInterpPartialsRetrigger.wav
Binary file not shown.

0 comments on commit 8207248

Please sign in to comment.