|
|
1.1 root 1: /*
1.1.1.5 root 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.
1.1 root 8: */
1.1.1.12! root 9: const char Audio_rcsid[] = "Hatari $Id: audio.c,v 1.29 2008/08/19 00:09:59 thothy Exp $";
1.1 root 10:
1.1.1.2 root 11: #include <SDL.h>
12:
1.1 root 13: #include "main.h"
14: #include "audio.h"
1.1.1.6 root 15: #include "configuration.h"
1.1.1.9 root 16: #include "log.h"
1.1 root 17: #include "sound.h"
18:
19:
20: /* 11Khz, 22Khz, 44Khz playback */
1.1.1.10 root 21: int const SoundPlayBackFrequencies[] =
1.1.1.5 root 22: {
1.1.1.9 root 23: 11025, /* PLAYBACK_LOW */
24: 22050, /* PLAYBACK_MEDIUM */
25: 44100, /* PLAYBACK_HIGH */
1.1 root 26: };
27:
1.1.1.2 root 28:
1.1.1.12! root 29: bool bSoundWorking = FALSE; /* Is sound OK */
! 30: volatile bool bPlayingBuffer = FALSE; /* Is playing buffer? */
1.1.1.5 root 31: int OutputAudioFreqIndex = FREQ_22Khz; /* Playback rate (11Khz,22Khz or 44Khz) */
32: int SoundBufferSize = 1024; /* Size of sound buffer */
33: int CompleteSndBufIdx; /* Replay-index into MixBuffer */
1.1.1.2 root 34:
1.1 root 35:
36:
1.1.1.2 root 37: /*-----------------------------------------------------------------------*/
1.1.1.11 root 38: /**
39: * SDL audio callback function - copy emulation sound to audio system.
40: */
1.1.1.7 root 41: static void Audio_CallBack(void *userdata, Uint8 *stream, int len)
1.1.1.2 root 42: {
1.1.1.12! root 43: Sint16 *pBuffer;
1.1.1.9 root 44: int i;
1.1.1.7 root 45:
1.1.1.12! root 46: pBuffer = (Sint16 *)stream;
! 47: len = len / 4; // Use length in samples (16 bit stereo), not in bytes
1.1.1.9 root 48:
49: if (nGeneratedSamples >= len)
50: {
1.1.1.10 root 51: /* Enough samples available: Pass completed buffer to audio system
52: * by write samples into sound buffer and by converting them from
53: * 'signed' to 'unsigned' */
54: for (i = 0; i < len; i++)
55: {
1.1.1.12! root 56: *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][0];
! 57: *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][1];
1.1.1.10 root 58: }
1.1.1.9 root 59: CompleteSndBufIdx += len;
60: nGeneratedSamples -= len;
61: }
1.1.1.10 root 62: else /* Not enough samples available: */
1.1.1.9 root 63: {
1.1.1.10 root 64: for (i = 0; i < nGeneratedSamples; i++)
65: {
1.1.1.12! root 66: *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][0];
! 67: *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][1];
1.1.1.10 root 68: }
69: /* If the buffer is filled more than 50%, mirror sample buffer to fake the
70: * missing samples */
71: if (nGeneratedSamples >= len/2)
72: {
73: int remaining = len - nGeneratedSamples;
1.1.1.12! root 74: memcpy(pBuffer, stream+(nGeneratedSamples-remaining)*4, remaining*4);
1.1.1.10 root 75: }
1.1.1.9 root 76: CompleteSndBufIdx += nGeneratedSamples;
77: nGeneratedSamples = 0;
1.1.1.10 root 78:
1.1.1.9 root 79: }
1.1.1.10 root 80:
1.1.1.9 root 81: CompleteSndBufIdx = CompleteSndBufIdx % MIXBUFFER_SIZE;
1.1.1.2 root 82: }
83:
1.1 root 84:
1.1.1.2 root 85: /*-----------------------------------------------------------------------*/
1.1.1.11 root 86: /**
87: * Initialize the audio subsystem. Return TRUE if all OK.
88: * We use direct access to the sound buffer, set to a unsigned 8-bit mono stream.
89: */
1.1.1.2 root 90: void Audio_Init(void)
1.1 root 91: {
1.1.1.9 root 92: SDL_AudioSpec desiredAudioSpec; /* We fill in the desired SDL audio options here */
1.1.1.5 root 93:
1.1.1.9 root 94: /* Is enabled? */
95: if (!ConfigureParams.Sound.bEnableSound)
96: {
97: /* Stop any sound access */
98: Log_Printf(LOG_DEBUG, "Sound: Disabled\n");
99: bSoundWorking = FALSE;
100: return;
101: }
102:
103: /* Init the SDL's audio subsystem: */
104: if (SDL_WasInit(SDL_INIT_AUDIO) == 0)
105: {
106: if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
107: {
108: fprintf(stderr, "Could not init audio: %s\n", SDL_GetError() );
109: bSoundWorking = FALSE;
110: return;
111: }
112: }
113:
114: /* Set up SDL audio: */
115: desiredAudioSpec.freq = SoundPlayBackFrequencies[OutputAudioFreqIndex];
1.1.1.12! root 116: desiredAudioSpec.format = AUDIO_S16SYS; /* 16-Bit signed */
! 117: desiredAudioSpec.channels = 2; /* stereo */
1.1.1.9 root 118: desiredAudioSpec.samples = 1024; /* Buffer size */
119: desiredAudioSpec.callback = Audio_CallBack;
120: desiredAudioSpec.userdata = NULL;
121:
122: if (SDL_OpenAudio(&desiredAudioSpec, NULL)) /* Open audio device */
123: {
124: fprintf(stderr, "Can't use audio: %s\n", SDL_GetError());
125: bSoundWorking = FALSE;
126: ConfigureParams.Sound.bEnableSound = FALSE;
127: SDL_QuitSubSystem(SDL_INIT_AUDIO);
128: return;
129: }
130:
131: SoundBufferSize = desiredAudioSpec.size; /* May be different than the requested one! */
132: if (SoundBufferSize > MIXBUFFER_SIZE/2)
133: {
134: fprintf(stderr, "Warning: Soundbuffer size is too big!\n");
135: }
136:
137: /* All OK */
138: bSoundWorking = TRUE;
139: /* And begin */
140: Audio_EnableAudio(TRUE);
1.1 root 141: }
142:
1.1.1.2 root 143:
144: /*-----------------------------------------------------------------------*/
1.1.1.11 root 145: /**
146: * Free audio subsystem
147: */
1.1.1.2 root 148: void Audio_UnInit(void)
1.1 root 149: {
1.1.1.9 root 150: if (bSoundWorking)
151: {
152: /* Stop */
153: Audio_EnableAudio(FALSE);
1.1.1.2 root 154:
1.1.1.9 root 155: SDL_CloseAudio();
1.1.1.7 root 156:
1.1.1.9 root 157: bSoundWorking = FALSE;
158: }
1.1 root 159: }
160:
1.1.1.2 root 161:
162: /*-----------------------------------------------------------------------*/
1.1.1.11 root 163: /**
164: * Lock the audio sub system so that the callback function will not be called.
165: */
1.1.1.5 root 166: void Audio_Lock(void)
1.1 root 167: {
1.1.1.9 root 168: SDL_LockAudio();
1.1 root 169: }
170:
1.1.1.2 root 171:
172: /*-----------------------------------------------------------------------*/
1.1.1.11 root 173: /**
174: * Unlock the audio sub system so that the callback function will be called again.
175: */
1.1.1.5 root 176: void Audio_Unlock(void)
1.1 root 177: {
1.1.1.9 root 178: SDL_UnlockAudio();
1.1 root 179: }
180:
1.1.1.2 root 181:
182: /*-----------------------------------------------------------------------*/
1.1.1.11 root 183: /**
184: * Set audio playback frequency variable, pass as PLAYBACK_xxxx
185: */
1.1.1.2 root 186: void Audio_SetOutputAudioFreq(int Frequency)
1.1 root 187: {
1.1.1.9 root 188: /* Do not reset sound system if nothing has changed! */
189: if (Frequency != OutputAudioFreqIndex)
190: {
191: /* Set new frequency, index into SoundPlayBackFrequencies[] */
192: OutputAudioFreqIndex = Frequency;
193:
194: /* Re-open SDL audio interface if necessary: */
195: if (bSoundWorking)
196: {
197: Audio_UnInit();
198: Audio_Init();
199: }
200: }
1.1 root 201: }
202:
1.1.1.2 root 203:
204: /*-----------------------------------------------------------------------*/
1.1.1.11 root 205: /**
206: * Start/Stop sound buffer
207: */
1.1.1.12! root 208: void Audio_EnableAudio(bool bEnable)
1.1 root 209: {
1.1.1.9 root 210: if (bEnable && !bPlayingBuffer)
211: {
212: /* Start playing */
213: SDL_PauseAudio(FALSE);
214: bPlayingBuffer = TRUE;
215: }
216: else if (!bEnable && bPlayingBuffer)
217: {
218: /* Stop from playing */
219: SDL_PauseAudio(TRUE);
220: bPlayingBuffer = FALSE;
221: }
1.1 root 222: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.