1 /***************************************************************************/
2 /* */
3 /* Sound Source File */
4 /* */
5 /* Initialisation, shuting down and PC Engine generation of sound */
6 /* */
7 /***************************************************************************/
8
9 /* Header */
10
11 #include "utils.h"
12 #include "sound.h"
13
14 #if defined(SDL) && !defined(SDL_mixer)
15 #include <SDL_audio.h>
16 SDL_AudioSpec wanted; /* For SDL Audio */
17 extern void sdl_fill_audio(void *data, Uint8 *stream, int len);
18 #endif
19
20 #ifdef SDL_mixer
21 #include "osd_linux_sdl_music.h"
22 #endif
23
24 /* Variables definition */
25
26 UChar sound_driver = 1;
27 // 0 =-� No sound driver
28 // 1 =-� Allegro sound driver
29 // 2 =-� Seal sound driver
30 // 3 =-� SDL/SDL_Mixer driver
31
32 char MP3_playing = 0;
33 // is MP3 playing ?
34
35 char *sbuf[6];
36 // the buffer where the "DATA-TO-SEND-TO-THE-SOUND-CARD" go
37 // one for each channel
38
39 char *adpcmbuf;
40 // the buffer filled with adpcm data
41
42 UChar new_adpcm_play = 0;
43 // Have we begun a new adpcm sample (i.e. must be reset adpcm index/prev value)
44
45 unsigned char main_buf[SBUF_SIZE_BYTE];
46 // the mixed buffer, may be removed later for hard mixing...
47
48 UInt32 CycleOld;
49 UInt32 CycleNew;
50 // indicates the last time music has been "released"
51
52 /* TODO */
53 extern int BaseClock; // use value set in pce.c
54 // int BaseClock = 8992000;
55 // the freq of the internal PC Engine CPU
56 // the sound use a kind of "relative" frequency
57 // I think there's a pb with this value that cause troubles with some cd sync
58
59 UInt32 ds_nChannels = 1;
60 // mono or stereo, to remove later
61
62 UInt32 dwNewPos;
63
64 UInt32 AdpcmFilledBuf = 0;
65 // Size (in nibbles) of adpcm buf that has been filled with new data
66
67 #ifdef DJGPP
68
69 // SEAL sound related section
70
71 HAC hVoice;
72
73 LPAUDIOWAVE lpWave;
74
75 // End of SEAL sound related section
76
77 #endif
78
79
80 #ifdef ALLEGRO
81
82 // ALLEGRO sound related section
83
84 SAMPLE *CD_sample = NULL;
85
86 AUDIOSTREAM *PCM_stream;
87
88
89 #endif
90
91 UChar *big_buf;
92
93 UChar gen_vol = 255;
94
95 UInt32 sbuf_size = 10 * 1024;
96
97 // End of ALLEGRO sound related section
98
99
100
101 /* Functions definition */
102
InitSound(void)103 int InitSound(void)
104 {
105
106 sound_driver=3; // USE SDL!
107
108 for (silent = 0; silent < 6; silent++)
109 sbuf[silent] = (char *) calloc(sizeof(char), SBUF_SIZE_BYTE);
110
111 adpcmbuf = (char *) calloc(sizeof(char), SBUF_SIZE_BYTE);
112
113 silent = 1;
114
115 if (smode == 0) // No sound
116 return TRUE;
117
118 /* SDL Audio / Mixer Begin */
119 if (sound_driver == 3)
120 {
121 /*
122 #if defined(SDL) && !defined(SDL_mixer)
123 SDL_AudioSpec obtained;
124 Log ("Initialisation of SDL sound... ");
125 wanted.freq = option.want_snd_freq; // Frequency
126 printf("Frequency = %d\n", option.want_snd_freq);
127 wanted.format = AUDIO_U8; // Unsigned 8 bits
128 wanted.channels = 1; // Mono
129 wanted.samples = 512; //SBUF_SIZE_BYTE;
130 wanted.size = SBUF_SIZE_BYTE;
131 printf("wanted.size = %d\n",wanted.size);
132 wanted.callback = sdl_fill_audio;
133 wanted.userdata = main_buf;//NULL;
134
135 if (SDL_OpenAudio(&wanted,&obtained) < 0) {
136 printf("Couldn't Open SDL Audio: %s\n",SDL_GetError());
137 #endif // driver = 3 && SDL_mixer
138 if (Mix_OpenAudio(option.want_snd_freq,AUDIO_U8,1,512) < 0) {
139 printf("Couldn't Open SDL Mixer: %s\n",Mix_GetError());
140
141 return FALSE;
142 }
143
144 #if defined(SDL) && !defined(SDL_mixer)
145 Log ("OK\nObtained frequency = %d\n",obtained.freq);
146 SDL_PauseAudio(0);
147 #endif
148
149 silent=0;
150 Mix_Resume(-1);
151 */
152 silent = 0;
153
154 }
155 /* End of SDL Audio / Mixer */
156
157 #ifdef MSDOS
158 if (sound_driver == 2) // Seal Sound
159 {
160
161 Log ("Initialisation of SEAL sound\n");
162
163 AInitialize ();
164 // Init the SEAL library
165
166 if (smode == -1)
167 {
168 AUDIOCAPS caps;
169 UINT nDeviceId;
170
171 printf (MESSAGE[language][autodetect_mode]);
172
173 if (APingAudio (&nDeviceId) != AUDIO_ERROR_NONE)
174 {
175 printf (MESSAGE[language][no_device_found]);
176 return FALSE;
177 }
178 else
179 {
180 AGetAudioDevCaps (nDeviceId, &caps);
181 printf (MESSAGE[language][device_found], caps.szProductName);
182 silent = 0;
183 }
184 }
185 // Autodetection
186
187 Log ("SEAL : sound card autodetected\n");
188
189 // Now, we can really initialize the card
190 {
191 AUDIOINFO info;
192
193 info.nDeviceId = AUDIO_DEVICE_MAPPER;
194 info.wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO;
195 info.nSampleRate = option.want_snd_freq;
196 if (AOpenAudio (&info) != AUDIO_ERROR_NONE)
197 {
198 printf (MESSAGE[language][audio_init_failed]);
199 exit (1);
200 }
201 else
202 {
203 printf (MESSAGE[language][audio_inited],
204 info.wFormat & AUDIO_FORMAT_16BITS ? 16 : 8,
205 info.wFormat & AUDIO_FORMAT_STEREO ?
206 "stereo" : "mono", info.nSampleRate);
207 }
208 }
209
210 Log ("SEAL : sound card initiated\n");
211
212 fflush (stdout);
213 AOpenVoices (1);
214
215 ACreateAudioVoice (&hVoice);
216 ASetVoiceVolume (hVoice, 64);
217
218 {
219 /* first allocate structure to hold the waveform object */
220 if ((lpWave = (LPAUDIOWAVE) malloc (sizeof (AUDIOWAVE))) != NULL)
221 {
222 /* create a 8-bit mono one-shot waveform object */
223 lpWave->wFormat =
224 AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO | AUDIO_FORMAT_LOOP;
225 lpWave->nSampleRate = host.sound.freq;
226 lpWave->dwLength = SBUF_SIZE_BYTE;
227 lpWave->dwLoopStart = 0;
228 #if defined(DOUBLE_BUFFER)
229 lpWave->dwLoopEnd = 398;
230 #else
231 lpWave->dwLoopEnd = lpWave->dwLength;
232 #endif
233 if (ACreateAudioData (lpWave) != AUDIO_ERROR_NONE)
234 {
235 free (lpWave);
236 return FALSE;
237 }
238 /* copy the data into the waveform object */
239 memset (lpWave->lpData, 0x80, SBUF_SIZE_BYTE);
240 /* upload the data to the audio DRAM local memory */
241 AWriteAudioData (lpWave, 0L, lpWave->dwLength);
242 }
243 }
244
245 APlayVoice (hVoice, lpWave);
246 }
247 else
248 #endif
249
250 #ifdef ALLEGRO
251
252 if (sound_driver == 1) // Allegro sound
253 {
254
255 printf (MESSAGE[language][autodetect_mode]);
256
257 reserve_voices (2, 0);
258 // reserve 2 digital voices and no midi
259
260 Log ("Installing allegro driver\n");
261
262 /* install a digital sound driver */
263 if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL))
264 {
265 Log ("No sound card found\n");
266 printf (MESSAGE[language][no_device_found]);
267 return FALSE;
268 }
269
270 /* create an audio stream
271 //stream = play_audio_stream(SBUF_SIZE_BYTE, 8, FALSE, 22050, 255, 128);
272 PCM_sample = create_sample(8, 0, 11025, SBUF_SIZE_BYTE );
273 if (!PCM_sample) {
274 printf("Error creating sample!\n");
275 return FALSE;
276 }
277
278 // PCM_sample_b1 = PCM_sample->data;
279 // PCM_sample_b2 = PCM_sample->data + SBUF_SIZE_BYTE / 2;
280 // mid_pos = SBUF_SIZE_BYTE / 2;
281
282 // PCM_sample_lenght = SBUF_SIZE_BYTE;
283
284 // memset( PCM_sample_b1, SBUF_SIZE_BYTE, 0x80 );
285 memset(PCM_sample->data, SBUF_SIZE_BYTE, 0x80);
286
287 PCM_voice = allocate_voice(PCM_sample);
288 if (PCM_voice < 0) {
289 destroy_sample(PCM_sample);
290 return FALSE;
291 }
292
293 voice_set_playmode(PCM_voice, PLAYMODE_LOOP);
294 voice_set_volume(PCM_voice, 128);
295 voice_set_pan(PCM_voice, 128);
296 voice_start(PCM_voice);
297 */
298
299 big_buf = (unsigned char *) malloc (sbuf_size);
300
301 set_volume (gen_vol, 0);
302
303 PCM_stream =
304 play_audio_stream (sbuf_size, 8, FALSE, host.sound.freq, 128, 128);
305 if (!PCM_stream)
306 {
307 Log ("Error creating audio stream!\n");
308 return FALSE;
309 }
310
311 #ifdef MSDOS
312 install_amp ();
313 #endif
314
315 silent = 0;
316 }
317 #endif
318
319 return 0;
320 }
321
322 void
TrashSound(void)323 TrashSound (void) /* Shut down sound */
324 {
325 UChar dum;
326
327 if (!silent)
328 {
329 #ifdef MSDOS
330 if (sound_driver == 2) // Seal sound
331 {
332 AStopVoice (hVoice);
333 ADestroyAudioVoice (hVoice);
334 ACloseVoices ();
335 ACloseAudio ();
336 }
337 else
338 #endif
339
340 #ifdef ALLEGRO
341
342 if (sound_driver == 1)
343 {
344 stop_audio_stream (PCM_stream);
345
346 if (big_buf)
347 free (big_buf);
348
349 if (CD_sample)
350 destroy_sample (CD_sample);
351 #ifdef MSDOS
352 unload_amp ();
353 #endif
354 }
355
356 #endif
357
358 for (dum = 0; dum < 6; dum++)
359 free (sbuf[dum]);
360
361 free (adpcmbuf);
362
363 silent = 1;
364
365 }
366
367 }
368
369
370 void
write_psg(int ch)371 write_psg (int ch)
372 {
373 UInt32 Cycle;
374
375 if (CycleNew != CycleOld)
376 {
377 Cycle = CycleNew - CycleOld;
378 CycleOld = CycleNew;
379
380 dwNewPos =
381 (unsigned) ((float) (host.sound.freq) * (float) Cycle / (float) BaseClock);
382 // in fact, size of the data to write
383
384 };
385
386
387 #ifdef SOUND_DEBUG
388 Log ("Nouvelle pos : %d\n", dwNewPos);
389 #endif
390
391 /* SDL makes clipping automagicaly
392 * if (sound_driver == 3) {
393 if (dwNewPos > wanted.size) {
394 dwNewPos = wanted.size;
395 fprintf(stderr, "overrun: %d\n",dwNewPos);
396 }
397 }
398 */
399
400 if (sound_driver == 2) // || sound_driver == 3) /* Added 3 (SDL) */
401 {
402 if (dwNewPos > (UInt32) host.sound.freq * SOUND_BUF_MS / 1000)
403 {
404 #ifdef SOUND_DEBUG
405 fprintf (stderr, "sound buffer overrun\n");
406 #endif
407 dwNewPos = host.sound.freq * SOUND_BUF_MS / 1000;
408 // Ask it to fill the buffer
409 }
410 else if (sound_driver == 1)
411 {
412 #ifdef SOUND_DEBUG
413 Log ("dwNewPos = %d / %d\n", dwNewPos, sbuf_size);
414 #endif
415 if (dwNewPos > sbuf_size)
416 {
417 #ifdef SOUND_DEBUG
418 fprintf (stderr, "sound buffer overrun\n");
419 #endif
420 dwNewPos = sbuf_size;
421 // Ask it to fill the buffer
422 }
423
424 #ifdef SOUND_DEBUG
425 Log ("After correction, dwNewPos = %d\n", dwNewPos);
426 #endif
427
428 }
429 }
430
431 #ifdef SOUND_DEBUG
432 Log ("Buffer %d will be filled\n", ch);
433 #endif
434 Log ("Buffer %d will be filled\n", ch);
435 WriteBuffer (&sbuf[ch][0], ch, dwNewPos * ds_nChannels);
436 // write DATA 'til dwNewPos
437
438 #ifdef SOUND_DEBUG
439 Log ("Buffer %d has been filled\n", ch);
440 #endif
441
442
443 };
444
445 /* TODO : doesn't support repeat mode for now */
446
write_adpcm(void)447 void write_adpcm(void)
448 {
449 UInt32 Cycle;
450 UInt32 AdpcmUsedNibbles;
451
452 static SChar index;
453 static SInt32 previousValue;
454
455 if (CycleNew != CycleOld)
456 {
457 Cycle = CycleNew - CycleOld;
458 CycleOld = CycleNew;
459
460 dwNewPos =
461 (unsigned) ((float) (host.sound.freq) * (float) Cycle / (float) BaseClock);
462 // in fact, size of the data to write
463 };
464
465 AdpcmFilledBuf = dwNewPos;
466
467 if (new_adpcm_play)
468 {
469 index = 0;
470 previousValue = 0;
471 }
472
473 if (AdpcmFilledBuf > io.adpcm_psize)
474 AdpcmFilledBuf = io.adpcm_psize;
475
476 AdpcmUsedNibbles =
477 WriteBufferAdpcm8 (adpcmbuf,
478 io.adpcm_pptr, AdpcmFilledBuf, &index, &previousValue);
479
480 io.adpcm_pptr += AdpcmUsedNibbles;
481 io.adpcm_pptr &= 0x1FFFF;
482
483 if (AdpcmUsedNibbles)
484 io.adpcm_psize -= AdpcmUsedNibbles;
485 else
486 io.adpcm_psize = 0;
487 /* If we haven't played even a nibbles, it problably mean we won't ever be
488 * able to play one, so we stop the adpcm playing
489 */
490
491 #ifdef SOUND_DEBUG
492 // Log ("size = %d\n", io.adpcm_psize);
493 #endif
494
495 };
496
497 //! file for dumping audio
498 static FILE* audio_output_file = NULL;
499
500 //! Size (in byte) of audio data dumped
501 static int sound_dump_length;
502
503 //! Cycle of the last sound output
504 static UInt32 sound_dump_last_cycle;
505
506 //! Start the audio dump process
507 //! return 1 if audio dumping began, else 0
start_dump_audio(void)508 int start_dump_audio(void)
509 {
510 char audio_output_filename[PATH_MAX];
511 struct tm * tm_current_time;
512 time_t time_t_current_time;
513
514 if (audio_output_file != NULL)
515 return 0;
516
517 time(&time_t_current_time);
518 tm_current_time = localtime(&time_t_current_time);
519
520 snprintf(audio_output_filename, PATH_MAX, "%saudio-%04d-%02d-%02d %02d-%02d-%02d.wav",
521 video_path,
522 tm_current_time->tm_year + 1900,
523 tm_current_time->tm_mon + 1,
524 tm_current_time->tm_mday,
525 tm_current_time->tm_hour,
526 tm_current_time->tm_min,
527 tm_current_time->tm_sec);
528
529 audio_output_file = fopen(audio_output_filename, "wb");
530
531 sound_dump_length = 0;
532
533 fwrite ("RIFF\145\330\073\0WAVEfmt ", 16, 1,
534 audio_output_file);
535 putc (0x10, audio_output_file); // size
536 putc (0x00, audio_output_file);
537 putc (0x00, audio_output_file);
538 putc (0x00, audio_output_file);
539 putc (1, audio_output_file); // PCM data
540 putc (0, audio_output_file);
541
542 if (host.sound.stereo)
543 putc(2, audio_output_file); // stereo
544 else
545 putc (1, audio_output_file); // mono
546
547 putc (0, audio_output_file);
548
549 putc (host.sound.freq, audio_output_file); // frequency
550 putc (host.sound.freq >> 8, audio_output_file);
551 putc (host.sound.freq >> 16, audio_output_file);
552 putc (host.sound.freq >> 24, audio_output_file);
553
554 if (host.sound.stereo)
555 {
556 putc (host.sound.freq << 1, audio_output_file); // size of data per second
557 putc (host.sound.freq >> 7, audio_output_file);
558 putc (host.sound.freq >> 15, audio_output_file);
559 putc (host.sound.freq >> 23, audio_output_file);
560 }
561 else
562 {
563 putc (host.sound.freq, audio_output_file); // size of data per second
564 putc (host.sound.freq >> 8, audio_output_file);
565 putc (host.sound.freq >> 16, audio_output_file);
566 putc (host.sound.freq >> 24, audio_output_file);
567 }
568
569 if (host.sound.stereo)
570 putc (2, audio_output_file); // byte per sample
571 else
572 putc (1, audio_output_file);
573 putc (0, audio_output_file);
574
575 putc (8, audio_output_file); // 8 bits
576 putc (0, audio_output_file);
577
578 fwrite ("data\377\377\377\377", 1, 9,
579 audio_output_file);
580 osd_gfx_set_message (MESSAGE[language]
581 [dump_on]);
582
583 return (audio_output_file != NULL ? 1 : 0);
584 }
585
stop_dump_audio(void)586 void stop_dump_audio(void)
587 {
588 UInt32 dum;
589
590 if (audio_output_file == NULL)
591 return;
592
593 dum = sound_dump_length + 0x2C; // Total file size, header is 0x2C long
594 fseek (audio_output_file, 4, SEEK_SET);
595 putc(dum , audio_output_file);
596 putc(dum >> 8 , audio_output_file);
597 putc(dum >> 16, audio_output_file);
598 putc(dum >> 24, audio_output_file);
599
600 dum = sound_dump_length; // Audio stream size
601 fseek (audio_output_file, 0x28, SEEK_SET);
602 putc(dum , audio_output_file);
603 putc(dum >> 8 , audio_output_file);
604 putc(dum >> 16, audio_output_file);
605 putc(dum >> 24, audio_output_file);
606
607 fclose(audio_output_file);
608
609 osd_gfx_set_message (MESSAGE[language]
610 [dump_off]);
611 }
612
dump_audio_chunck(UChar * content,int length)613 void dump_audio_chunck(UChar* content, int length)
614 {
615 int cycle;
616 int real_length;
617
618 real_length = 0;
619
620 if (audio_output_file == NULL)
621 return;
622
623 if (CycleNew != sound_dump_last_cycle)
624 {
625 cycle = CycleNew - sound_dump_last_cycle;
626 sound_dump_last_cycle = CycleNew;
627
628 real_length = (unsigned) ((float) (host.sound.freq) * (float) cycle / (float) BaseClock);
629 // in fact, size of the data to write
630 };
631
632 printf("given length = %5d\treal length = %5d\n", length, real_length);
633
634 if (real_length > length)
635 real_length = length;
636
637 fwrite(content, real_length, 1, audio_output_file);
638
639 sound_dump_length += real_length;
640 }
641