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

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"
1.1.1.15! root       18: #include "dmaSnd.h"
1.1       root       19: 
                     20: 
1.1.1.15! root       21: int nAudioFrequency = 44100;                   /* Sound playback frequency */
        !            22: bool bSoundWorking = false;                    /* Is sound OK */
        !            23: volatile bool bPlayingBuffer = false;          /* Is playing buffer? */
        !            24: int SoundBufferSize = 1024 / 4;                        /* Size of sound buffer (in samples) */
        !            25: int CompleteSndBufIdx;                         /* Replay-index into MixBuffer */
        !            26: int SdlAudioBufferSize = 0;                    /* in ms (0 = use default) */
1.1       root       27: 
                     28: 
1.1.1.2   root       29: /*-----------------------------------------------------------------------*/
1.1.1.11  root       30: /**
                     31:  * SDL audio callback function - copy emulation sound to audio system.
                     32:  */
1.1.1.7   root       33: static void Audio_CallBack(void *userdata, Uint8 *stream, int len)
1.1.1.2   root       34: {
1.1.1.12  root       35:        Sint16 *pBuffer;
1.1.1.9   root       36:        int i;
1.1.1.7   root       37: 
1.1.1.12  root       38:        pBuffer = (Sint16 *)stream;
                     39:        len = len / 4;  // Use length in samples (16 bit stereo), not in bytes
1.1.1.9   root       40: 
                     41:        if (nGeneratedSamples >= len)
                     42:        {
1.1.1.10  root       43:                /* Enough samples available: Pass completed buffer to audio system
                     44:                 * by write samples into sound buffer and by converting them from
                     45:                 * 'signed' to 'unsigned' */
                     46:                for (i = 0; i < len; i++)
                     47:                {
1.1.1.12  root       48:                        *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][0];
                     49:                        *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][1];
1.1.1.10  root       50:                }
1.1.1.9   root       51:                CompleteSndBufIdx += len;
                     52:                nGeneratedSamples -= len;
                     53:        }
1.1.1.10  root       54:        else  /* Not enough samples available: */
1.1.1.9   root       55:        {
1.1.1.10  root       56:                for (i = 0; i < nGeneratedSamples; i++)
                     57:                {
1.1.1.12  root       58:                        *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][0];
                     59:                        *pBuffer++ = MixBuffer[(CompleteSndBufIdx + i) % MIXBUFFER_SIZE][1];
1.1.1.10  root       60:                }
                     61:                /* If the buffer is filled more than 50%, mirror sample buffer to fake the
                     62:                 * missing samples */
                     63:                if (nGeneratedSamples >= len/2)
                     64:                {
                     65:                        int remaining = len - nGeneratedSamples;
1.1.1.12  root       66:                        memcpy(pBuffer, stream+(nGeneratedSamples-remaining)*4, remaining*4);
1.1.1.10  root       67:                }
1.1.1.9   root       68:                CompleteSndBufIdx += nGeneratedSamples;
                     69:                nGeneratedSamples = 0;
1.1.1.10  root       70:                
1.1.1.9   root       71:        }
1.1.1.10  root       72: 
1.1.1.9   root       73:        CompleteSndBufIdx = CompleteSndBufIdx % MIXBUFFER_SIZE;
1.1.1.2   root       74: }
                     75: 
1.1       root       76: 
1.1.1.2   root       77: /*-----------------------------------------------------------------------*/
1.1.1.11  root       78: /**
1.1.1.14  root       79:  * Initialize the audio subsystem. Return true if all OK.
1.1.1.11  root       80:  * We use direct access to the sound buffer, set to a unsigned 8-bit mono stream.
                     81:  */
1.1.1.2   root       82: void Audio_Init(void)
1.1       root       83: {
1.1.1.9   root       84:        SDL_AudioSpec desiredAudioSpec;    /* We fill in the desired SDL audio options here */
1.1.1.5   root       85: 
1.1.1.9   root       86:        /* Is enabled? */
                     87:        if (!ConfigureParams.Sound.bEnableSound)
                     88:        {
                     89:                /* Stop any sound access */
                     90:                Log_Printf(LOG_DEBUG, "Sound: Disabled\n");
1.1.1.14  root       91:                bSoundWorking = false;
1.1.1.9   root       92:                return;
                     93:        }
                     94: 
                     95:        /* Init the SDL's audio subsystem: */
                     96:        if (SDL_WasInit(SDL_INIT_AUDIO) == 0)
                     97:        {
                     98:                if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
                     99:                {
                    100:                        fprintf(stderr, "Could not init audio: %s\n", SDL_GetError() );
1.1.1.14  root      101:                        bSoundWorking = false;
1.1.1.9   root      102:                        return;
                    103:                }
                    104:        }
                    105: 
                    106:        /* Set up SDL audio: */
1.1.1.14  root      107:        desiredAudioSpec.freq = nAudioFrequency;
1.1.1.15! root      108:        desiredAudioSpec.format = AUDIO_S16SYS;         /* 16-Bit signed */
        !           109:        desiredAudioSpec.channels = 2;                  /* stereo */
1.1.1.9   root      110:        desiredAudioSpec.callback = Audio_CallBack;
                    111:        desiredAudioSpec.userdata = NULL;
                    112: 
1.1.1.15! root      113:        /* In most case, setting samples to 1024 will give an equivalent */
        !           114:        /* sdl sound buffer of ~20-30 ms (depending on freq). */
        !           115:        /* But setting samples to 1024 for all the freq can cause some faulty */
        !           116:        /* OS sound drivers to add an important delay when playing sound at lower freq. */
        !           117:        /* In that case we use SdlAudioBufferSize (in ms) to compute a value */
        !           118:        /* of samples that matches the corresponding freq and buffer size. */
        !           119:        if ( SdlAudioBufferSize == 0 )                  /* don't compute "samples", use default value */
        !           120:                desiredAudioSpec.samples = 1024;        /* buffer size in samples */
        !           121:        else
        !           122:        {
        !           123:                int samples = (desiredAudioSpec.freq / 1000) * SdlAudioBufferSize;
        !           124:                int power2 = 1;
        !           125:                while ( power2 < samples )              /* compute the power of 2 just above samples */
        !           126:                         power2 *= 2;
        !           127: 
        !           128: //fprintf ( stderr , "samples %d power %d\n" , samples , power2 );
        !           129:                desiredAudioSpec.samples = power2;      /* number of samples corresponding to the requested SdlAudioBufferSize */
        !           130:        }
        !           131: 
        !           132: 
        !           133:        if (SDL_OpenAudio(&desiredAudioSpec, NULL))     /* Open audio device */
1.1.1.9   root      134:        {
                    135:                fprintf(stderr, "Can't use audio: %s\n", SDL_GetError());
1.1.1.14  root      136:                bSoundWorking = false;
                    137:                ConfigureParams.Sound.bEnableSound = false;
1.1.1.9   root      138:                SDL_QuitSubSystem(SDL_INIT_AUDIO);
                    139:                return;
                    140:        }
                    141: 
1.1.1.15! root      142:        SoundBufferSize = desiredAudioSpec.size;        /* May be different than the requested one! */
        !           143:        SoundBufferSize /= 4;                           /* bytes -> samples (16 bit signed stereo -> 4 bytes per sample) */
1.1.1.9   root      144:        if (SoundBufferSize > MIXBUFFER_SIZE/2)
                    145:        {
                    146:                fprintf(stderr, "Warning: Soundbuffer size is too big!\n");
                    147:        }
                    148: 
                    149:        /* All OK */
1.1.1.14  root      150:        bSoundWorking = true;
1.1.1.9   root      151:        /* And begin */
1.1.1.14  root      152:        Audio_EnableAudio(true);
1.1       root      153: }
                    154: 
1.1.1.2   root      155: 
                    156: /*-----------------------------------------------------------------------*/
1.1.1.11  root      157: /**
                    158:  * Free audio subsystem
                    159:  */
1.1.1.2   root      160: void Audio_UnInit(void)
1.1       root      161: {
1.1.1.9   root      162:        if (bSoundWorking)
                    163:        {
                    164:                /* Stop */
1.1.1.14  root      165:                Audio_EnableAudio(false);
1.1.1.2   root      166: 
1.1.1.9   root      167:                SDL_CloseAudio();
1.1.1.7   root      168: 
1.1.1.14  root      169:                bSoundWorking = false;
1.1.1.9   root      170:        }
1.1       root      171: }
                    172: 
1.1.1.2   root      173: 
                    174: /*-----------------------------------------------------------------------*/
1.1.1.11  root      175: /**
                    176:  * Lock the audio sub system so that the callback function will not be called.
                    177:  */
1.1.1.5   root      178: void Audio_Lock(void)
1.1       root      179: {
1.1.1.9   root      180:        SDL_LockAudio();
1.1       root      181: }
                    182: 
1.1.1.2   root      183: 
                    184: /*-----------------------------------------------------------------------*/
1.1.1.11  root      185: /**
                    186:  * Unlock the audio sub system so that the callback function will be called again.
                    187:  */
1.1.1.5   root      188: void Audio_Unlock(void)
1.1       root      189: {
1.1.1.9   root      190:        SDL_UnlockAudio();
1.1       root      191: }
                    192: 
1.1.1.2   root      193: 
                    194: /*-----------------------------------------------------------------------*/
1.1.1.11  root      195: /**
                    196:  * Set audio playback frequency variable, pass as PLAYBACK_xxxx
                    197:  */
1.1.1.14  root      198: void Audio_SetOutputAudioFreq(int nNewFrequency)
1.1       root      199: {
1.1.1.9   root      200:        /* Do not reset sound system if nothing has changed! */
1.1.1.14  root      201:        if (nNewFrequency != nAudioFrequency)
1.1.1.9   root      202:        {
1.1.1.14  root      203:                /* Set new frequency */
                    204:                nAudioFrequency = nNewFrequency;
1.1.1.9   root      205: 
                    206:                /* Re-open SDL audio interface if necessary: */
                    207:                if (bSoundWorking)
                    208:                {
                    209:                        Audio_UnInit();
                    210:                        Audio_Init();
1.1.1.15! root      211:                        DmaSnd_Init_Bass_and_Treble_Tables();
1.1.1.9   root      212:                }
                    213:        }
1.1       root      214: }
                    215: 
1.1.1.2   root      216: 
                    217: /*-----------------------------------------------------------------------*/
1.1.1.11  root      218: /**
                    219:  * Start/Stop sound buffer
                    220:  */
1.1.1.12  root      221: void Audio_EnableAudio(bool bEnable)
1.1       root      222: {
1.1.1.9   root      223:        if (bEnable && !bPlayingBuffer)
                    224:        {
                    225:                /* Start playing */
1.1.1.14  root      226:                SDL_PauseAudio(false);
                    227:                bPlayingBuffer = true;
1.1.1.9   root      228:        }
                    229:        else if (!bEnable && bPlayingBuffer)
                    230:        {
                    231:                /* Stop from playing */
1.1.1.14  root      232:                SDL_PauseAudio(true);
                    233:                bPlayingBuffer = false;
1.1.1.9   root      234:        }
1.1       root      235: }

unix.superglobalmegacorp.com

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