Ticket #8233: spk2wav.c

File spk2wav.c, 26.4 KB (added by (none), 21 years ago)

spk2wav (or rather spk2dsp :)

Line 
1#include <stdio.h>
2#include <malloc.h>
3#include <math.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <fcntl.h>
7#include <linux/soundcard.h>
8
9#define SAMPLE_RATE 22050
10#define FREQ_HZ 236 /* Don't change! */
11#define FRAGMENTS ((2<<16) | 7)
12#define SAMPLE_LENGTH (SAMPLE_RATE / FREQ_HZ)
13
14#define AUTHENTIC_SOUND
15#define DECAY 0xf400 /* Depends on sample rate */
16#define PCJR_DECAY 0xd000 /* Depends on sample rate */
17
18int sound_fd;
19
20int pc_jr = 0;
21
22typedef unsigned short uint16;
23typedef short int16;
24typedef unsigned char uint8;
25typedef signed char int8;
26
27typedef struct _channel_info {
28 uint16 time_left;
29 uint16 next_cmd;
30 uint16 base_freq;
31 uint16 freq_delta;
32 uint16 freq;
33 uint16 volume;
34 uint16 volume_delta;
35 uint16 tempo;
36 uint16 inter_note_pause;
37 uint16 transpose;
38 uint16 note_length;
39 uint16 hull_curve;
40 uint16 hull_offset;
41 uint16 hull_counter;
42 uint16 freqmod_table;
43 uint16 freqmod_offset;
44 uint16 freqmod_incr;
45 uint16 freqmod_multiplier;
46 uint16 freqmod_modulo;
47 uint16 unknown[5];
48 uint16 music_script_nr;
49} channel_info;
50
51void debug_channel(channel_info *channel) {
52 fprintf(stdout, "chn: %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d\n",
53 channel->time_left, channel->next_cmd,
54 channel->base_freq, channel->freq_delta,
55 channel->freq, channel->volume,
56 channel->volume_delta, channel->tempo);
57 fprintf(stdout, " %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d\n",
58 channel->inter_note_pause, channel->transpose,
59 channel->note_length, channel->hull_curve,
60 channel->hull_offset, channel->hull_counter,
61 channel->freqmod_table, channel->freqmod_offset);
62 fprintf(stdout, " %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d\n",
63 channel->freqmod_incr, channel->freqmod_multiplier,
64 channel->freqmod_modulo, channel->unknown[0],
65 channel->unknown[1], channel->unknown[2],
66 channel->unknown[3], channel->unknown[4]);
67 fprintf(stdout, " %5d\n",
68 channel->music_script_nr);
69}
70
71
72channel_info channels[8];
73uint8 * retaddr;
74
75uint8 m_lfl[128];
76uint16 m_off[128];
77uint8 * music_script[128];
78
79uint8 note_lengths[] = {
80 0,
81 0, 0, 2,
82 0, 3, 4,
83 0, 6, 8,
84 0, 12, 16,
85 0, 24, 32,
86 0, 48, 64
87};
88
89uint16 hull_offsets[] = {
90 0, 12, 24, 36, 48, 60,
91 72, 88, 104, 120, 136, 240,
92 152, 164
93};
94
95int16 hulls[] = {
96 /* hull 0 */
97 3, -1, 0, 0, 0, 0, 0, 0,
98 0, -1, 0, 0,
99 /* hull 1 (staccato) */
100 3, -1, 0, 30, 0, -1, 0, 0,
101 0, -1, 0, 0,
102 /* hull 2 (legato) */
103 3, -1, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0,
105 /* hull 3 (staccatissimo) */
106 3, -1, 0, 2, 0, -1, 0, 0,
107 0, -1, 0, 0,
108 /* hull 4 */
109 3, -1, 0, 6, 0, -1, 0, 0,
110 0, -1, 0, 0,
111 /* hull 5 */
112 3, -1, 0, 10, 0, -1, 0, 0,
113 0, -1, 0, 0,
114 /* hull 6 */
115 60000, -1, -1000, 20, 0, 0, 0, 0,
116 40000, -1, -5000, 5, 0, -1, 0, 0,
117 /* hull 7 */
118 50000, -1, 0, 8, 30000, -1, 0, 0,
119 28000, -1, -5000, 5, 0, -1, 0, 0,
120 /* hull 8 */
121 60000, -1, -2000, 16, 0, 0, 0, 0,
122 28000, -1, -6000, 5, 0, -1, 0, 0,
123 /* hull 9 */
124 55000, -1, 0, 8, 35000, -1, 0, 0,
125 40000, -1, -2000, 10, 0, -1, 0, 0,
126 /* hull 10 */
127 60000, -1, 0, 4, -2000, 8, 0, 0,
128 40000, -1, -6000, 5, 0, -1, 0, 0,
129 /* hull 12 */
130 0, -1, 150, 340, -150, 340, 0, -1,
131 0, -1, 0, 0,
132 /* hull 13 == 164*/
133 20000, -1, 4000, 7, 1000, 15, 0, 0,
134 35000, -1, -2000, 15, 0, -1, 0, 0,
135
136 /* hull misc = 180 */
137 44000, -1, -4400, 10, 0, -1, 0, 0,
138 0, -1, 0, 0,
139
140 53000, -1, -5300, 10, 0, -1, 0, 0,
141 0, -1, 0, 0,
142
143 63000, -1, -6300, 10, 0, -1, 0, 0,
144 0, -1, 0, 0,
145
146 44000, -1, -1375, 32, 0, -1, 0, 0,
147 0, -1, 0, 0,
148
149 53000, -1, -1656, 32, 0, -1, 0, 0,
150 0, -1, 0, 0,
151
152 /* hull 11 == 240 */
153 63000, -1, -1968, 32, 0, -1, 0, 0,
154 0, -1, 0, 0,
155
156 44000, -1, - 733, 60, 0, -1, 0, 0,
157 0, -1, 0, 0,
158
159 53000, -1, - 883, 60, 0, -1, 0, 0,
160 0, -1, 0, 0,
161
162 63000, -1, -1050, 60, 0, -1, 0, 0,
163 0, -1, 0, 0,
164
165 44000, -1, - 488, 90, 0, -1, 0, 0,
166 0, -1, 0, 0,
167
168 53000, -1, - 588, 90, 0, -1, 0, 0,
169 0, -1, 0, 0,
170
171 63000, -1, - 700, 90, 0, -1, 0, 0,
172 0, -1, 0, 0
173
174};
175
176uint16 freqmod_lengths[] = {
177 0x1000, 0x1000, 0x20, 0x2000, 0x1000
178};
179
180uint16 freqmod_offsets[] = {
181 0, 0x100, 0x200, 0x302, 0x202
182};
183
184uint8 freqmod_table[0x502] = {
185 /* freqmod 1 */
186 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51,
187 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 80, 82, 85, 87, 89, 91, 94,
188 96, 98, 100, 102, 103, 105, 107, 108, 110, 112, 113, 114, 116, 117,
189 118, 119, 120, 121, 122, 123, 123, 124, 125, 125, 126, 126, 126, 126,
190 126, 126, 126, 126, 126, 126, 126, 125, 125, 124, 123, 123, 122, 121,
191 120, 119, 118, 117, 116, 114, 113, 112, 110, 108, 107, 105, 103, 102,
192 100, 98, 96, 94, 91, 89, 87, 85, 82, 80, 78, 75, 73, 70, 67, 65, 62,
193 59, 57, 54, 51, 48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12,
194 9, 6, 3, 0, 253, 250, 247, 244, 241, 238, 235, 232, 229, 226, 223, 220,
195 217, 214, 211, 208, 205, 202, 199, 197, 194, 191, 189, 186, 183, 181,
196 178, 176, 174, 171, 169, 167, 165, 162, 160, 158, 156, 154, 153, 151,
197 149, 148, 146, 144, 143, 142, 140, 139, 138, 137, 136, 135, 134, 133,
198 133, 132, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
199 130, 131, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 142,
200 143, 144, 146, 148, 149, 151, 153, 154, 156, 158, 160, 162, 165, 167,
201 169, 171, 174, 176, 178, 181, 183, 186, 189, 191, 194, 197, 199, 202,
202 205, 208, 211, 214, 217, 220, 223, 226, 229, 232, 235, 238, 241, 244,
203 247, 250, 253,
204
205 /*freqmod 2*/
206 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
207 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
208 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
209 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
210 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
211 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
212 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
213 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
214 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
215 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
216 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
217 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
218 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
219 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
220 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
221 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
222 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
223
224 /* freqmod 3 */
225 136, 120,
226 /* freqmod 4 */
227 136, 136, 136, 136, 136, 136, 136, 136,
228 136, 136, 136, 136, 136, 136, 136, 136,
229 136, 136, 136, 136, 136, 136, 136, 136,
230 136, 136, 136, 136, 136, 136, 136, 136,
231 136, 136, 136, 136, 136, 136, 136, 136,
232 136, 136, 136, 136, 136, 136, 136, 136,
233 136, 136, 136, 136, 136, 136, 136, 136,
234 136, 136, 136, 136, 136, 136, 136, 136,
235 136, 136, 136, 136, 136, 136, 136, 136,
236 136, 136, 136, 136, 136, 136, 136, 136,
237 136, 136, 136, 136, 136, 136, 136, 136,
238 136, 136, 136, 136, 136, 136, 136, 136,
239 136, 136, 136, 136, 136, 136, 136, 136,
240 136, 136, 136, 136, 136, 136, 136, 136,
241 136, 136, 136, 136, 136, 136, 136, 136,
242 136, 136, 136, 136, 136, 136, 136, 136,
243
244 120, 120, 120, 120, 120, 120, 120, 120,
245 120, 120, 120, 120, 120, 120, 120, 120,
246 120, 120, 120, 120, 120, 120, 120, 120,
247 120, 120, 120, 120, 120, 120, 120, 120,
248 120, 120, 120, 120, 120, 120, 120, 120,
249 120, 120, 120, 120, 120, 120, 120, 120,
250 120, 120, 120, 120, 120, 120, 120, 120,
251 120, 120, 120, 120, 120, 120, 120, 120,
252 120, 120, 120, 120, 120, 120, 120, 120,
253 120, 120, 120, 120, 120, 120, 120, 120,
254 120, 120, 120, 120, 120, 120, 120, 120,
255 120, 120, 120, 120, 120, 120, 120, 120,
256 120, 120, 120, 120, 120, 120, 120, 120,
257 120, 120, 120, 120, 120, 120, 120, 120,
258 120, 120, 120, 120, 120, 120, 120, 120,
259 120, 120, 120, 120, 120, 120, 120, 120,
260
261 41, 35, 190, 132, 225, 108, 214, 174,
262 82, 144, 73, 241, 241, 187, 233, 235,
263 179, 166, 219, 60, 135, 12, 62, 153,
264 36, 94, 13, 28, 6, 183, 71, 222,
265 179, 18, 77, 200, 67, 187, 139, 166,
266 31, 3, 90, 125, 9, 56, 37, 31,
267 93, 212, 203, 252, 150, 245, 69, 59,
268 19, 13, 137, 10, 28, 219, 174, 50,
269 32, 154, 80, 238, 64, 120, 54, 253,
270 18, 73, 50, 246, 158, 125, 73, 220,
271 173, 79, 20, 242, 68, 64, 102, 208,
272 107, 196, 48, 183, 50, 59, 161, 34,
273 246, 34, 145, 157, 225, 139, 31, 218,
274 176, 202, 153, 2, 185, 114, 157, 73,
275 44, 128, 126, 197, 153, 213, 233, 128,
276 178, 234, 201, 204, 83, 191, 103, 214,
277 191, 20, 214, 126, 45, 220, 142, 102,
278 131, 239, 87, 73, 97, 255, 105, 143,
279 97, 205, 209, 30, 157, 156, 22, 114,
280 114, 230, 29, 240, 132, 79, 74, 119,
281 2, 215, 232, 57, 44, 83, 203, 201,
282 18, 30, 51, 116, 158, 12, 244, 213,
283 212, 159, 212, 164, 89, 126, 53, 207,
284 50, 34, 244, 204, 207, 211, 144, 45,
285 72, 211, 143, 117, 230, 217, 29, 42,
286 229, 192, 247, 43, 120, 129, 135, 68,
287 14, 95, 80, 0, 212, 97, 141, 190,
288 123, 5, 21, 7, 59, 51, 130, 31,
289 24, 112, 146, 218, 100, 84, 206, 177,
290 133, 62, 105, 21, 248, 70, 106, 4,
291 150, 115, 14, 217, 22, 47, 103, 104,
292 212, 247, 74, 74, 208, 87, 104, 118,
293 250, 22, 187, 17, 173, 174, 36, 136,
294 121, 254, 82, 219, 37, 67, 229, 60,
295 244, 69, 211, 216, 40, 206, 11, 245,
296 197, 96, 89, 61, 151, 39, 138, 89,
297 118, 45, 208, 194, 201, 205, 104, 212,
298 73, 106, 121, 37, 8, 97, 64, 20,
299 177, 59, 106, 165, 17, 40, 193, 140,
300 214, 169, 11, 135, 151, 140, 47, 241,
301 21, 29, 154, 149, 193, 155, 225, 192,
302 126, 233, 168, 154, 167, 134, 194, 181,
303 84, 191, 154, 231, 217, 35, 209, 85,
304 144, 56, 40, 209, 217, 108, 161, 102,
305 94, 78, 225, 48, 156, 254, 217, 113,
306 159, 226, 165, 226, 12, 155, 180, 71,
307 101, 56, 42, 70, 137, 169, 130, 121,
308 122, 118, 120, 194, 99, 177, 38, 223,
309 218, 41, 109, 62, 98, 224, 150, 18,
310 52, 191, 57, 166, 63, 137, 94, 241,
311 109, 14, 227, 108, 40, 161, 30, 32,
312 29, 203, 194, 3, 63, 65, 7, 132,
313 15, 20, 5, 101, 27, 40, 97, 201,
314 197, 231, 44, 142, 70, 54, 8, 220,
315 243, 168, 141, 254, 190, 242, 235, 113,
316 255, 160, 208, 59, 117, 6, 140, 126,
317 135, 120, 115, 77, 208, 190, 130, 190,
318 219, 194, 70, 65, 43, 140, 250, 48,
319 127, 112, 240, 167, 84, 134, 50, 149,
320 170, 91, 104, 19, 11, 230, 252, 245,
321 202, 190, 125, 159, 137, 138, 65, 27,
322 253, 184, 79, 104, 246, 114, 123, 20,
323 153, 205, 211, 13, 240, 68, 58, 180,
324 166, 102, 83, 51, 11, 203, 161, 16,
325};
326
327uint16 *freqs_table;
328uint16 spk_freq_table[12] = {
329 36484, 34436, 32503, 30679, 29007, 27332,
330 25798, 24350, 22983, 21693, 20476, 19326
331};
332uint16 pcjr_freq_table[12] = {
333 65472, 61760, 58304, 55040, 52032, 49024,
334 46272, 43648, 41216, 38912, 36736, 34624
335};
336
337void execute_cmd(channel_info *channel) {
338 uint16 value;
339 int16 offset;
340 uint8 *script_ptr;
341 channel_info * current_channel;
342 channel_info * dest_channel;
343
344 current_channel = channel;
345
346 if (channel->next_cmd == 0)
347 return;
348 script_ptr = &music_script[channel->music_script_nr][channel->next_cmd];
349
350 for (;;) {
351 uint8 opcode = *script_ptr++;
352 if (opcode >= 0xf8) {
353 switch (opcode) {
354 case 0xf8: /* set hull curve */
355 printf("channel[%d]: hull curve %2d\n",
356 channel - channels, *script_ptr);
357 channel->hull_curve = hull_offsets[*script_ptr/2];
358 script_ptr++;
359 break;
360
361 case 0xf9: /* set freqmod curve */
362 printf("channel[%d]: freqmod curve %2d\n",
363 channel - channels, *script_ptr);
364 channel->freqmod_table = freqmod_offsets[*script_ptr/4];
365 channel->freqmod_modulo = freqmod_lengths[*script_ptr/4];
366 script_ptr++;
367 break;
368
369 case 0xfd: /* clear other channel */
370 value = *(int16*)script_ptr;
371 printf("clear channel %d\n", value/50);
372 script_ptr += 2;
373 channel = &channels[value / sizeof(channel_info)];
374 /* fall through */
375 case 0xfa: /* clear current channel */
376 if (opcode == 0xfa)
377 printf("clear channel\n");
378 channel->next_cmd = 0;
379 channel->base_freq = 0;
380 channel->freq_delta = 0;
381 channel->freq = 0;
382 channel->volume = 0;
383 channel->volume_delta = 0;
384 channel->inter_note_pause = 0;
385 channel->transpose = 0;
386 channel->hull_curve = 0;
387 channel->hull_offset = 0;
388 channel->hull_counter = 0;
389 channel->freqmod_table = 0;
390 channel->freqmod_offset = 0;
391 channel->freqmod_incr = 0;
392 channel->freqmod_multiplier = 0;
393 channel->freqmod_modulo = 0;
394 break;
395
396 case 0xfb: /* ret from subroutine */
397 printf("ret from sub\n");
398 script_ptr = retaddr;
399 break;
400 case 0xfc: /* call subroutine */
401 offset = *(int16*)script_ptr;
402 printf("subroutine %d\n", offset);
403 script_ptr += 2;
404 retaddr = script_ptr;
405 script_ptr = (void*)(int)offset;
406 printf("XXX1: %p -> %04x", script_ptr, offset);
407 break;
408 case 0xfe: /* loop music */
409 opcode = *script_ptr++;
410 offset = *(int16*)script_ptr;
411 script_ptr += 2;
412 printf("loop if %d to %d\n", opcode, offset);
413 if (! ((uint16*) channel)[opcode/2]
414 || --((uint16*) channel)[opcode/2])
415 script_ptr += offset;
416 break;
417
418 case 0xff: /* set parameter */
419 opcode = *script_ptr++;
420 value = *(uint16*)script_ptr;
421 ((uint16*) channel)[opcode/2] = value;
422 printf("channel[%d]: set param %2d = %5d\n",
423 channel - &channels[0], opcode, value);
424 script_ptr+=2;
425 if (opcode == 0)
426 goto end;
427 break;
428 }
429 } else { /* opcode < 0xf8 */
430 for (;;) {
431 int16 note, octave;
432 dest_channel = &channels[opcode >> 5];
433 channel->time_left = channel->tempo * note_lengths[opcode & 0x1f];
434 fprintf(stdout, "channel[%d]: @%04x note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s\n",
435 opcode>>5, script_ptr ? script_ptr - music_script[channel->music_script_nr] : 0,
436 *script_ptr & 0x7f, (signed short) dest_channel->transpose, opcode & 0x1f,
437 dest_channel->hull_curve, dest_channel->freqmod_table,
438 dest_channel->freqmod_incr,dest_channel->freqmod_multiplier,
439 *script_ptr & 0x80 ? "last":"");
440 opcode = *script_ptr++;
441 note = opcode & 0x7f;
442 if (note != 0x7f) {
443 uint16 freq;
444 dest_channel->time_left = channel->time_left;
445 dest_channel->note_length =
446 channel->time_left - dest_channel->inter_note_pause;
447 note += dest_channel->transpose;
448 while (note < 0)
449 note += 12;
450 octave = note / 12;
451 note = note % 12;
452 dest_channel->hull_offset = 0;
453 dest_channel->hull_counter = 1;
454 if (pc_jr && dest_channel == &channels[3]) {
455 dest_channel->hull_curve = 180 + note * 12;
456 freq = 384 - 64 * octave;
457 } else {
458 freq = freqs_table[note] >> octave;
459 }
460 dest_channel->freq = dest_channel->base_freq = freq;
461 }
462 if ((opcode & 0x80) != 0)
463 goto end;
464 opcode = *script_ptr++;
465 }
466 }
467 }
468 end:
469 channel = current_channel;
470 if (channel->time_left)
471 goto finish;
472#if 0
473 script_ptr = 0;
474 if (--fc8_c)
475 goto finish;
476
477 channel->next_cmd = 0;
478 sound_status[fc8_4]--;
479 fc8_4 = 0;
480 look_for_pending_sound();
481#endif
482 return;
483
484 finish:
485 channel->next_cmd = script_ptr -
486 music_script[channel->music_script_nr];
487 return;
488}
489
490
491
492void next_freqs(channel_info *channel) {
493 channel->volume += channel->volume_delta;
494 channel->base_freq += channel->freq_delta;
495
496 channel->freqmod_offset += channel->freqmod_incr;
497 if (channel->freqmod_offset > channel->freqmod_modulo)
498 channel->freqmod_offset -= channel->freqmod_modulo;
499 channel->freq =
500 (int) (freqmod_table[channel->freqmod_table + (channel->freqmod_offset >> 4)])
501 * (int) channel->freqmod_multiplier / 256
502 + channel->base_freq;
503#if 0
504 printf("Freq: %d/%d, %d/%d/%d*%d %d\n",
505 channel->base_freq, (int16)channel->freq_delta,
506 channel->freqmod_table, channel->freqmod_offset,
507 channel->freqmod_incr, channel->freqmod_multiplier,
508 channel->freq);
509#endif
510
511 if (channel->note_length && !--channel->note_length) {
512 channel->hull_offset += 16;
513 channel->hull_counter = 1;
514 }
515
516 if (!--channel->time_left) {
517 execute_cmd(channel);
518 }
519#if 0
520 fprintf(stdout, "channel[%d]: freq %d hull %d/%d/%d\n",
521 channel - &channels[0], channel->freq, channel->hull_curve, channel->hull_offset, channel->hull_counter);
522#endif
523
524 if (channel->hull_counter && !--channel->hull_counter) {
525 for (;;) {
526 int16 *hull_ptr = hulls
527 + channel->hull_curve + channel->hull_offset/2;
528 if (hull_ptr[1] == -1) {
529 channel->volume = hull_ptr[0];
530 if (hull_ptr[0] == 0)
531 channel->volume_delta = 0;
532 channel->hull_offset += 4;
533 } else {
534 channel->volume_delta = hull_ptr[0];
535 channel->hull_counter = hull_ptr[1];
536 channel->hull_offset += 4;
537 break;
538 }
539 }
540 }
541}
542
543#ifdef AUTHENTIC_SOUND
544/**
545 * This simulates the pc speaker sound, which is driven
546 * by the 8253 (square wave generator) and a low-band filter.
547 */
548void produce_spk_sound() {
549 int8 sample[SAMPLE_LENGTH];
550 static int sample_offset = 0;
551 static int last_freq=100;
552 int winning_channel = -1;
553 int i, j;
554 int freq;
555 static uint level = 0;
556 for (j = 0; j < SAMPLE_LENGTH; j++) {
557 sample[j] = 0;
558 }
559 for (i = 0; i < 4; i++) {
560 if (!channels[i].time_left)
561 continue;
562 next_freqs(&channels[i]);
563 if (winning_channel == -1
564 && channels[i].volume
565 && channels[i].time_left) {
566 winning_channel = i;
567 }
568 }
569 if (winning_channel != -1) {
570 freq = channels[winning_channel].freq;
571 } else {
572 freq = 0;
573 }
574
575 for (j = 0; j < SAMPLE_LENGTH; j++) {
576 level = (level * DECAY) >> 16;
577 if (sample_offset < freq*500)
578 level += 0xffff-DECAY;
579 sample[j] = (level >> 8);
580
581 sample_offset += 1193000*1000 / SAMPLE_RATE;
582 if (sample_offset >= last_freq*1000) {
583 sample_offset -= last_freq*1000;
584 last_freq = freq;
585 }
586 }
587
588#if 0
589 fprintf(stdout, "channel[%d]: freq %d ; %d\n", winning_channel, freq, sample_offset);
590#endif
591 fflush(stdout);
592 for (j = 0; j < SAMPLE_LENGTH;)
593 j += write(sound_fd, sample + j, SAMPLE_LENGTH - j);
594}
595
596#else
597void produce_spk_sound() {
598 int8 sample[SAMPLE_LENGTH];
599 static int sample_offset = 0;
600 int winning_channel = -1;
601 int i, j;
602 float freq, volume;
603 for (j = 0; j < SAMPLE_LENGTH; j++) {
604 sample[j] = 0;
605 }
606 for (i = 0; i < 4; i++) {
607 if (!channels[i].time_left)
608 continue;
609 next_freqs(&channels[i]);
610 if (winning_channel == -1
611 && channels[i].volume
612 && channels[i].time_left) {
613 winning_channel = i;
614 }
615 }
616 if (winning_channel != -1) {
617 i = winning_channel;
618 freq = channels[i].freq;
619 volume = channels[i].volume;
620 volume /= 3.0;
621 freq = 1193000 / freq;
622
623
624 for (j = 0; j < SAMPLE_LENGTH; j++) {
625 sample[j] += (int8)
626 (volume * 100
627#ifdef SAEGEZAHN
628 * (sample_offset < SAMPLE_RATE/2
629 ? sample_offset - SAMPLE_RATE/4
630 : 3*SAMPLE_RATE/4 - sample_offset) /(SAMPLE_RATE/4)
631#elif defined(RECHTECK)
632 * (sample_offset < SAMPLE_RATE/2 ? 1 : -1)
633#else
634 * sin((double)sample_offset*2*3.145926 / SAMPLE_RATE)
635#endif
636 );
637 sample_offset += freq;
638 sample_offset %= SAMPLE_RATE;
639 }
640
641#if 0
642 fprintf(stdout, "channel[%d]: freq %d = %0f ; volume %f %d\n", i, channels[i].freq, freq, volume, sample_offset);
643#endif
644 }
645 fflush(stdout);
646 for (j = 0; j < SAMPLE_LENGTH;)
647 j += write(sound_fd, sample + j, SAMPLE_LENGTH - j);
648}
649#endif
650
651#define STEP 0x10000
652#define UPDATESTEP ((STEP * SAMPLE_RATE) / (111860*2))
653#define MAX_OUTPUT 0x7fff
654
655#define FB_WNOISE 0x12000 /* bit15.d(16bits) = bit0(out) ^ bit2 */
656#define FB_PNOISE 0x08000 /* JH 981127 - fixes Do Run Run */
657#define NG_PRESET 0x0f35
658
659int SN76496_count[4];
660int SN76496_output[4];
661int SN76496_voltable[16];
662
663void init_pcjr()
664{
665 int i;
666 double out;
667 int gain;
668 /* increase max output basing on gain (0.2 dB per step) */
669 out = MAX_OUTPUT / 3;
670 gain = 10;
671 while (gain-- > 0)
672 out *= 1.023292992; /* = (10 ^ (0.2/20)) */
673 /* build volume table (2dB per step) */
674 for (i = 0; i < 15; i++) {
675 /* limit volume to avoid clipping */
676 if (out > MAX_OUTPUT / 3)
677 SN76496_voltable[i] = MAX_OUTPUT / 3;
678 else
679 SN76496_voltable[i] = out;
680 printf("%2d: %4x\n", i, SN76496_voltable[i]);
681 out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */
682 }
683 SN76496_voltable[15] = 0;
684}
685
686void produce_pcjr_sound() {
687 uint16 sample[SAMPLE_LENGTH];
688 int i, j;
689 uint16 freq, vol;
690 static int16 lastvol = 0;
691 memset(sample, 0, sizeof(sample));
692 for (i = 0; i < 4; i++) {
693 if (!channels[i].time_left)
694 continue;
695 next_freqs(&channels[i]);
696
697 freq = channels[i].freq >> 6;
698 vol = (65535 - channels[i].volume) >> 12;
699 if (!channels[i].volume
700 && !channels[i].time_left) {
701 if (SN76496_count[i] >= SAMPLE_LENGTH * STEP)
702 SN76496_count[i] -= STEP * SAMPLE_LENGTH;
703 } else if (i < 3) {
704 int period = UPDATESTEP * freq;
705 if (period == 0)
706 period = UPDATESTEP;
707
708 for (j = 0; j < SAMPLE_LENGTH; j++) {
709 unsigned int volume = 0;
710
711 if (SN76496_output[i])
712 volume += SN76496_count[i];
713
714 SN76496_count[i] -= STEP;
715 while (SN76496_count[i] <= 0) {
716 SN76496_count[i] += period;
717 if (SN76496_count[i] > 0) {
718 SN76496_output[i] ^= 1;
719 if (SN76496_output[i])
720 volume += period;
721 break;
722 }
723 SN76496_count[i] += period;
724 volume += period;
725 }
726
727 if (SN76496_output[i])
728 volume -= SN76496_count[i];
729 volume *= SN76496_voltable[vol];
730 sample[j] += volume / STEP;
731 }
732 } else {
733 int left, period, RNG, NoiseFB;
734
735 int n = (freq & 3);
736 if (n == 3) {
737 period = 2 * UPDATESTEP * (channels[2].freq>>6);
738 if (!period)
739 period = 2 * UPDATESTEP;
740 } else
741 period = UPDATESTEP << (5 + n);
742
743 RNG = NG_PRESET;
744 NoiseFB = (freq & 4) ? FB_WNOISE : FB_PNOISE;
745 SN76496_output[3] = RNG & 1;
746
747 for (j = 0; j < SAMPLE_LENGTH; j++) {
748 unsigned int volume = 0;
749
750 if (SN76496_output[3])
751 volume += SN76496_count[3];
752 SN76496_count[3] -= STEP;
753 while (SN76496_count[3] <= 0) {
754 if (RNG & 1)
755 RNG ^= NoiseFB;
756 RNG >>= 1;
757 SN76496_output[3] = RNG & 1;
758 SN76496_count[3] += period;
759 if (SN76496_output[3])
760 volume += period;
761 }
762 if (SN76496_output[3])
763 volume -= SN76496_count[3];
764
765 volume *= SN76496_voltable[vol];
766 sample[j] += volume / STEP;
767 }
768 }
769#if 0
770 fprintf(stdout, "channel[%d]: freq %d %.1f ; volume %d \n", i, freq, 111860.0/freq, vol);
771#endif
772 }
773 for (j = 0; j < SAMPLE_LENGTH; j++) {
774 lastvol = ((int)lastvol * PCJR_DECAY + (int)sample[j] * (0x10000-PCJR_DECAY)) >> 16;
775 sample[j] = lastvol;
776 }
777
778 fflush(stdout);
779 for (j = 0; j < 2*SAMPLE_LENGTH;)
780 j += write(sound_fd, sample + j, 2*SAMPLE_LENGTH - j);
781#if 0
782 for (j = 0; j < 2*SAMPLE_LENGTH;)
783 j += write(3, sample + j, 2*SAMPLE_LENGTH - j);
784#endif
785}
786
787
788void init_channel(channel_info *channel) {
789 channel->next_cmd = 0;
790 channel->base_freq = 0;
791 channel->freq_delta = 0;
792 channel->freq = 0;
793 channel->volume = 0;
794 channel->volume_delta = 0;
795 channel->inter_note_pause = 0;
796 channel->transpose = 0;
797 channel->hull_curve = 0;
798 channel->hull_offset = 0;
799 channel->hull_counter = 0;
800 channel->freqmod_table = 0;
801 channel->freqmod_offset = 0;
802 channel->freqmod_incr = 0;
803 channel->freqmod_multiplier = 0;
804 channel->freqmod_modulo = 0;
805 channel->unknown[0] = 0;
806 channel->unknown[1] = 0;
807 channel->unknown[2] = 0;
808 channel->unknown[3] = 0;
809 channel->unknown[4] = 0;
810 channel->tempo = 0;
811 channel->note_length = 0;
812}
813
814
815void load_music(int nr) {
816 int i;
817 uint16 *music = (uint16*) music_script[nr];
818 int offset = pc_jr ? 7 : 3;
819 for (i = 0; i< 4; i++) {
820 init_channel(&channels[i]);
821 if (music[offset+i]) {
822 channels[i].music_script_nr = nr;
823 channels[i].next_cmd = music[offset+i];
824 channels[i].time_left = 1;
825 }
826 }
827
828 while (channels[0].time_left
829 || channels[1].time_left
830 || channels[2].time_left
831 || channels[3].time_left) {
832 if (pc_jr)
833 produce_pcjr_sound();
834 else
835 produce_spk_sound();
836 }
837}
838
839void read_level0() {
840 FILE * file;
841 uint8 b;
842 uint16 w;
843 int i;
844 file = fopen("00.lfl", "rb");
845
846 fread(&w, 2, 1, file);
847 w ^= 0xffff;
848
849 /* skip object */
850 fread(&w, 2, 1, file);
851 w ^= 0xffff;
852 fseek(file, w, SEEK_CUR);
853
854 /* skip unknowns */
855 fread(&b, 1, 1, file);
856 b ^= 0xff;
857 fseek(file, 3*b, SEEK_CUR);
858
859 /* skip costumes */
860 fread(&b, 1, 1, file);
861 b ^= 0xff;
862 fseek(file, 3*b, SEEK_CUR);
863
864 /* skip scripts */
865 fread(&b, 1, 1, file);
866 b ^= 0xff;
867 fseek(file, 3*b, SEEK_CUR);
868
869 /* read music */
870 fread(&b, 1, 1, file);
871 b ^= 0xff;
872 fread(&m_lfl, 1, b, file);
873 fread(&m_off, 2, b, file);
874 for (i = 0; i < b; i++) {
875 m_lfl[i] ^= 0xff;
876 m_off[i] ^= 0xffff;
877 }
878 fclose(file);
879}
880
881void read_music(int nr) {
882 char lvl[20];
883 FILE * file;
884 int i;
885 uint16 len;
886 sprintf(lvl, "%02d.lfl", m_lfl[nr]);
887 printf("Opening %s\n", lvl);
888 file = fopen(lvl, "rb");
889 fseek(file, m_off[nr], SEEK_CUR);
890 fread(&len, 2, 1, file);
891 len ^= 0xffff;
892 music_script[nr] = malloc(len);
893 fseek(file, -2, SEEK_CUR);
894 fread(music_script[nr], 1, len, file);
895 for (i = 0; i < len; i++)
896 music_script[nr][i] ^= 0xff;
897 fclose(file);
898}
899
900void open_sound() {
901 int param;
902#ifndef WRITE_TO_RAW_FILE
903 sound_fd = open("/dev/dsp", O_WRONLY);
904
905 param = FRAGMENTS;
906 ioctl(sound_fd, SNDCTL_DSP_SETFRAGMENT, &param);
907 printf ("Frags %d, ", param);
908 param = pc_jr ? AFMT_S16_LE : AFMT_U8;
909 ioctl(sound_fd, SNDCTL_DSP_SETFMT, &param);
910 printf ("Format %d, ", param);
911 param = 1;
912 ioctl(sound_fd, SNDCTL_DSP_CHANNELS, &param);
913 printf ("channels %d, ", param);
914
915 param = SAMPLE_RATE;
916 ioctl(sound_fd, SNDCTL_DSP_SPEED, &param);
917 printf ("Sample rate: %d\n", param);
918#else
919 sound_fd = open("intro.raw", O_CREAT|O_WRONLY, 0666);
920#endif
921}
922
923int main(int argc, char** argv) {
924 int nr, i;
925 if (argc > 2)
926 pc_jr = 1;
927 open_sound();
928 read_level0();
929 if (argc > 1)
930 nr = atoi(argv[1]);
931 else
932 nr = 95;
933 srand(1234);
934 /* freqmod_table[302-502] contains random values. This code replaces
935 this with different ones. Try it and say whether you hear the difference.
936 for (i = 0x302; i < 0x502; i++)
937 freqmod_table[i] = (rand()>> 8) & 0xff;
938 */
939 read_music(nr);
940 if (pc_jr)
941 init_pcjr();
942
943 freqs_table = pc_jr ? pcjr_freq_table : spk_freq_table;
944
945 load_music(nr);
946 return 0;
947}
948