Annotation of hatari/src/audio.c, revision 1.1.1.6

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.