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