Annotation of uae/src/sd-sdl/sound.c, revision 1.1.1.5

1.1.1.4   root        1:  /*
1.1       root        2:   * UAE - The Un*x Amiga Emulator
1.1.1.4   root        3:   *
1.1       root        4:   * Support for Linux/USS sound
1.1.1.4   root        5:   *
1.1       root        6:   * Copyright 1997 Bernd Schmidt
                      7:   */
                      8: 
                      9: #include "sysconfig.h"
                     10: #include "sysdeps.h"
                     11: 
                     12: #include "options.h"
                     13: #include "memory.h"
                     14: #include "events.h"
                     15: #include "custom.h"
                     16: #include "gensound.h"
                     17: #include "sounddep/sound.h"
                     18: #include "threaddep/thread.h"
                     19: #include "SDL_audio.h"
                     20: 
                     21: int sound_fd;
                     22: static int have_sound = 0;
                     23: static unsigned long formats;
                     24: 
1.1.1.5 ! root       25: uae_u16 sndbuffer[2][44100];
        !            26: uae_u16 *sndbufpt, *sndbuf_base;
        !            27: int which_buffer;
1.1       root       28: int sndbufsize;
                     29: static SDL_AudioSpec spec;
                     30: 
                     31: static smp_comm_pipe to_sound_pipe;
                     32: static uae_sem_t data_available_sem, callback_done_sem, sound_init_sem;
                     33: 
1.1.1.5 ! root       34: static int dont_block;
        !            35: 
1.1       root       36: static int in_callback, closing_sound;
                     37: 
                     38: static void sound_callback (void *userdata, Uint8 *stream, int len)
                     39: {
                     40:     if (closing_sound)
                     41:        return;
                     42:     in_callback = 1;
                     43:     /* Wait for data to finish.  */
                     44:     uae_sem_wait (&data_available_sem);
                     45:     if (! closing_sound) {
                     46:        memcpy (stream, sndbuffer, sndbufsize);
1.1.1.5 ! root       47: 
1.1       root       48:        /* Notify writer that we're done.  */
1.1.1.5 ! root       49:        if (!dont_block)
        !            50:            uae_sem_post (&callback_done_sem);
        !            51:        else
        !            52:            blocking_on_sound = 0;
1.1       root       53:     }
                     54:     in_callback = 0;
                     55: }
                     56: 
                     57: void finish_sound_buffer (void)
                     58: {
1.1.1.5 ! root       59:     dont_block = currprefs.m68k_speed == -1;
        !            60: 
        !            61:     if (dont_block)
        !            62:        blocking_on_sound = 1;
1.1       root       63:     uae_sem_post (&data_available_sem);
1.1.1.5 ! root       64:     if (!dont_block)
        !            65:        uae_sem_wait (&callback_done_sem);
        !            66:     sndbufpt = sndbuffer[which_buffer ^= 1];
1.1       root       67: }
                     68: 
                     69: /* Try to determine whether sound is available.  This is only for GUI purposes.  */
                     70: int setup_sound (void)
                     71: {
                     72:     int size = currprefs.sound_maxbsiz;
                     73: 
                     74:     spec.freq = currprefs.sound_freq;
                     75:     spec.format = AUDIO_S16;
1.1.1.3   root       76:     spec.channels = currprefs.sound_stereo ? 2 : 1;
1.1       root       77:     size >>= spec.channels - 1;
                     78:     size >>= 1;
                     79:     while (size & (size - 1))
                     80:        size &= size - 1;
                     81:     if (size < 512)
                     82:        size = 512;
                     83:     spec.samples = size;
                     84:     spec.callback = sound_callback;
                     85:     spec.userdata = 0;
                     86: 
                     87:     if (SDL_OpenAudio (&spec, NULL) < 0) {
                     88:        write_log (stderr, "Couldn't open audio: %s\n", SDL_GetError());
                     89:        return 0;
                     90:     }
                     91:     sound_available = 1;
                     92:     SDL_CloseAudio ();
                     93:     return 1;
                     94: }
                     95: 
                     96: static int open_sound (void)
                     97: {
                     98:     int size = currprefs.sound_maxbsiz;
                     99: 
                    100:     spec.freq = currprefs.sound_freq;
1.1.1.5 ! root      101:     spec.format = AUDIO_S16;
1.1.1.3   root      102:     spec.channels = currprefs.sound_stereo ? 2 : 1;
1.1       root      103:     /* Always interpret buffer size as number of samples, not as actual
                    104:        buffer size.  Of course, since 8192 is the default, we'll have to
                    105:        scale that to a sane value (assuming that otherwise 16 bits and
                    106:        stereo would have been enabled and we'd have done the shift by
                    107:        two anyway).  */
1.1.1.5 ! root      108:     size >>= spec.channels;
        !           109: 
1.1       root      110:     while (size & (size - 1))
                    111:        size &= size - 1;
                    112:     if (size < 512)
                    113:        size = 512;
                    114:     spec.samples = size;
                    115:     spec.callback = sound_callback;
                    116:     spec.userdata = 0;
                    117: 
                    118:     if (SDL_OpenAudio (&spec, NULL) < 0) {
                    119:        write_log (stderr, "Couldn't open audio: %s\n", SDL_GetError());
                    120:        return 0;
                    121:     }
                    122:     have_sound = 1;
                    123: 
1.1.1.5 ! root      124:     obtainedfreq = spec.freq;
1.1       root      125: 
                    126:     if (spec.format == AUDIO_S16) {
                    127:        init_sound_table16 ();
1.1.1.3   root      128:        sample_handler = currprefs.sound_stereo ? sample16s_handler : sample16_handler;
1.1       root      129:     } else {
                    130:        init_sound_table8 ();
1.1.1.3   root      131:        sample_handler = currprefs.sound_stereo ? sample8s_handler : sample8_handler;
1.1       root      132:     }
                    133:     sound_available = 1;
1.1.1.5 ! root      134:     write_log ("SDL sound driver found and configured at %d Hz, buffer is %d samples\n",
        !           135:               spec.freq, spec.samples);
        !           136:     sndbufpt = sndbuf_base = sndbuffer[which_buffer = 0];
        !           137:     sndbufsize = size * 2 * spec.channels;
1.1       root      138:     return 1;
                    139: }
                    140: 
                    141: static void *sound_thread (void *dummy)
                    142: {
                    143:     for (;;) {
                    144:        int cmd = read_comm_pipe_int_blocking (&to_sound_pipe);
                    145:        int n;
                    146: 
                    147:        switch (cmd) {
                    148:        case 0:
                    149:            open_sound ();
                    150:            uae_sem_post (&sound_init_sem);
                    151:            break;
                    152:        case 1:
                    153:            uae_sem_post (&sound_init_sem);
                    154:            return 0;
                    155:        }
                    156:     }
                    157: }
                    158: 
                    159: /* We need a thread for this, since communication between finish_sound_buffer
                    160:    and the callback works through semaphores.  In theory, this is unnecessary,
                    161:    since SDL uses a sound thread internally, and the callback runs in its
                    162:    context.  But we don't want to depend on SDL's internals too much.  */
                    163: static void init_sound_thread (void)
                    164: {
                    165:     uae_thread_id tid;
                    166: 
                    167:     init_comm_pipe (&to_sound_pipe, 20, 1);
                    168:     uae_sem_init (&data_available_sem, 0, 0);
                    169:     uae_sem_init (&callback_done_sem, 0, 0);
                    170:     uae_sem_init (&sound_init_sem, 0, 0);
                    171:     uae_start_thread (sound_thread, NULL, &tid);
                    172: }
                    173: 
                    174: void close_sound (void)
                    175: {
                    176:     if (! have_sound)
                    177:        return;
                    178: 
                    179:     SDL_PauseAudio (1);
                    180:     if (in_callback) {
                    181:        closing_sound = 1;
                    182:        uae_sem_post (&data_available_sem);
                    183:     }
                    184:     write_comm_pipe_int (&to_sound_pipe, 1, 1);
                    185:     uae_sem_wait (&sound_init_sem);
                    186:     SDL_CloseAudio ();
                    187:     uae_sem_destroy (&data_available_sem);
                    188:     uae_sem_destroy (&sound_init_sem);
                    189:     uae_sem_destroy (&callback_done_sem);
                    190:     have_sound = 0;
                    191: }
                    192: 
                    193: int init_sound (void)
                    194: {
                    195:     in_callback = 0;
                    196:     closing_sound = 0;
                    197: 
                    198:     init_sound_thread ();
                    199:     write_comm_pipe_int (&to_sound_pipe, 0, 1);
                    200:     uae_sem_wait (&sound_init_sem);
                    201:     SDL_PauseAudio (0);
                    202: 
                    203:     return have_sound;
                    204: }
                    205: 
                    206: void pause_sound (void)
                    207: {
                    208:     SDL_PauseAudio (1);
                    209: }
                    210: 
                    211: void resume_sound (void)
                    212: {
                    213:     SDL_PauseAudio (0);
                    214: }

unix.superglobalmegacorp.com

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