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