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