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