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