1 #include "cydfm.h"
2 #include "cyddefs.h"
3 #include "freqs.h"
4 #include "cydosc.h"
5 #include "macros.h"
6 #include <stdlib.h>
7 #include <string.h>
8
9
10 #define MODULATOR_MAX 1024
11
12
cydfm_init(CydFm * fm)13 void cydfm_init(CydFm *fm)
14 {
15 memset(fm, 0, sizeof(*fm));
16 }
17
18
get_modulator(const CydEngine * cyd,const CydFm * fm)19 static Uint32 get_modulator(const CydEngine *cyd, const CydFm *fm)
20 {
21 const static Uint32 fbtab[] = { 0, 64, 32, 16, 8, 4, 2, 1 };
22
23 if ((fm->flags & CYD_FM_ENABLE_WAVE) && fm->wave_entry)
24 {
25 Uint32 acc = fm->wave.acc;
26 CydWaveAcc length = (CydWaveAcc)(fm->wave_entry->loop_end - fm->wave_entry->loop_begin) * WAVETABLE_RESOLUTION;
27
28 if (length == 0) return 0;
29
30 if (fm->feedback)
31 {
32 acc = acc + ((Uint64)(fm->fb1 + fm->fb2) / 2 * (length * 4 / fbtab[fm->feedback]) / MODULATOR_MAX);
33 }
34
35 return (Sint64)(cyd_wave_get_sample(&fm->wave, fm->wave_entry, acc % length)) * fm->env_output / 32768 + 65536;
36 }
37 else
38 {
39 Uint32 acc = fm->accumulator;
40 if (fm->feedback) acc += ((Uint64)(fm->fb1 + fm->fb2) / 2 * (ACC_LENGTH * 4 / fbtab[fm->feedback]) / MODULATOR_MAX);
41 return (Uint64)cyd_osc(CYD_CHN_ENABLE_TRIANGLE, acc % ACC_LENGTH, 0, 0, 0) * fm->env_output / WAVE_AMP + WAVE_AMP / 2;
42 }
43 }
44
45
cydfm_cycle_oversample(const CydEngine * cyd,CydFm * fm)46 void cydfm_cycle_oversample(const CydEngine *cyd, CydFm *fm)
47 {
48
49 }
50
51
cydfm_cycle(const CydEngine * cyd,CydFm * fm)52 void cydfm_cycle(const CydEngine *cyd, CydFm *fm)
53 {
54 cyd_cycle_adsr(cyd, 0, 0, &fm->adsr);
55
56 fm->env_output = cyd_env_output(cyd, 0, &fm->adsr, MODULATOR_MAX);
57
58 cyd_wave_cycle(&fm->wave, fm->wave_entry);
59
60 fm->accumulator = (fm->accumulator + fm->period) % ACC_LENGTH;
61
62 Uint32 mod = get_modulator(cyd, fm);
63
64 fm->fb2 = fm->fb1;
65 fm->fb1 = mod;
66 fm->current_modulation = mod;
67 }
68
69
cydfm_set_frequency(const CydEngine * cyd,CydFm * fm,Uint32 base_frequency)70 void cydfm_set_frequency(const CydEngine *cyd, CydFm *fm, Uint32 base_frequency)
71 {
72 const int MUL = 2;
73 static Sint32 harmonic[16] = { 0.5 * MUL, 1.0 * MUL, 2.0 * MUL, 3 * MUL, 4 * MUL, 5 * MUL, 6 * MUL, 7 * MUL, 8 * MUL, 9 * MUL, 10 * MUL, 10 * MUL, 12 * MUL, 12 * MUL, 15 * MUL, 15 * MUL };
74
75 fm->period = ((Uint64)(ACC_LENGTH)/16 * (Uint64)base_frequency / (Uint64)cyd->sample_rate) * (Uint64)harmonic[fm->harmonic & 15] / (Uint64)harmonic[fm->harmonic >> 4];
76
77 if (fm->wave_entry)
78 {
79 fm->wave.playing = true;
80 fm->wave.frequency = ((Uint64)(WAVETABLE_RESOLUTION) * (Uint64)fm->wave_entry->sample_rate / (Uint64)cyd->sample_rate * (Uint64)base_frequency / (Uint64)get_freq(fm->wave_entry->base_note)) * (Uint64)harmonic[fm->harmonic & 15] / (Uint64)harmonic[fm->harmonic >> 4];
81 }
82 }
83
84
cydfm_modulate(const CydEngine * cyd,const CydFm * fm,Uint32 accumulator)85 Uint32 cydfm_modulate(const CydEngine *cyd, const CydFm *fm, Uint32 accumulator)
86 {
87 Uint32 mod = (Uint64)fm->current_modulation * ACC_LENGTH * 8 / MODULATOR_MAX;
88
89 return (mod + accumulator) % ACC_LENGTH;
90 }
91
92
cydfm_modulate_wave(const CydEngine * cyd,const CydFm * fm,const CydWavetableEntry * wave,CydWaveAcc accumulator)93 CydWaveAcc cydfm_modulate_wave(const CydEngine *cyd, const CydFm *fm, const CydWavetableEntry *wave, CydWaveAcc accumulator)
94 {
95 if (wave->loop_begin == wave->loop_end)
96 return accumulator;
97
98 CydWaveAcc length = (CydWaveAcc)(wave->loop_end - wave->loop_begin) * WAVETABLE_RESOLUTION;
99 CydWaveAcc mod = (CydWaveAcc)fm->current_modulation * length * 8 / MODULATOR_MAX;
100
101 return (mod + accumulator) % length;
102 }
103
104
cydfm_set_wave_entry(CydFm * fm,const CydWavetableEntry * entry)105 void cydfm_set_wave_entry(CydFm *fm, const CydWavetableEntry * entry)
106 {
107 fm->wave_entry = entry;
108 fm->wave.frequency = 0;
109 fm->wave.direction = 0;
110 }
111