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