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

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

unix.superglobalmegacorp.com

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