|
|
1.1 root 1: /*
2: Hatari - audio.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: This file contains the routines which pass the audio data to the SDL library.
8: */
9:
10: #include <SDL.h>
11:
12: #include "main.h"
13: #include "audio.h"
14: #include "configuration.h"
15: #include "memAlloc.h"
16: #include "misc.h"
1.1.1.2 ! root 17: #include "../m68000.h"
1.1 root 18:
19: #define SND_FREQ 22050
20:
21: /* Converted frontier SFX to wav samples. */
22: #define MAX_SAMPLES 33
23: #define MAX_CHANNELS 4
24:
25: typedef struct wav_stream {
26: Uint8 *buf;
27: int buf_pos;
28: int buf_len;
29: int loop; /* -1 no loop, otherwise specifies loop start pos */
30: } wav_stream;
31:
32: wav_stream sfx_buf[MAX_SAMPLES];
33: wav_stream wav_channels[MAX_CHANNELS];
34:
1.1.1.2 ! root 35: void Call_PlaySFX ()
1.1 root 36: {
37: int sample, chan;
38:
39: SDL_LockAudio ();
40:
1.1.1.2 ! root 41: sample = (short) GetReg (REG_D0);
! 42: chan = (short) GetReg (REG_D1);
1.1 root 43: //printf ("Playing sample %d on channel %d.\n", sample, chan);
44:
45: wav_channels[chan].buf_pos = 0;
46: wav_channels[chan].buf_len = sfx_buf[sample].buf_len;
47: wav_channels[chan].buf = sfx_buf[sample].buf;
48: wav_channels[chan].loop = sfx_buf[sample].loop;
49:
50: SDL_UnlockAudio ();
51: }
52:
53: void Audio_Reset ()
54: {
55: int i;
56: SDL_LockAudio ();
57: for (i=0; i<MAX_CHANNELS; i++) {
58: wav_channels[i].buf = NULL;
59: }
60: SDL_UnlockAudio ();
61: }
62:
63: /* 11Khz, 22Khz, 44Khz playback */
64: int SoundPlayBackFrequencies[] =
65: {
66: 11025, /* PLAYBACK_LOW */
67: 22050, /* PLAYBACK_MEDIUM */
68: 44100, /* PLAYBACK_HIGH */
69: };
70:
71:
72: BOOL bDisableSound = FALSE;
73: BOOL bSoundWorking = TRUE; /* Is sound OK */
74: volatile BOOL bPlayingBuffer = FALSE; /* Is playing buffer? */
75: int OutputAudioFreqIndex = FREQ_22Khz; /* Playback rate (11Khz,22Khz or 44Khz) */
76: float PlayVolume = 0.0f;
77: int SoundBufferSize = 1024; /* Size of sound buffer */
78: int CompleteSndBufIdx; /* Replay-index into MixBuffer */
79:
80:
81:
82: /*-----------------------------------------------------------------------*/
83: /*
84: SDL audio callback function - copy emulation sound to audio system.
85: */
86: void Audio_CallBack(void *userdata, Uint8 *pDestBuffer, int len)
87: {
88: Sint8 *pBuffer;
89: int i, j;
90: short sample;
91: BOOL playing = FALSE;
92:
93: pBuffer = pDestBuffer;
94:
95: for (i=0; i<MAX_CHANNELS; i++) {
96: if (wav_channels[i].buf != NULL) {
97: playing = TRUE;
98: break;
99: }
100: }
101:
102: if (!playing) {
103: memset (pDestBuffer, 0, len);
104: return;
105: }
106:
107: for (i = 0; i < len; i+=2) {
108: sample = 0;
109: for (j=0; j<MAX_CHANNELS; j++) {
110: if (wav_channels[j].buf == NULL) continue;
111: sample += *(short *)(wav_channels[j].buf + wav_channels[j].buf_pos);
112: wav_channels[j].buf_pos += 2;
113: if (wav_channels[j].buf_pos >= wav_channels[j].buf_len) {
114: /* end of sample. either loop or terminate */
115: if (wav_channels[j].loop != -1) {
116: wav_channels[j].buf_pos = wav_channels[j].loop;
117: } else {
118: wav_channels[j].buf = NULL;
119: }
120: }
121: }
122: *((short*)pBuffer) = sample;
123: pBuffer += 2;
124: }
125: }
126:
127: /*
128: * Loaded samples must be SND_FREQ, 16-bit signed. Reject
129: * other frequencies but convert 8-bit unsigned.
130: */
131: void check_sample_format (SDL_AudioSpec *spec, Uint8 **buf, int *len, const char *filename)
132: {
133: Uint8 *old_buf = *buf;
134: short *new_buf;
135: int i;
136:
137: if (spec->freq != SND_FREQ) {
138: printf ("Sample %s is the wrong sample rate (wanted %dHz). Ignoring.\n", filename, SND_FREQ);
139: SDL_FreeWAV (*buf);
140: *buf = NULL;
141: return;
142: }
143:
144: if (spec->format == AUDIO_U8) {
145: new_buf = malloc ((*len)*2);
146: for (i=0; i<(*len); i++) {
147: new_buf[i] = (old_buf[i] ^ 128) << 8;
148: }
149: *len *= 2;
150: SDL_FreeWAV (old_buf);
151: *buf = (char *)new_buf;
152: } else if (spec->format != AUDIO_S16) {
153: printf ("Sample %s is not 16-bit-signed or 8-bit unsigned. Ignoring.", filename);
154: SDL_FreeWAV (*buf);
155: *buf = NULL;
156: return;
157: }
158: }
159:
160: /*-----------------------------------------------------------------------*/
161: /*
162: Initialize the audio subsystem. Return TRUE if all OK.
163: We use direct access to the sound buffer, set to a unsigned 8-bit mono stream.
164: */
165: void Audio_Init(void)
166: {
167: int i;
168: char filename[32];
169: SDL_AudioSpec desiredAudioSpec; /* We fill in the desired SDL audio options here */
170:
171: /* Is enabled? */
172: if(bDisableSound)
173: {
174: /* Stop any sound access */
175: printf("Sound: Disabled\n");
176: bSoundWorking = FALSE;
177: return;
178: }
179:
180: /* Init the SDL's audio subsystem: */
181: if( SDL_WasInit(SDL_INIT_AUDIO)==0 )
182: {
183: if( SDL_InitSubSystem(SDL_INIT_AUDIO)<0 )
184: {
185: fprintf(stderr, "Could not init audio: %s\n", SDL_GetError() );
186: bSoundWorking = FALSE;
187: return;
188: }
189: }
190:
191: /* Set up SDL audio: */
192: desiredAudioSpec.freq = SND_FREQ;
193: desiredAudioSpec.format = AUDIO_S16; /* 8 Bit unsigned */
194: desiredAudioSpec.channels = 1; /* Mono */
195: desiredAudioSpec.samples = 1024; /* Buffer size */
196: desiredAudioSpec.callback = Audio_CallBack;
197: desiredAudioSpec.userdata = NULL;
198:
199: if( SDL_OpenAudio(&desiredAudioSpec, NULL) ) /* Open audio device */
200: {
201: fprintf(stderr, "Can't use audio: %s\n", SDL_GetError());
202: bSoundWorking = FALSE;
203: ConfigureParams.Sound.bEnableSound = FALSE;
204: return;
205: }
206:
207: SoundBufferSize = desiredAudioSpec.size; /* May be different than the requested one! */
208:
209: for (i=0; i<MAX_SAMPLES; i++) {
210: snprintf (filename, sizeof (filename), "sfx/sfx_%02d.wav", i);
211: if (SDL_LoadWAV (filename, &desiredAudioSpec, &sfx_buf[i].buf,
212: &sfx_buf[i].buf_len) == NULL) {
213: printf ("Error loading %s: %s\n", filename, SDL_GetError ());
214: sfx_buf[i].buf = NULL;
215: }
216: check_sample_format (&desiredAudioSpec, &sfx_buf[i].buf, &sfx_buf[i].buf_len, filename);
217:
218: /* 19 (hyperspace) and 23 (noise) loop */
219: if (i == 19) sfx_buf[i].loop = SND_FREQ; /* loop to about 0.5 sec in */
220: else if (i == 23) sfx_buf[i].loop = 0;
221: else sfx_buf[i].loop = -1;
222: }
223:
224: /* All OK */
225: bSoundWorking = TRUE;
226: /* And begin */
227: Audio_EnableAudio(TRUE);
228: }
229:
230:
231: /*-----------------------------------------------------------------------*/
232: /*
233: Free audio subsystem
234: */
235: void Audio_UnInit(void)
236: {
237: /* Stop */
238: Audio_EnableAudio(FALSE);
239:
240: SDL_CloseAudio();
241: }
242:
243:
244: /*-----------------------------------------------------------------------*/
245: /*
246: Lock the audio sub system so that the callback function will not be called.
247: */
248: void Audio_Lock(void)
249: {
250: SDL_LockAudio();
251: }
252:
253:
254: /*-----------------------------------------------------------------------*/
255: /*
256: Unlock the audio sub system so that the callback function will be called again.
257: */
258: void Audio_Unlock(void)
259: {
260: SDL_UnlockAudio();
261: }
262:
263:
264: /*-----------------------------------------------------------------------*/
265: /*
266: Set audio playback frequency variable, pass as PLAYBACK_xxxx
267: */
268: void Audio_SetOutputAudioFreq(int Frequency)
269: {
270: /* Do not reset sound system if nothing has changed! */
271: if(Frequency != OutputAudioFreqIndex)
272: {
273: /* Set new frequency, index into SoundPlayBackFrequencies[] */
274: OutputAudioFreqIndex = Frequency;
275:
276: /* Re-open SDL audio interface... */
277: Audio_UnInit();
278: Audio_Init();
279: }
280: }
281:
282:
283: /*-----------------------------------------------------------------------*/
284: /*
285: Start/Stop sound buffer
286: */
287: void Audio_EnableAudio(BOOL bEnable)
288: {
289: if(bEnable && !bPlayingBuffer)
290: {
291: /* Start playing */
292: SDL_PauseAudio(FALSE);
293: bPlayingBuffer = TRUE;
294: }
295: else if(!bEnable && bPlayingBuffer)
296: {
297: /* Stop from playing */
298: SDL_PauseAudio(!bEnable);
299: bPlayingBuffer = bEnable;
300: }
301: }
302:
303:
304: /*-----------------------------------------------------------------------*/
305: /*
306: Scale sample value (-128...127) according to 'PlayVolume' setting
307: */
308: Sint16 Audio_ModifyVolume(Sint16 Sample)
309: {
310: /* If full volume, just use current value */
311: if (PlayVolume==1.0f)
312: return(Sample);
313:
314: /* Else, scale volume */
315: Sample = (Sint16)((float)Sample*PlayVolume);
316:
317: return(Sample);
318: }
319:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.