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