Annotation of frontvm/src/audio.c, revision 1.1.1.1

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 "../m68000.h"
                     15: 
                     16: #ifdef OGG_MUSIC
                     17: # include <vorbis/codec.h>
                     18: # include <vorbis/vorbisfile.h>
                     19: #endif /* OGG_MUSIC */
                     20: 
                     21: BOOL bDisableSound = FALSE;
                     22: 
                     23: 
                     24: 
                     25: #define SND_FREQ       22050
                     26: 
                     27: /* Converted frontier SFX to wav samples. */
                     28: #define MAX_SAMPLES    33
                     29: #define MAX_CHANNELS   4
                     30: 
                     31: typedef struct wav_stream {
                     32:        Uint8 *buf;
                     33:        int buf_pos;
                     34:        int buf_len;
                     35:        int loop; /* -1 no loop, otherwise specifies loop start pos */
                     36: } wav_stream;
                     37: 
                     38: wav_stream sfx_buf[MAX_SAMPLES];
                     39: wav_stream wav_channels[MAX_CHANNELS];
                     40: 
                     41: BOOL bSoundWorking = TRUE;                /* Is sound OK */
                     42: volatile BOOL bPlayingBuffer = FALSE;     /* Is playing buffer? */
                     43: int SoundBufferSize = 1024;               /* Size of sound buffer */
                     44: 
                     45: #ifdef OGG_MUSIC
                     46: static OggVorbis_File music_file;
                     47: static int music_mode;
                     48: static BOOL music_playing = FALSE;
                     49: static int enabled_tracks;
                     50: 
                     51: static void play_music (int track)
                     52: {
                     53:        char buf[32];
                     54:        FILE *f;
                     55: 
                     56:        if (music_playing == TRUE) ov_clear (&music_file);
                     57:        
                     58:        snprintf (buf, sizeof (buf), "music/%02d.ogg", track);
                     59: 
                     60:        f = fopen (buf, "rb");
                     61:        if (f == NULL) {
                     62:                music_playing = FALSE;
                     63:                return;
                     64:        }
                     65: 
                     66:        if (ov_open (f, &music_file, NULL, 0) < 0) {
                     67:                fprintf (stderr, "Libvorbis could not open '%s'. Is it an ogg file?\n", buf);
                     68:                fclose (f);
                     69:                music_playing = FALSE;
                     70:                return;
                     71:        }
                     72: 
                     73:        music_playing = TRUE;
                     74: 
                     75: }
                     76: 
                     77: int rand_tracknum ()
                     78: {
                     79:        int track;
                     80:        if (enabled_tracks == 0) return 999;
                     81:        do {
                     82:                track = rand () % 8;
                     83:        } while ((enabled_tracks & (1<<track)) == 0);
                     84:        return track;
                     85: }
                     86: #endif /* OGG_MUSIC */
                     87: 
                     88: void Call_PlayMusic ()
                     89: {
                     90: #ifdef OGG_MUSIC
                     91:        /* Playing mode in d0:
                     92:         * -2 = play random track once
                     93:         * -1 = play random tracks continuously
                     94:         * 0+ = play specific track once
                     95:         * d1:d2 is a mask of enabled tracks
                     96:         */
                     97:        //printf ("Play track $%x. Enabled tracks $%x%x.\n", GetReg (0), GetReg (1), GetReg(2));
                     98:        music_mode = GetReg (0);
                     99: 
                    100:        enabled_tracks = 0;
                    101: 
                    102:        if (GetReg (1)&0xff000000) enabled_tracks |= 0x1;
                    103:        if (GetReg (1)&0xff0000) enabled_tracks |= 0x2;
                    104:        if (GetReg (1)&0xff00) enabled_tracks |= 0x4;
                    105:        if (GetReg (1)&0xff) enabled_tracks |= 0x8;
                    106:        if (GetReg (2)&0xff000000) enabled_tracks |= 0x10;
                    107:        if (GetReg (2)&0xff0000) enabled_tracks |= 0x20;
                    108:        if (GetReg (2)&0xff00) enabled_tracks |= 0x40;
                    109:        if (GetReg (2)&0xff) enabled_tracks |= 0x80;
                    110:        
                    111:        SDL_LockAudio ();
                    112:        switch (music_mode) {
                    113:                case -2:
                    114:                        /* hyperspace and battle music --
                    115:                         * don't play blue danube or reward music */
                    116:                        enabled_tracks &= ~0x40;
                    117:                        enabled_tracks &= ~0x80;
                    118:                        play_music (rand_tracknum ());
                    119:                        break;
                    120:                case -1:
                    121:                        /* any music */
                    122:                        play_music (rand_tracknum ());
                    123:                        break;
                    124:                default:
                    125:                        play_music (music_mode);
                    126:                        break;
                    127:        }
                    128:        SDL_UnlockAudio ();
                    129: 
                    130: #endif /* OGG_MUSIC */
                    131: }
                    132: 
                    133: #ifdef OGG_MUSIC
                    134: static void stop_music ()
                    135: {
                    136:        music_playing = FALSE;
                    137:        //printf ("Stop music.\n");
                    138:        ov_clear (&music_file);
                    139: }
                    140: #endif /* OGG_MUSIC */
                    141: 
                    142: void Call_StopMusic ()
                    143: {
                    144: #ifdef OGG_MUSIC
                    145:        SDL_LockAudio ();
                    146:        stop_music ();
                    147:        SDL_UnlockAudio ();
                    148: #endif /* OGG_MUSIC */
                    149: }
                    150: 
                    151: void Call_IsMusicPlaying ()
                    152: {
                    153: #ifdef OGG_MUSIC
                    154:        SetReg (0, music_playing);
                    155: #else
                    156:        SetReg (0, 0);
                    157: #endif /* OGG_MUSIC */
                    158: }
                    159: 
                    160: void Call_PlaySFX ()
                    161: {
                    162:        int sample, chan;
                    163: 
                    164:        SDL_LockAudio ();
                    165:        
                    166:        sample = (short) GetReg (REG_D0);
                    167:        chan = (short) GetReg (REG_D1);
                    168:        //printf ("Playing sample %d on channel %d.\n", sample, chan);
                    169: 
                    170:        wav_channels[chan].buf_pos = 0;
                    171:        wav_channels[chan].buf_len = sfx_buf[sample].buf_len;
                    172:        wav_channels[chan].buf = sfx_buf[sample].buf;
                    173:        wav_channels[chan].loop = sfx_buf[sample].loop;
                    174: 
                    175:        SDL_UnlockAudio ();
                    176: }
                    177: 
                    178: /*-----------------------------------------------------------------------*/
                    179: /*
                    180:   SDL audio callback function - copy emulation sound to audio system.
                    181: */
                    182: void Audio_CallBack(void *userdata, Uint8 *pDestBuffer, int len)
                    183: {
                    184:        Sint8 *pBuffer;
                    185:        int i, j;
                    186:        short sample;
                    187:        BOOL playing = FALSE;
                    188:        
                    189:        pBuffer = pDestBuffer;
                    190:        
                    191:        for (i=0; i<MAX_CHANNELS; i++) {
                    192:                if (wav_channels[i].buf != NULL) {
                    193:                        playing = TRUE;
                    194:                        break;
                    195:                }
                    196:        }
                    197: 
                    198:        memset (pDestBuffer, 0, len);
                    199: 
                    200: #ifdef OGG_MUSIC
                    201:        if (music_playing) {
                    202:                i = 0;
                    203:                while (i < len) {
                    204:                        int amt;
                    205:                        int music_section;
                    206:                        amt = ov_read (&music_file, (char *)&pDestBuffer[i],
                    207:                                        (len - i), 0, 2, 1, &music_section);
                    208:                        i += amt;
                    209: 
                    210:                        /* end of stream */
                    211:                        if (amt == 0) {
                    212:                                //printf ("ogg stream ended.\n");
                    213:                                if (music_mode == -1) {
                    214:                                        play_music (rand_tracknum ());
                    215:                                } else {
                    216:                                        stop_music ();
                    217:                                }
                    218:                                break;
                    219:                        }
                    220:                }
                    221:        }
                    222: #endif /* OGG_MUSIC */
                    223:        
                    224:        if (!playing) return;
                    225:        
                    226:        for (i = 0; i < len; i+=4) {
                    227:                sample = 0;
                    228:                for (j=0; j<MAX_CHANNELS; j++) {
                    229:                        if (wav_channels[j].buf == NULL) continue;
                    230:                        sample += *(short *)(wav_channels[j].buf + wav_channels[j].buf_pos);
                    231:                        wav_channels[j].buf_pos += 2;
                    232:                        if (wav_channels[j].buf_pos >= wav_channels[j].buf_len) {
                    233:                                /* end of sample. either loop or terminate */
                    234:                                if (wav_channels[j].loop != -1) {
                    235:                                        wav_channels[j].buf_pos = wav_channels[j].loop;
                    236:                                } else {
                    237:                                        wav_channels[j].buf = NULL;
                    238:                                }
                    239:                        }
                    240:                }
                    241:                /* stereo! */
                    242:                *((short*)pBuffer) += sample;
                    243:                pBuffer += 2;
                    244:                *((short*)pBuffer) += sample;
                    245:                pBuffer += 2;
                    246:        }
                    247: }
                    248: 
                    249: /*
                    250:  * Loaded samples must be SND_FREQ, 16-bit signed. Reject
                    251:  * other frequencies but convert 8-bit unsigned.
                    252:  */
                    253: void check_sample_format (SDL_AudioSpec *spec, Uint8 **buf, int *len, const char *filename)
                    254: {
                    255:        Uint8 *old_buf = *buf;
                    256:        short *new_buf;
                    257:        int i;
                    258: 
                    259:        if (spec->freq != SND_FREQ) {
                    260:                printf ("Sample %s is the wrong sample rate (wanted %dHz). Ignoring.\n", filename, SND_FREQ);
                    261:                SDL_FreeWAV (*buf);
                    262:                *buf = NULL;
                    263:                return;
                    264:        }
                    265: 
                    266:        if (spec->format == AUDIO_U8) {
                    267:                new_buf = malloc ((*len)*2);
                    268:                for (i=0; i<(*len); i++) {
                    269:                        new_buf[i] = (old_buf[i] ^ 128) << 8;
                    270:                }
                    271:                *len *= 2;
                    272:                SDL_FreeWAV (old_buf);
                    273:                *buf = (char *)new_buf;
                    274:        } else if (spec->format != AUDIO_S16) {
                    275:                printf ("Sample %s is not 16-bit-signed or 8-bit unsigned. Ignoring.", filename);
                    276:                SDL_FreeWAV (*buf);
                    277:                *buf = NULL;
                    278:                return;
                    279:        }
                    280: }
                    281: 
                    282: /*-----------------------------------------------------------------------*/
                    283: /*
                    284:   Initialize the audio subsystem. Return TRUE if all OK.
                    285:   We use direct access to the sound buffer, set to a unsigned 8-bit mono stream.
                    286: */
                    287: void Audio_Init(void)
                    288: {
                    289:        int i;
                    290:        char filename[32];
                    291:   SDL_AudioSpec desiredAudioSpec;    /* We fill in the desired SDL audio options here */
                    292: 
                    293:   /* Is enabled? */
                    294:   if(bDisableSound)
                    295:   {
                    296:     /* Stop any sound access */
                    297:     printf("Sound: Disabled\n");
                    298:     bSoundWorking = FALSE;
                    299:     return;
                    300:   }
                    301: 
                    302:   /* Init the SDL's audio subsystem: */
                    303:   if( SDL_WasInit(SDL_INIT_AUDIO)==0 )
                    304:   {
                    305:     if( SDL_InitSubSystem(SDL_INIT_AUDIO)<0 )
                    306:     {
                    307:       fprintf(stderr, "Could not init audio: %s\n", SDL_GetError() );
                    308:       bSoundWorking = FALSE;
                    309:       return;
                    310:     }
                    311:   }
                    312: 
                    313:   /* Set up SDL audio: */
                    314:   desiredAudioSpec.freq = SND_FREQ;
                    315:   desiredAudioSpec.format = AUDIO_S16;           /* 8 Bit unsigned */
                    316:   desiredAudioSpec.channels = 2;                /* Mono */
                    317:   desiredAudioSpec.samples = 1024;              /* Buffer size */
                    318:   desiredAudioSpec.callback = Audio_CallBack;
                    319:   desiredAudioSpec.userdata = NULL;
                    320: 
                    321:   if( SDL_OpenAudio(&desiredAudioSpec, NULL) )  /* Open audio device */
                    322:   {
                    323:     fprintf(stderr, "Can't use audio: %s\n", SDL_GetError());
                    324:     bSoundWorking = FALSE;
                    325:     //ConfigureParams.Sound.bEnableSound = FALSE;
                    326:     return;
                    327:   }
                    328: 
                    329:   SoundBufferSize = desiredAudioSpec.size;      /* May be different than the requested one! */
                    330: 
                    331:   for (i=0; i<MAX_SAMPLES; i++) {
                    332:          snprintf (filename, sizeof (filename), "sfx/sfx_%02d.wav", i);
                    333:          if (SDL_LoadWAV (filename, &desiredAudioSpec, &sfx_buf[i].buf,
                    334:                                  &sfx_buf[i].buf_len) == NULL) {
                    335:                printf ("Error loading %s: %s\n", filename, SDL_GetError ());
                    336:                sfx_buf[i].buf = NULL;
                    337:          }
                    338:          check_sample_format (&desiredAudioSpec, &sfx_buf[i].buf, &sfx_buf[i].buf_len, filename);
                    339:          
                    340:          /* 19 (hyperspace) and 23 (noise) loop */
                    341:          if (i == 19) sfx_buf[i].loop = SND_FREQ; /* loop to about 0.5 sec in */
                    342:          else if (i == 23) sfx_buf[i].loop = 0;
                    343:          else sfx_buf[i].loop = -1;
                    344:   }
                    345:   
                    346:   /* All OK */
                    347:   bSoundWorking = TRUE;
                    348:   /* And begin */
                    349:   Audio_EnableAudio(TRUE);
                    350: }
                    351: 
                    352: 
                    353: /*-----------------------------------------------------------------------*/
                    354: /*
                    355:   Free audio subsystem
                    356: */
                    357: void Audio_UnInit(void)
                    358: {
                    359:   /* Stop */
                    360:   Audio_EnableAudio(FALSE);
                    361: 
                    362:   SDL_CloseAudio();
                    363: }
                    364: 
                    365: 
                    366: /*-----------------------------------------------------------------------*/
                    367: /*
                    368:   Start/Stop sound buffer
                    369: */
                    370: void Audio_EnableAudio(BOOL bEnable)
                    371: {
                    372:   if(bEnable && !bPlayingBuffer)
                    373:   {
                    374:     /* Start playing */
                    375:     SDL_PauseAudio(FALSE);
                    376:     bPlayingBuffer = TRUE;
                    377:   }
                    378:   else if(!bEnable && bPlayingBuffer)
                    379:   {
                    380:     /* Stop from playing */
                    381:     SDL_PauseAudio(!bEnable);
                    382:     bPlayingBuffer = bEnable;
                    383:   }
                    384: }
                    385: 

unix.superglobalmegacorp.com

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