Annotation of frontvm/src/audio.c, revision 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.