|
|
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.6 ! root 9: static char rcsid[] = "Hatari $Id: audio.c,v 1.16 2003/04/12 16:28:06 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 bDisableSound = FALSE;
33: BOOL bSoundWorking = TRUE; /* Is sound OK */
34: volatile BOOL bPlayingBuffer = FALSE; /* Is playing buffer? */
35: int OutputAudioFreqIndex = FREQ_22Khz; /* Playback rate (11Khz,22Khz or 44Khz) */
36: float PlayVolume = 0.0f;
37: int SoundBufferSize = 1024; /* Size of sound buffer */
38: int CompleteSndBufIdx; /* Replay-index into MixBuffer */
1.1.1.2 root 39:
1.1 root 40:
41:
1.1.1.2 root 42: /*-----------------------------------------------------------------------*/
43: /*
1.1.1.5 root 44: SDL audio callback function - copy emulation sound to audio system.
1.1.1.2 root 45: */
46: void Audio_CallBack(void *userdata, Uint8 *stream, int len)
47: {
1.1.1.6 ! root 48: /* If there are only some samples missing to have a complete buffer,
! 49: * we generate them here (sounds much better then!). However, if a lot of
! 50: * samples are missing, then the system is probably too slow, so we don't
! 51: * generate more samples to not make things worse... */
! 52: if(nGeneratedSamples < len && len-nGeneratedSamples < 128)
! 53: Sound_UpdateFromAudioCallBack();
! 54:
1.1.1.5 root 55: /* Pass completed buffer to audio system: */
56: Audio_WriteSamplesIntoBuffer(MixBuffer, CompleteSndBufIdx, len,
1.1.1.6 ! root 57: (bEmulationActive ? RAMP_UP : RAMP_DOWN), stream);
1.1.1.5 root 58:
59: /* We should now have generated a complete frame of samples.
60: * However, for slow systems we have to check how many generated samples
61: * we may advance... */
62: if(nGeneratedSamples >= len)
63: {
64: CompleteSndBufIdx += len;
65: nGeneratedSamples -= len;
66: }
67: else
68: {
69: CompleteSndBufIdx += nGeneratedSamples;
70: nGeneratedSamples = 0;
71: }
72: CompleteSndBufIdx = CompleteSndBufIdx % MIXBUFFER_SIZE;
1.1.1.2 root 73: }
74:
1.1 root 75:
1.1.1.2 root 76: /*-----------------------------------------------------------------------*/
1.1 root 77: /*
1.1.1.5 root 78: Initialize the audio subsystem. Return TRUE if all OK.
79: We use direct access to the sound buffer, set to a unsigned 8-bit mono stream.
1.1 root 80: */
1.1.1.2 root 81: void Audio_Init(void)
1.1 root 82: {
1.1.1.5 root 83: SDL_AudioSpec desiredAudioSpec; /* We fill in the desired SDL audio options here */
84:
1.1.1.2 root 85: /* Is enabled? */
1.1.1.4 root 86: if(bDisableSound)
87: {
1.1.1.3 root 88: /* Stop any sound access */
1.1.1.2 root 89: ErrLog_File("Sound: Disabled\n");
90: bSoundWorking = FALSE;
1.1 root 91: return;
92: }
93:
1.1.1.4 root 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() );
100: bSoundWorking = FALSE;
101: return;
102: }
103: }
104:
105: /* Set up SDL audio: */
1.1.1.3 root 106: desiredAudioSpec.freq = SoundPlayBackFrequencies[OutputAudioFreqIndex];
1.1.1.5 root 107: desiredAudioSpec.format = AUDIO_U8; /* 8 Bit unsigned */
108: desiredAudioSpec.channels = 1; /* Mono */
109: desiredAudioSpec.samples = 1024; /* Buffer size */
1.1.1.3 root 110: desiredAudioSpec.callback = Audio_CallBack;
111: desiredAudioSpec.userdata = NULL;
1.1.1.5 root 112:
113: if( SDL_OpenAudio(&desiredAudioSpec, NULL) ) /* Open audio device */
1.1.1.3 root 114: {
1.1.1.4 root 115: fprintf(stderr, "Can't use audio: %s\n", SDL_GetError());
1.1.1.2 root 116: bSoundWorking = FALSE;
1.1.1.3 root 117: ConfigureParams.Sound.bEnableSound = FALSE;
1.1.1.2 root 118: return;
1.1 root 119: }
1.1.1.3 root 120:
1.1.1.5 root 121: SoundBufferSize = desiredAudioSpec.size; /* May be different than the requested one! */
122: if(SoundBufferSize > MIXBUFFER_SIZE/2)
123: {
124: fprintf(stderr, "Warning: Soundbuffer size is too big!\n");
125: }
126:
127: /* All OK */
128: bSoundWorking = TRUE;
129: /* And begin */
130: Audio_EnableAudio(TRUE);
1.1 root 131: }
132:
1.1.1.2 root 133:
134: /*-----------------------------------------------------------------------*/
1.1 root 135: /*
1.1.1.5 root 136: Free audio subsystem
1.1 root 137: */
1.1.1.2 root 138: void Audio_UnInit(void)
1.1 root 139: {
1.1.1.5 root 140: /* Stop */
141: Audio_EnableAudio(FALSE);
1.1.1.2 root 142:
143: SDL_CloseAudio();
1.1 root 144: }
145:
1.1.1.2 root 146:
147: /*-----------------------------------------------------------------------*/
1.1 root 148: /*
1.1.1.5 root 149: Lock the audio sub system so that the callback function will not be called.
1.1 root 150: */
1.1.1.5 root 151: void Audio_Lock(void)
1.1 root 152: {
1.1.1.5 root 153: SDL_LockAudio();
1.1 root 154: }
155:
1.1.1.2 root 156:
157: /*-----------------------------------------------------------------------*/
1.1 root 158: /*
1.1.1.5 root 159: Unlock the audio sub system so that the callback function will be called again.
1.1 root 160: */
1.1.1.5 root 161: void Audio_Unlock(void)
1.1 root 162: {
1.1.1.5 root 163: SDL_UnlockAudio();
1.1 root 164: }
165:
1.1.1.2 root 166:
167: /*-----------------------------------------------------------------------*/
1.1 root 168: /*
1.1.1.3 root 169: Set audio playback frequency variable, pass as PLAYBACK_xxxx
1.1 root 170: */
1.1.1.2 root 171: void Audio_SetOutputAudioFreq(int Frequency)
1.1 root 172: {
1.1.1.5 root 173: /* Do not reset sound system if nothing has changed! */
174: if(Frequency != OutputAudioFreqIndex)
175: {
176: /* Set new frequency, index into SoundPlayBackFrequencies[] */
177: OutputAudioFreqIndex = Frequency;
1.1.1.2 root 178:
1.1.1.5 root 179: /* Re-open SDL audio interface... */
180: Audio_UnInit();
181: Audio_Init();
182: }
1.1 root 183: }
184:
1.1.1.2 root 185:
186: /*-----------------------------------------------------------------------*/
1.1 root 187: /*
1.1.1.5 root 188: Start/Stop sound buffer
1.1 root 189: */
1.1.1.5 root 190: void Audio_EnableAudio(BOOL bEnable)
1.1 root 191: {
1.1.1.5 root 192: if(bEnable && !bPlayingBuffer)
193: {
194: /* Start playing */
195: SDL_PauseAudio(FALSE);
196: bPlayingBuffer = TRUE;
197: }
198: else if(!bEnable && bPlayingBuffer)
199: {
200: /* Stop from playing */
201: SDL_PauseAudio(!bEnable);
202: bPlayingBuffer = bEnable;
203: }
1.1 root 204: }
205:
1.1.1.2 root 206:
207: /*-----------------------------------------------------------------------*/
1.1 root 208: /*
1.1.1.5 root 209: Scale sample value (-128...127) according to 'PlayVolume' setting
1.1 root 210: */
1.1.1.5 root 211: Sint8 Audio_ModifyVolume(Sint8 Sample)
1.1 root 212: {
1.1.1.2 root 213: /* If full volume, just use current value */
1.1 root 214: if (PlayVolume==1.0f)
215: return(Sample);
216:
1.1.1.2 root 217: /* Else, scale volume */
1.1.1.5 root 218: Sample = (Sint8)((float)Sample*PlayVolume);
1.1 root 219:
220: return(Sample);
221: }
222:
1.1.1.2 root 223:
224: /*-----------------------------------------------------------------------*/
1.1 root 225: /*
1.1.1.5 root 226: Write samples into sound buffer. Pass pSamples=NULL to write zero's.
1.1 root 227: */
1.1.1.5 root 228: void Audio_WriteSamplesIntoBuffer(Sint8 *pSamples, int Index, int Length,
229: int RampSetting, Sint8 *pDestBuffer)
1.1 root 230: {
1.1.1.5 root 231: Sint8 *pBuffer;
1.1.1.2 root 232: int i;
1.1 root 233:
1.1.1.2 root 234: /* Modify ramp volume - ramp down if sound not enabled or not in windows mouse mode */
1.1.1.5 root 235: if( (((RampSetting==RAMP_DOWN) || (!ConfigureParams.Sound.bEnableSound)) && (PlayVolume>0.0f)) )
236: {
1.1 root 237: PlayVolume -= RAMP_DOWN_VOLUME_LEVEL;
1.1.1.5 root 238: if(PlayVolume <= 0.0f)
1.1 root 239: PlayVolume = 0.0f;
240: }
1.1.1.5 root 241: else if((RampSetting==RAMP_UP) && (PlayVolume<1.0f))
242: {
1.1 root 243: PlayVolume += RAMP_UP_VOLUME_LEVEL;
1.1.1.5 root 244: if(PlayVolume >= 1.0f)
1.1 root 245: PlayVolume = 1.0f;
246: }
247:
1.1.1.5 root 248: /* Write section, convert to 'unsigned' and write '128's if passed NULL */
249: if(Length > 0)
250: {
251: if(pSamples)
252: {
253: pBuffer = pDestBuffer;
254: for(i = 0; i < Length; i++)
255: {
256: *pBuffer++ = Audio_ModifyVolume(pSamples[Index]) ^ 128;
257: Index = (Index + 1) % MIXBUFFER_SIZE;
1.1.1.2 root 258: }
1.1 root 259: }
1.1.1.5 root 260: else
261: {
262: memset(pDestBuffer, 128, Length);
1.1 root 263: }
264: }
265: }
1.1.1.5 root 266:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.