commit a63175a99c62a0d07ccf4fa51c36e11b3bef0add
parent cee75e2bb82c9a8f9430164a7d5efe92ee581133
Author: zavok <an2qzavok@gmail.com>
Date: Mon, 4 Nov 2019 20:12:25 +0300
implemented polyphony
Diffstat:
M | fm.c | | | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
1 file changed, 53 insertions(+), 10 deletions(-)
diff --git a/fm.c b/fm.c
@@ -16,18 +16,46 @@ double tune[]={
30.87, //B 47
};
-size_t c, dt;
+size_t c;
int16_t vol;
+struct schan{
+ int id;
+ uint8_t note;
+ uint8_t velocity;
+};
+struct schan fm_sounds[32];
+
+int16_t fm_synth(int);
+int16_t fm_mix(void);
-int16_t fmsynth(void);
+int16_t
+fm_synth(int i)
+{
+ struct schan *sc;
+ sc = &fm_sounds[i];
+ if (sc->id < 0) return 0;
+ if (sc->velocity == 0) return 0;
+ size_t dt;
+ int16_t out;
+ out = 0x7fff * sc->velocity / 0xff;
+ dt = 44100.0 / (tune[sc->note%12] * (1 << (sc->note/12)));
+ if (c%dt > dt/2) out = -out;
+ return out;
+}
int16_t
-fm_synth(void)
+fm_mix(void)
{
+ int64_t out;
+ int i;
c++;
- if (dt == 0) return 0;
- if (c%dt > dt / 2) return vol;
- return -vol;
+ out = 0;
+ for (i=0; i<32; i++){
+ out += fm_synth(i);
+ }
+ if (out > 0x7fff) out = 0x7fff;
+ if (out < -0x7fff) out = -0x7fff;
+ return out;
}
void
@@ -35,19 +63,34 @@ fm_fillbuf(int16_t *buf, size_t nsamples)
{
size_t i;
for (i=0; i < nsamples; i+=2){
- buf[i] = buf[i+1] = fm_synth();
+ buf[i] = buf[i+1] = fm_mix();
}
}
void
fm_note_on(uint8_t *mm)
{
- dt = 44100.0 / (tune[mm[2]%12] * (1 << mm[2]/12));
- vol = 0x7fff * mm[3] / 0xff;
+ int i, nmin, nmax;
+ nmin = 32;
+ nmax = 32;
+ for (i=0;i<32;i++){
+ if (fm_sounds[i].id<fm_sounds[nmin].id) nmin = i;
+ if (fm_sounds[i].id>fm_sounds[nmax].id) nmax = i;
+ //if (fm_sounds[i].id<=0) break;
+ }
+ fm_sounds[nmin].id = nmax+1;
+ fm_sounds[nmin].note = mm[2];
+ fm_sounds[nmin].velocity = mm[3];
}
void
fm_note_off(uint8_t *mm)
{
- vol = 0;
+ int i;
+ for (i=0; i<32; i++){
+ if (fm_sounds[i].note == mm[2]){
+ fm_sounds[i].velocity = mm[3];
+ fm_sounds[i].id = -1;
+ }
+ }
}