Annotation of frontvm/hardware/audio.c, revision 1.1.1.2

1.1       root        1: /*
                      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.
                      8: */
                      9: 
                     10: #include <SDL.h>
                     11: 
                     12: #include "main.h"
                     13: #include "audio.h"
                     14: #include "configuration.h"
                     15: #include "memAlloc.h"
                     16: #include "misc.h"
1.1.1.2 ! root       17: #include "../m68000.h"
1.1       root       18: 
                     19: #define SND_FREQ       22050
                     20: 
                     21: /* Converted frontier SFX to wav samples. */
                     22: #define MAX_SAMPLES    33
                     23: #define MAX_CHANNELS   4
                     24: 
                     25: typedef struct wav_stream {
                     26:        Uint8 *buf;
                     27:        int buf_pos;
                     28:        int buf_len;
                     29:        int loop; /* -1 no loop, otherwise specifies loop start pos */
                     30: } wav_stream;
                     31: 
                     32: wav_stream sfx_buf[MAX_SAMPLES];
                     33: wav_stream wav_channels[MAX_CHANNELS];
                     34: 
1.1.1.2 ! root       35: void Call_PlaySFX ()
1.1       root       36: {
                     37:        int sample, chan;
                     38: 
                     39:        SDL_LockAudio ();
                     40:        
1.1.1.2 ! root       41:        sample = (short) GetReg (REG_D0);
        !            42:        chan = (short) GetReg (REG_D1);
1.1       root       43:        //printf ("Playing sample %d on channel %d.\n", sample, chan);
                     44: 
                     45:        wav_channels[chan].buf_pos = 0;
                     46:        wav_channels[chan].buf_len = sfx_buf[sample].buf_len;
                     47:        wav_channels[chan].buf = sfx_buf[sample].buf;
                     48:        wav_channels[chan].loop = sfx_buf[sample].loop;
                     49: 
                     50:        SDL_UnlockAudio ();
                     51: }
                     52: 
                     53: void Audio_Reset ()
                     54: {
                     55:        int i;
                     56:        SDL_LockAudio ();
                     57:        for (i=0; i<MAX_CHANNELS; i++) {
                     58:                wav_channels[i].buf = NULL;
                     59:        }
                     60:        SDL_UnlockAudio ();
                     61: }
                     62: 
                     63: /* 11Khz, 22Khz, 44Khz playback */
                     64: int SoundPlayBackFrequencies[] =
                     65: {
                     66:   11025,  /* PLAYBACK_LOW */
                     67:   22050,  /* PLAYBACK_MEDIUM */
                     68:   44100,  /* PLAYBACK_HIGH */
                     69: };
                     70: 
                     71: 
                     72: BOOL bDisableSound = FALSE;
                     73: BOOL bSoundWorking = TRUE;                /* Is sound OK */
                     74: volatile BOOL bPlayingBuffer = FALSE;     /* Is playing buffer? */
                     75: int OutputAudioFreqIndex = FREQ_22Khz;    /* Playback rate (11Khz,22Khz or 44Khz) */
                     76: float PlayVolume = 0.0f;
                     77: int SoundBufferSize = 1024;               /* Size of sound buffer */
                     78: int CompleteSndBufIdx;                    /* Replay-index into MixBuffer */
                     79: 
                     80: 
                     81: 
                     82: /*-----------------------------------------------------------------------*/
                     83: /*
                     84:   SDL audio callback function - copy emulation sound to audio system.
                     85: */
                     86: void Audio_CallBack(void *userdata, Uint8 *pDestBuffer, int len)
                     87: {
                     88:        Sint8 *pBuffer;
                     89:        int i, j;
                     90:        short sample;
                     91:        BOOL playing = FALSE;
                     92:        
                     93:        pBuffer = pDestBuffer;
                     94:        
                     95:        for (i=0; i<MAX_CHANNELS; i++) {
                     96:                if (wav_channels[i].buf != NULL) {
                     97:                        playing = TRUE;
                     98:                        break;
                     99:                }
                    100:        }
                    101: 
                    102:        if (!playing) {
                    103:                memset (pDestBuffer, 0, len);
                    104:                return;
                    105:        }
                    106:        
                    107:        for (i = 0; i < len; i+=2) {
                    108:                sample = 0;
                    109:                for (j=0; j<MAX_CHANNELS; j++) {
                    110:                        if (wav_channels[j].buf == NULL) continue;
                    111:                        sample += *(short *)(wav_channels[j].buf + wav_channels[j].buf_pos);
                    112:                        wav_channels[j].buf_pos += 2;
                    113:                        if (wav_channels[j].buf_pos >= wav_channels[j].buf_len) {
                    114:                                /* end of sample. either loop or terminate */
                    115:                                if (wav_channels[j].loop != -1) {
                    116:                                        wav_channels[j].buf_pos = wav_channels[j].loop;
                    117:                                } else {
                    118:                                        wav_channels[j].buf = NULL;
                    119:                                }
                    120:                        }
                    121:                }
                    122:                *((short*)pBuffer) = sample;
                    123:                pBuffer += 2;
                    124:        }
                    125: }
                    126: 
                    127: /*
                    128:  * Loaded samples must be SND_FREQ, 16-bit signed. Reject
                    129:  * other frequencies but convert 8-bit unsigned.
                    130:  */
                    131: void check_sample_format (SDL_AudioSpec *spec, Uint8 **buf, int *len, const char *filename)
                    132: {
                    133:        Uint8 *old_buf = *buf;
                    134:        short *new_buf;
                    135:        int i;
                    136: 
                    137:        if (spec->freq != SND_FREQ) {
                    138:                printf ("Sample %s is the wrong sample rate (wanted %dHz). Ignoring.\n", filename, SND_FREQ);
                    139:                SDL_FreeWAV (*buf);
                    140:                *buf = NULL;
                    141:                return;
                    142:        }
                    143: 
                    144:        if (spec->format == AUDIO_U8) {
                    145:                new_buf = malloc ((*len)*2);
                    146:                for (i=0; i<(*len); i++) {
                    147:                        new_buf[i] = (old_buf[i] ^ 128) << 8;
                    148:                }
                    149:                *len *= 2;
                    150:                SDL_FreeWAV (old_buf);
                    151:                *buf = (char *)new_buf;
                    152:        } else if (spec->format != AUDIO_S16) {
                    153:                printf ("Sample %s is not 16-bit-signed or 8-bit unsigned. Ignoring.", filename);
                    154:                SDL_FreeWAV (*buf);
                    155:                *buf = NULL;
                    156:                return;
                    157:        }
                    158: }
                    159: 
                    160: /*-----------------------------------------------------------------------*/
                    161: /*
                    162:   Initialize the audio subsystem. Return TRUE if all OK.
                    163:   We use direct access to the sound buffer, set to a unsigned 8-bit mono stream.
                    164: */
                    165: void Audio_Init(void)
                    166: {
                    167:        int i;
                    168:        char filename[32];
                    169:   SDL_AudioSpec desiredAudioSpec;    /* We fill in the desired SDL audio options here */
                    170: 
                    171:   /* Is enabled? */
                    172:   if(bDisableSound)
                    173:   {
                    174:     /* Stop any sound access */
                    175:     printf("Sound: Disabled\n");
                    176:     bSoundWorking = FALSE;
                    177:     return;
                    178:   }
                    179: 
                    180:   /* Init the SDL's audio subsystem: */
                    181:   if( SDL_WasInit(SDL_INIT_AUDIO)==0 )
                    182:   {
                    183:     if( SDL_InitSubSystem(SDL_INIT_AUDIO)<0 )
                    184:     {
                    185:       fprintf(stderr, "Could not init audio: %s\n", SDL_GetError() );
                    186:       bSoundWorking = FALSE;
                    187:       return;
                    188:     }
                    189:   }
                    190: 
                    191:   /* Set up SDL audio: */
                    192:   desiredAudioSpec.freq = SND_FREQ;
                    193:   desiredAudioSpec.format = AUDIO_S16;           /* 8 Bit unsigned */
                    194:   desiredAudioSpec.channels = 1;                /* Mono */
                    195:   desiredAudioSpec.samples = 1024;              /* Buffer size */
                    196:   desiredAudioSpec.callback = Audio_CallBack;
                    197:   desiredAudioSpec.userdata = NULL;
                    198: 
                    199:   if( SDL_OpenAudio(&desiredAudioSpec, NULL) )  /* Open audio device */
                    200:   {
                    201:     fprintf(stderr, "Can't use audio: %s\n", SDL_GetError());
                    202:     bSoundWorking = FALSE;
                    203:     ConfigureParams.Sound.bEnableSound = FALSE;
                    204:     return;
                    205:   }
                    206: 
                    207:   SoundBufferSize = desiredAudioSpec.size;      /* May be different than the requested one! */
                    208: 
                    209:   for (i=0; i<MAX_SAMPLES; i++) {
                    210:          snprintf (filename, sizeof (filename), "sfx/sfx_%02d.wav", i);
                    211:          if (SDL_LoadWAV (filename, &desiredAudioSpec, &sfx_buf[i].buf,
                    212:                                  &sfx_buf[i].buf_len) == NULL) {
                    213:                printf ("Error loading %s: %s\n", filename, SDL_GetError ());
                    214:                sfx_buf[i].buf = NULL;
                    215:          }
                    216:          check_sample_format (&desiredAudioSpec, &sfx_buf[i].buf, &sfx_buf[i].buf_len, filename);
                    217:          
                    218:          /* 19 (hyperspace) and 23 (noise) loop */
                    219:          if (i == 19) sfx_buf[i].loop = SND_FREQ; /* loop to about 0.5 sec in */
                    220:          else if (i == 23) sfx_buf[i].loop = 0;
                    221:          else sfx_buf[i].loop = -1;
                    222:   }
                    223:   
                    224:   /* All OK */
                    225:   bSoundWorking = TRUE;
                    226:   /* And begin */
                    227:   Audio_EnableAudio(TRUE);
                    228: }
                    229: 
                    230: 
                    231: /*-----------------------------------------------------------------------*/
                    232: /*
                    233:   Free audio subsystem
                    234: */
                    235: void Audio_UnInit(void)
                    236: {
                    237:   /* Stop */
                    238:   Audio_EnableAudio(FALSE);
                    239: 
                    240:   SDL_CloseAudio();
                    241: }
                    242: 
                    243: 
                    244: /*-----------------------------------------------------------------------*/
                    245: /*
                    246:   Lock the audio sub system so that the callback function will not be called.
                    247: */
                    248: void Audio_Lock(void)
                    249: {
                    250:   SDL_LockAudio();
                    251: }
                    252: 
                    253: 
                    254: /*-----------------------------------------------------------------------*/
                    255: /*
                    256:   Unlock the audio sub system so that the callback function will be called again.
                    257: */
                    258: void Audio_Unlock(void)
                    259: {
                    260:   SDL_UnlockAudio();
                    261: }
                    262: 
                    263: 
                    264: /*-----------------------------------------------------------------------*/
                    265: /*
                    266:   Set audio playback frequency variable, pass as PLAYBACK_xxxx
                    267: */
                    268: void Audio_SetOutputAudioFreq(int Frequency)
                    269: {
                    270:   /* Do not reset sound system if nothing has changed! */
                    271:   if(Frequency != OutputAudioFreqIndex)
                    272:   {
                    273:     /* Set new frequency, index into SoundPlayBackFrequencies[] */
                    274:     OutputAudioFreqIndex = Frequency;
                    275: 
                    276:     /* Re-open SDL audio interface... */
                    277:     Audio_UnInit();
                    278:     Audio_Init();
                    279:   }
                    280: }
                    281: 
                    282: 
                    283: /*-----------------------------------------------------------------------*/
                    284: /*
                    285:   Start/Stop sound buffer
                    286: */
                    287: void Audio_EnableAudio(BOOL bEnable)
                    288: {
                    289:   if(bEnable && !bPlayingBuffer)
                    290:   {
                    291:     /* Start playing */
                    292:     SDL_PauseAudio(FALSE);
                    293:     bPlayingBuffer = TRUE;
                    294:   }
                    295:   else if(!bEnable && bPlayingBuffer)
                    296:   {
                    297:     /* Stop from playing */
                    298:     SDL_PauseAudio(!bEnable);
                    299:     bPlayingBuffer = bEnable;
                    300:   }
                    301: }
                    302: 
                    303: 
                    304: /*-----------------------------------------------------------------------*/
                    305: /*
                    306:   Scale sample value (-128...127) according to 'PlayVolume' setting
                    307: */
                    308: Sint16 Audio_ModifyVolume(Sint16 Sample)
                    309: {
                    310:   /* If full volume, just use current value */
                    311:   if (PlayVolume==1.0f)
                    312:     return(Sample);
                    313: 
                    314:   /* Else, scale volume */
                    315:   Sample = (Sint16)((float)Sample*PlayVolume);
                    316: 
                    317:   return(Sample);
                    318: }
                    319: 

unix.superglobalmegacorp.com

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