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

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

unix.superglobalmegacorp.com

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