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

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.13! root        9: const char Audio_fileid[] = "Hatari audio.c : " __DATE__ " " __TIME__;
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.10  root       21: int const SoundPlayBackFrequencies[] =
1.1.1.5   root       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.12  root       29: bool bSoundWorking = FALSE;               /* Is sound OK */
                     30: volatile bool bPlayingBuffer = FALSE;     /* Is playing buffer? */
1.1.1.5   root       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: /*-----------------------------------------------------------------------*/
1.1.1.11  root       38: /**
                     39:  * SDL audio callback function - copy emulation sound to audio system.
                     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.12  root       43:        Sint16 *pBuffer;
1.1.1.9   root       44:        int i;
1.1.1.7   root       45: 
1.1.1.12  root       46:        pBuffer = (Sint16 *)stream;
                     47:        len = len / 4;  // Use length in samples (16 bit stereo), not in bytes
1.1.1.9   root       48: 
                     49:        if (nGeneratedSamples >= len)
                     50:        {
1.1.1.10  root       51:                /* Enough samples available: Pass completed buffer to audio system
                     52:                 * by write samples into sound buffer and by converting them from
                     53:                 * 'signed' to 'unsigned' */
                     54:                for (i = 0; i < len; i++)
                     55:                {
1.1.1.12  root       56:                        *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][0];
                     57:                        *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][1];
1.1.1.10  root       58:                }
1.1.1.9   root       59:                CompleteSndBufIdx += len;
                     60:                nGeneratedSamples -= len;
                     61:        }
1.1.1.10  root       62:        else  /* Not enough samples available: */
1.1.1.9   root       63:        {
1.1.1.10  root       64:                for (i = 0; i < nGeneratedSamples; i++)
                     65:                {
1.1.1.12  root       66:                        *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][0];
                     67:                        *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][1];
1.1.1.10  root       68:                }
                     69:                /* If the buffer is filled more than 50%, mirror sample buffer to fake the
                     70:                 * missing samples */
                     71:                if (nGeneratedSamples >= len/2)
                     72:                {
                     73:                        int remaining = len - nGeneratedSamples;
1.1.1.12  root       74:                        memcpy(pBuffer, stream+(nGeneratedSamples-remaining)*4, remaining*4);
1.1.1.10  root       75:                }
1.1.1.9   root       76:                CompleteSndBufIdx += nGeneratedSamples;
                     77:                nGeneratedSamples = 0;
1.1.1.10  root       78:                
1.1.1.9   root       79:        }
1.1.1.10  root       80: 
1.1.1.9   root       81:        CompleteSndBufIdx = CompleteSndBufIdx % MIXBUFFER_SIZE;
1.1.1.2   root       82: }
                     83: 
1.1       root       84: 
1.1.1.2   root       85: /*-----------------------------------------------------------------------*/
1.1.1.11  root       86: /**
                     87:  * Initialize the audio subsystem. Return TRUE if all OK.
                     88:  * We use direct access to the sound buffer, set to a unsigned 8-bit mono stream.
                     89:  */
1.1.1.2   root       90: void Audio_Init(void)
1.1       root       91: {
1.1.1.9   root       92:        SDL_AudioSpec desiredAudioSpec;    /* We fill in the desired SDL audio options here */
1.1.1.5   root       93: 
1.1.1.9   root       94:        /* Is enabled? */
                     95:        if (!ConfigureParams.Sound.bEnableSound)
                     96:        {
                     97:                /* Stop any sound access */
                     98:                Log_Printf(LOG_DEBUG, "Sound: Disabled\n");
                     99:                bSoundWorking = FALSE;
                    100:                return;
                    101:        }
                    102: 
                    103:        /* Init the SDL's audio subsystem: */
                    104:        if (SDL_WasInit(SDL_INIT_AUDIO) == 0)
                    105:        {
                    106:                if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
                    107:                {
                    108:                        fprintf(stderr, "Could not init audio: %s\n", SDL_GetError() );
                    109:                        bSoundWorking = FALSE;
                    110:                        return;
                    111:                }
                    112:        }
                    113: 
                    114:        /* Set up SDL audio: */
                    115:        desiredAudioSpec.freq = SoundPlayBackFrequencies[OutputAudioFreqIndex];
1.1.1.12  root      116:        desiredAudioSpec.format = AUDIO_S16SYS;       /* 16-Bit signed */
                    117:        desiredAudioSpec.channels = 2;                /* stereo */
1.1.1.9   root      118:        desiredAudioSpec.samples = 1024;              /* Buffer size */
                    119:        desiredAudioSpec.callback = Audio_CallBack;
                    120:        desiredAudioSpec.userdata = NULL;
                    121: 
                    122:        if (SDL_OpenAudio(&desiredAudioSpec, NULL))   /* Open audio device */
                    123:        {
                    124:                fprintf(stderr, "Can't use audio: %s\n", SDL_GetError());
                    125:                bSoundWorking = FALSE;
                    126:                ConfigureParams.Sound.bEnableSound = FALSE;
                    127:                SDL_QuitSubSystem(SDL_INIT_AUDIO);
                    128:                return;
                    129:        }
                    130: 
                    131:        SoundBufferSize = desiredAudioSpec.size;      /* May be different than the requested one! */
                    132:        if (SoundBufferSize > MIXBUFFER_SIZE/2)
                    133:        {
                    134:                fprintf(stderr, "Warning: Soundbuffer size is too big!\n");
                    135:        }
                    136: 
                    137:        /* All OK */
                    138:        bSoundWorking = TRUE;
                    139:        /* And begin */
                    140:        Audio_EnableAudio(TRUE);
1.1       root      141: }
                    142: 
1.1.1.2   root      143: 
                    144: /*-----------------------------------------------------------------------*/
1.1.1.11  root      145: /**
                    146:  * Free audio subsystem
                    147:  */
1.1.1.2   root      148: void Audio_UnInit(void)
1.1       root      149: {
1.1.1.9   root      150:        if (bSoundWorking)
                    151:        {
                    152:                /* Stop */
                    153:                Audio_EnableAudio(FALSE);
1.1.1.2   root      154: 
1.1.1.9   root      155:                SDL_CloseAudio();
1.1.1.7   root      156: 
1.1.1.9   root      157:                bSoundWorking = FALSE;
                    158:        }
1.1       root      159: }
                    160: 
1.1.1.2   root      161: 
                    162: /*-----------------------------------------------------------------------*/
1.1.1.11  root      163: /**
                    164:  * Lock the audio sub system so that the callback function will not be called.
                    165:  */
1.1.1.5   root      166: void Audio_Lock(void)
1.1       root      167: {
1.1.1.9   root      168:        SDL_LockAudio();
1.1       root      169: }
                    170: 
1.1.1.2   root      171: 
                    172: /*-----------------------------------------------------------------------*/
1.1.1.11  root      173: /**
                    174:  * Unlock the audio sub system so that the callback function will be called again.
                    175:  */
1.1.1.5   root      176: void Audio_Unlock(void)
1.1       root      177: {
1.1.1.9   root      178:        SDL_UnlockAudio();
1.1       root      179: }
                    180: 
1.1.1.2   root      181: 
                    182: /*-----------------------------------------------------------------------*/
1.1.1.11  root      183: /**
                    184:  * Set audio playback frequency variable, pass as PLAYBACK_xxxx
                    185:  */
1.1.1.2   root      186: void Audio_SetOutputAudioFreq(int Frequency)
1.1       root      187: {
1.1.1.9   root      188:        /* Do not reset sound system if nothing has changed! */
                    189:        if (Frequency != OutputAudioFreqIndex)
                    190:        {
                    191:                /* Set new frequency, index into SoundPlayBackFrequencies[] */
                    192:                OutputAudioFreqIndex = Frequency;
                    193: 
                    194:                /* Re-open SDL audio interface if necessary: */
                    195:                if (bSoundWorking)
                    196:                {
                    197:                        Audio_UnInit();
                    198:                        Audio_Init();
                    199:                }
                    200:        }
1.1       root      201: }
                    202: 
1.1.1.2   root      203: 
                    204: /*-----------------------------------------------------------------------*/
1.1.1.11  root      205: /**
                    206:  * Start/Stop sound buffer
                    207:  */
1.1.1.12  root      208: void Audio_EnableAudio(bool bEnable)
1.1       root      209: {
1.1.1.9   root      210:        if (bEnable && !bPlayingBuffer)
                    211:        {
                    212:                /* Start playing */
                    213:                SDL_PauseAudio(FALSE);
                    214:                bPlayingBuffer = TRUE;
                    215:        }
                    216:        else if (!bEnable && bPlayingBuffer)
                    217:        {
                    218:                /* Stop from playing */
                    219:                SDL_PauseAudio(TRUE);
                    220:                bPlayingBuffer = FALSE;
                    221:        }
1.1       root      222: }

unix.superglobalmegacorp.com

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