summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libayumi/ayumi.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libayumi/ayumi.c')
-rw-r--r--lib/rbcodec/codecs/libayumi/ayumi.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libayumi/ayumi.c b/lib/rbcodec/codecs/libayumi/ayumi.c
new file mode 100644
index 0000000000..2e0419f6cb
--- /dev/null
+++ b/lib/rbcodec/codecs/libayumi/ayumi.c
@@ -0,0 +1,361 @@
1/* Author: Peter Sovietov */
2
3#include <string.h>
4#include <math.h>
5#include "ayumi.h"
6
7static const double AY_dac_table[] = {
8 0.0, 0.0,
9 0.00999465934234, 0.00999465934234,
10 0.0144502937362, 0.0144502937362,
11 0.0210574502174, 0.0210574502174,
12 0.0307011520562, 0.0307011520562,
13 0.0455481803616, 0.0455481803616,
14 0.0644998855573, 0.0644998855573,
15 0.107362478065, 0.107362478065,
16 0.126588845655, 0.126588845655,
17 0.20498970016, 0.20498970016,
18 0.292210269322, 0.292210269322,
19 0.372838941024, 0.372838941024,
20 0.492530708782, 0.492530708782,
21 0.635324635691, 0.635324635691,
22 0.805584802014, 0.805584802014,
23 1.0, 1.0
24};
25
26static const double YM_dac_table[] = {
27 0.0, 0.0,
28 0.00465400167849, 0.00772106507973,
29 0.0109559777218, 0.0139620050355,
30 0.0169985503929, 0.0200198367285,
31 0.024368657969, 0.029694056611,
32 0.0350652323186, 0.0403906309606,
33 0.0485389486534, 0.0583352407111,
34 0.0680552376593, 0.0777752346075,
35 0.0925154497597, 0.111085679408,
36 0.129747463188, 0.148485542077,
37 0.17666895552, 0.211551079576,
38 0.246387426566, 0.281101701381,
39 0.333730067903, 0.400427252613,
40 0.467383840696, 0.53443198291,
41 0.635172045472, 0.75800717174,
42 0.879926756695, 1.0
43};
44
45static void reset_segment(struct ayumi* ay);
46
47double sqrt(double n)
48{
49 double x0 = n;
50 double x1;
51 for (;;) {
52 x1 = x0 - (x0 * x0 - n) / (2 * x0);
53 double delta = (x1 - x0) / x0;
54 if (delta < .000001 && delta > -.000001)
55 return x1;
56 x0 = x1;
57 }
58}
59
60static int update_tone(struct ayumi* ay, int index) {
61 struct tone_channel* ch = &ay->channels[index];
62 ch->tone_counter += 1;
63 if (ch->tone_counter >= ch->tone_period) {
64 ch->tone_counter = 0;
65 ch->tone ^= 1;
66 }
67 return ch->tone;
68}
69
70static int update_noise(struct ayumi* ay) {
71 int bit0x3;
72 ay->noise_counter += 1;
73 if (ay->noise_counter >= (ay->noise_period << 1)) {
74 ay->noise_counter = 0;
75 bit0x3 = ((ay->noise ^ (ay->noise >> 3)) & 1);
76 ay->noise = (ay->noise >> 1) | (bit0x3 << 16);
77 }
78 return ay->noise & 1;
79}
80
81static void slide_up(struct ayumi* ay) {
82 ay->envelope += 1;
83 if (ay->envelope > 31) {
84 ay->envelope_segment ^= 1;
85 reset_segment(ay);
86 }
87}
88
89static void slide_down(struct ayumi* ay) {
90 ay->envelope -= 1;
91 if (ay->envelope < 0) {
92 ay->envelope_segment ^= 1;
93 reset_segment(ay);
94 }
95}
96
97static void hold_top(struct ayumi* ay) {
98 (void) ay;
99}
100
101static void hold_bottom(struct ayumi* ay) {
102 (void) ay;
103}
104
105static void (* const Envelopes[][2])(struct ayumi*) = {
106 {slide_down, hold_bottom},
107 {slide_down, hold_bottom},
108 {slide_down, hold_bottom},
109 {slide_down, hold_bottom},
110 {slide_up, hold_bottom},
111 {slide_up, hold_bottom},
112 {slide_up, hold_bottom},
113 {slide_up, hold_bottom},
114 {slide_down, slide_down},
115 {slide_down, hold_bottom},
116 {slide_down, slide_up},
117 {slide_down, hold_top},
118 {slide_up, slide_up},
119 {slide_up, hold_top},
120 {slide_up, slide_down},
121 {slide_up, hold_bottom}
122};
123
124static void reset_segment(struct ayumi* ay) {
125 if (Envelopes[ay->envelope_shape][ay->envelope_segment] == slide_down
126 || Envelopes[ay->envelope_shape][ay->envelope_segment] == hold_top) {
127 ay->envelope = 31;
128 return;
129 }
130 ay->envelope = 0;
131}
132
133int update_envelope(struct ayumi* ay) {
134 ay->envelope_counter += 1;
135 if (ay->envelope_counter >= ay->envelope_period) {
136 ay->envelope_counter = 0;
137 Envelopes[ay->envelope_shape][ay->envelope_segment](ay);
138 }
139 return ay->envelope;
140}
141
142static void update_mixer(struct ayumi* ay) {
143 int i;
144 int out;
145 int noise = update_noise(ay);
146 int envelope = update_envelope(ay);
147 ay->left = 0;
148 ay->right = 0;
149 for (i = 0; i < TONE_CHANNELS; i += 1) {
150 out = (update_tone(ay, i) | ay->channels[i].t_off) & (noise | ay->channels[i].n_off);
151 out *= ay->channels[i].e_on ? envelope : ay->channels[i].volume * 2 + 1;
152 ay->left += ay->dac_table[out] * ay->channels[i].pan_left;
153 ay->right += ay->dac_table[out] * ay->channels[i].pan_right;
154 }
155}
156
157int ayumi_configure(struct ayumi* ay, int is_ym, double clock_rate, int sr) {
158 int i;
159 memset(ay, 0, sizeof(struct ayumi));
160 ay->step = clock_rate / (sr * 8 * DECIMATE_FACTOR);
161 ay->dac_table = is_ym ? YM_dac_table : AY_dac_table;
162 ay->noise = 1;
163 ayumi_set_envelope(ay, 1);
164 for (i = 0; i < TONE_CHANNELS; i += 1) {
165 ayumi_set_tone(ay, i, 1);
166 }
167 return ay->step < 1;
168}
169
170void ayumi_set_pan(struct ayumi* ay, int index, double pan, int is_eqp) {
171 if (is_eqp) {
172 ay->channels[index].pan_left = sqrt(1 - pan);
173 ay->channels[index].pan_right = sqrt(pan);
174 } else {
175 ay->channels[index].pan_left = 1 - pan;
176 ay->channels[index].pan_right = pan;
177 }
178}
179
180void ayumi_set_tone(struct ayumi* ay, int index, int period) {
181 period &= 0xfff;
182 ay->channels[index].tone_period = (period == 0) | period;
183}
184
185void ayumi_set_noise(struct ayumi* ay, int period) {
186 ay->noise_period = period & 0x1f;
187}
188
189void ayumi_set_mixer(struct ayumi* ay, int index, int t_off, int n_off, int e_on) {
190 ay->channels[index].t_off = t_off & 1;
191 ay->channels[index].n_off = n_off & 1;
192 ay->channels[index].e_on = e_on;
193}
194
195void ayumi_set_volume(struct ayumi* ay, int index, int volume) {
196 ay->channels[index].volume = volume & 0xf;
197}
198
199void ayumi_set_envelope(struct ayumi* ay, int period) {
200 period &= 0xffff;
201 ay->envelope_period = (period == 0) | period;
202}
203
204void ayumi_set_envelope_shape(struct ayumi* ay, int shape) {
205 ay->envelope_shape = shape & 0xf;
206 ay->envelope_counter = 0;
207 ay->envelope_segment = 0;
208 reset_segment(ay);
209}
210
211static double decimate(double* x) {
212 double y = -0.0000046183113992051936 * (x[1] + x[191]) +
213 -0.00001117761640887225 * (x[2] + x[190]) +
214 -0.000018610264502005432 * (x[3] + x[189]) +
215 -0.000025134586135631012 * (x[4] + x[188]) +
216 -0.000028494281690666197 * (x[5] + x[187]) +
217 -0.000026396828793275159 * (x[6] + x[186]) +
218 -0.000017094212558802156 * (x[7] + x[185]) +
219 0.000023798193576966866 * (x[9] + x[183]) +
220 0.000051281160242202183 * (x[10] + x[182]) +
221 0.00007762197826243427 * (x[11] + x[181]) +
222 0.000096759426664120416 * (x[12] + x[180]) +
223 0.00010240229300393402 * (x[13] + x[179]) +
224 0.000089344614218077106 * (x[14] + x[178]) +
225 0.000054875700118949183 * (x[15] + x[177]) +
226 -0.000069839082210680165 * (x[17] + x[175]) +
227 -0.0001447966132360757 * (x[18] + x[174]) +
228 -0.00021158452917708308 * (x[19] + x[173]) +
229 -0.00025535069106550544 * (x[20] + x[172]) +
230 -0.00026228714374322104 * (x[21] + x[171]) +
231 -0.00022258805927027799 * (x[22] + x[170]) +
232 -0.00013323230495695704 * (x[23] + x[169]) +
233 0.00016182578767055206 * (x[25] + x[167]) +
234 0.00032846175385096581 * (x[26] + x[166]) +
235 0.00047045611576184863 * (x[27] + x[165]) +
236 0.00055713851457530944 * (x[28] + x[164]) +
237 0.00056212565121518726 * (x[29] + x[163]) +
238 0.00046901918553962478 * (x[30] + x[162]) +
239 0.00027624866838952986 * (x[31] + x[161]) +
240 -0.00032564179486838622 * (x[33] + x[159]) +
241 -0.00065182310286710388 * (x[34] + x[158]) +
242 -0.00092127787309319298 * (x[35] + x[157]) +
243 -0.0010772534348943575 * (x[36] + x[156]) +
244 -0.0010737727700273478 * (x[37] + x[155]) +
245 -0.00088556645390392634 * (x[38] + x[154]) +
246 -0.00051581896090765534 * (x[39] + x[153]) +
247 0.00059548767193795277 * (x[41] + x[151]) +
248 0.0011803558710661009 * (x[42] + x[150]) +
249 0.0016527320270369871 * (x[43] + x[149]) +
250 0.0019152679330965555 * (x[44] + x[148]) +
251 0.0018927324805381538 * (x[45] + x[147]) +
252 0.0015481870327877937 * (x[46] + x[146]) +
253 0.00089470695834941306 * (x[47] + x[145]) +
254 -0.0010178225878206125 * (x[49] + x[143]) +
255 -0.0020037400552054292 * (x[50] + x[142]) +
256 -0.0027874356824117317 * (x[51] + x[141]) +
257 -0.003210329988021943 * (x[52] + x[140]) +
258 -0.0031540624117984395 * (x[53] + x[139]) +
259 -0.0025657163651900345 * (x[54] + x[138]) +
260 -0.0014750752642111449 * (x[55] + x[137]) +
261 0.0016624165446378462 * (x[57] + x[135]) +
262 0.0032591192839069179 * (x[58] + x[134]) +
263 0.0045165685815867747 * (x[59] + x[133]) +
264 0.0051838984346123896 * (x[60] + x[132]) +
265 0.0050774264697459933 * (x[61] + x[131]) +
266 0.0041192521414141585 * (x[62] + x[130]) +
267 0.0023628575417966491 * (x[63] + x[129]) +
268 -0.0026543507866759182 * (x[65] + x[127]) +
269 -0.0051990251084333425 * (x[66] + x[126]) +
270 -0.0072020238234656924 * (x[67] + x[125]) +
271 -0.0082672928192007358 * (x[68] + x[124]) +
272 -0.0081033739572956287 * (x[69] + x[123]) +
273 -0.006583111539570221 * (x[70] + x[122]) +
274 -0.0037839040415292386 * (x[71] + x[121]) +
275 0.0042781252851152507 * (x[73] + x[119]) +
276 0.0084176358598320178 * (x[74] + x[118]) +
277 0.01172566057463055 * (x[75] + x[117]) +
278 0.013550476647788672 * (x[76] + x[116]) +
279 0.013388189369997496 * (x[77] + x[115]) +
280 0.010979501242341259 * (x[78] + x[114]) +
281 0.006381274941685413 * (x[79] + x[113]) +
282 -0.007421229604153888 * (x[81] + x[111]) +
283 -0.01486456304340213 * (x[82] + x[110]) +
284 -0.021143584622178104 * (x[83] + x[109]) +
285 -0.02504275058758609 * (x[84] + x[108]) +
286 -0.025473530942547201 * (x[85] + x[107]) +
287 -0.021627310017882196 * (x[86] + x[106]) +
288 -0.013104323383225543 * (x[87] + x[105]) +
289 0.017065133989980476 * (x[89] + x[103]) +
290 0.036978919264451952 * (x[90] + x[102]) +
291 0.05823318062093958 * (x[91] + x[101]) +
292 0.079072012081405949 * (x[92] + x[100]) +
293 0.097675998716952317 * (x[93] + x[99]) +
294 0.11236045936950932 * (x[94] + x[98]) +
295 0.12176343577287731 * (x[95] + x[97]) +
296 0.125 * x[96];
297 memcpy(&x[FIR_SIZE - DECIMATE_FACTOR], x, DECIMATE_FACTOR * sizeof(double));
298 return y;
299}
300
301void ayumi_process(struct ayumi* ay) {
302 int i;
303 double y1;
304 double* c_left = ay->interpolator_left.c;
305 double* y_left = ay->interpolator_left.y;
306 double* c_right = ay->interpolator_right.c;
307 double* y_right = ay->interpolator_right.y;
308 double* fir_left = &ay->fir_left[FIR_SIZE - ay->fir_index * DECIMATE_FACTOR];
309 double* fir_right = &ay->fir_right[FIR_SIZE - ay->fir_index * DECIMATE_FACTOR];
310 ay->fir_index = (ay->fir_index + 1) % (FIR_SIZE / DECIMATE_FACTOR - 1);
311 for (i = DECIMATE_FACTOR - 1; i >= 0; i -= 1) {
312 ay->x += ay->step;
313 if (ay->x >= 1) {
314 ay->x -= 1;
315 y_left[0] = y_left[1];
316 y_left[1] = y_left[2];
317 y_left[2] = y_left[3];
318 y_right[0] = y_right[1];
319 y_right[1] = y_right[2];
320 y_right[2] = y_right[3];
321 update_mixer(ay);
322 y_left[3] = ay->left;
323 y_right[3] = ay->right;
324 y1 = y_left[2] - y_left[0];
325 c_left[0] = 0.5 * y_left[1] + 0.25 * (y_left[0] + y_left[2]);
326 c_left[1] = 0.5 * y1;
327 c_left[2] = 0.25 * (y_left[3] - y_left[1] - y1);
328 y1 = y_right[2] - y_right[0];
329 c_right[0] = 0.5 * y_right[1] + 0.25 * (y_right[0] + y_right[2]);
330 c_right[1] = 0.5 * y1;
331 c_right[2] = 0.25 * (y_right[3] - y_right[1] - y1);
332 }
333 fir_left[i] = (c_left[2] * ay->x + c_left[1]) * ay->x + c_left[0];
334 fir_right[i] = (c_right[2] * ay->x + c_right[1]) * ay->x + c_right[0];
335 }
336 ay->left = decimate(fir_left);
337 ay->right = decimate(fir_right);
338}
339
340void ayumi_seek(struct ayumi* ay) {
341 int i;
342 for (i = DECIMATE_FACTOR - 1; i >= 0; i -= 1) {
343 ay->x += ay->step;
344 if (ay->x >= 1) {
345 ay->x -= 1;
346 update_mixer(ay);
347 }
348 }
349}
350
351static double dc_filter(struct dc_filter* dc, int index, double x) {
352 dc->sum += -dc->delay[index] + x;
353 dc->delay[index] = x;
354 return x - dc->sum / DC_FILTER_SIZE;
355}
356
357void ayumi_remove_dc(struct ayumi* ay) {
358 ay->left = dc_filter(&ay->dc_left, ay->dc_index, ay->left);
359 ay->right = dc_filter(&ay->dc_right, ay->dc_index, ay->right);
360 ay->dc_index = (ay->dc_index + 1) & (DC_FILTER_SIZE - 1);
361}