2022-10-14 12:36:14 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
add amplitude window
diff --git a/qms.c b/qms.c index f60ab37..a720386 100644 --- a/qms.c +++ b/qms.c @@ -10,15 +10,18 @@ typedef struct TrackState { typedef struct VoiceState { unsigned int phase_acc; /* fixed point with NEXP.16 precision */ unsigned int phase_step; /* fixed point with NEXP.16 precision */ - int velocity; /* 0x00-0x7F */ - int pitch; /* 0x00-0x7F */ - int wheel; /* S7.8 default (zero) means center */ - int note_age; /* for amplitude envelope */ + int velocity; /* 0x00-0x7F */ + int pitch; /* 0x00-0x7F */ + int wheel; /* S7.8 default (zero) means center */ + int note_age; /* for amplitude envelope */ + /* current computed amplitude (for smoothing) - left & right */ + int lamp, ramp; } VoiceState; static int16_t wavetables[NPACS][N]; static TrackState tracks[NTRACKS]; static VoiceState voices[NTRACKS][NVOICES]; +static int32_t windows[NTRACKS][NVOICES][K][2]; /* sine approximation using Bhaskara I's formula * input is in [0;2048] @@ -139,29 +142,41 @@ void qms_advance(unsigned int sample_i, unsigned int nsamples) { int32_t left, right; - int32_t amp; + int32_t wave_sample; int16_t *pac; - int lvol, rvol; /* 0 - 2^14 */ + int32_t tlamp, tramp; /* 0 - 2^14 */ + int32_t vamp; /* 0 - 2^14 */ + int32_t vlamp, vramp; /* 0 - 2^28 */ + int32_t *win_addr; TrackState *track; VoiceState *voice; int ti, vi; - for (; nsamples; nsamples--) { + for (; nsamples; nsamples--, sample_i++) { left = right = 0; for (ti = 0; ti < NTRACKS; ti++) { track = &tracks[ti]; - lvol = (63 - track->pan) * (127 - track->vol); - rvol = (63 + track->pan) * (127 - track->vol); + tlamp = (63 - track->pan) * (127 - track->vol); + tramp = (63 + track->pan) * (127 - track->vol); pac = wavetables[track->pac]; for (vi = 0; vi < NVOICES; vi++) { voice = &voices[ti][vi]; - amp = pac[voice->phase_acc >> 16]; - amp = amp * voice->velocity >> 7; - if (voice->note_age < 16) - amp = amp * (16 - voice->note_age++) >> 4; - else if (voice->note_age < track->atk + 16) - amp = amp * (voice->note_age++ - 16) / track->atk; - left += amp * lvol >> 14; - right += amp * rvol >> 14; + win_addr = windows[ti][vi][sample_i & (K-1)]; + vamp = voice->velocity; + if (voice->note_age++ < track->atk) + vamp = vamp * (voice->note_age * 0x7F / track->atk); + else + vamp = vamp * 0x7F; + vlamp = tlamp * vamp; + vramp = tramp * vamp; + voice->lamp += vlamp - win_addr[0]; + win_addr[0] = vlamp; + voice->ramp += vramp - win_addr[1]; + win_addr[1] = vramp; + wave_sample = pac[voice->phase_acc >> 16]; + //~ left += wave_sample * (vlamp >> 12) >> 16; + //~ right += wave_sample * (vramp >> 12) >> 16; + left += wave_sample * (voice->lamp >> 16) >> 16; + right += wave_sample * (voice->ramp >> 16) >> 16; voice->phase_acc += voice->phase_step; voice->phase_acc &= (1 << (NEXP + 16)) - 1; } diff --git a/qms.h b/qms.h index 5514eba..9780394 100644 --- a/qms.h +++ b/qms.h @@ -14,6 +14,8 @@ #define N (1 << NEXP) /* sample rate in samples per second*/ #define R 44100 +/* size of amplitude window in samples */ +#define K 16 typedef enum EvType {END, PAC, VOL, PAN, VEL, PITCH, WHEEL} EvType;