Annotation of uae/src/sd-uss/sound.c, revision 1.1.1.9

1.1.1.8   root        1:  /*
1.1       root        2:   * UAE - The Un*x Amiga Emulator
1.1.1.8   root        3:   *
1.1       root        4:   * Support for Linux/USS sound
1.1.1.8   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"
1.1.1.4   root       14: #include "events.h"
1.1       root       15: #include "custom.h"
                     16: #include "gensound.h"
                     17: #include "sounddep/sound.h"
1.1.1.9 ! root       18: #include "threaddep/thread.h"
1.1       root       19: 
                     20: #include <sys/ioctl.h>
                     21: 
                     22: #ifdef HAVE_SYS_SOUNDCARD_H
                     23: #include <sys/soundcard.h>
                     24: #elif defined HAVE_MACHINE_SOUNDCARD_H
                     25: #include <machine/soundcard.h>
                     26: #else
                     27: #error "Something went wrong during configuration."
                     28: #endif
                     29: 
1.1.1.9 ! root       30: static smp_comm_pipe to_sound_pipe;
        !            31: static uae_sem_t sound_comm_sem;
        !            32: 
        !            33: static int sound_fd;
1.1.1.3   root       34: static int have_sound = 0;
1.1.1.9 ! root       35: static int dont_block;
1.1       root       36: static unsigned long formats;
                     37: 
1.1.1.9 ! root       38: static int which_buffer;
        !            39: static uae_u16 sndbuffer[2][44100];
        !            40: uae_u16 *sndbufpt, *sndbuf_base;
1.1       root       41: int sndbufsize;
                     42: 
1.1.1.2   root       43: static int exact_log2 (int v)
1.1       root       44: {
                     45:     int l = 0;
                     46:     while ((v >>= 1) != 0)
                     47:        l++;
                     48:     return l;
                     49: }
                     50: 
1.1.1.9 ! root       51: void finish_sound_buffers (void)
        !            52: {
        !            53:     dont_block = currprefs.m68k_speed == -1;
        !            54:     write_comm_pipe_int (&to_sound_pipe, 2, 1);
        !            55:     uae_sem_wait (&sound_comm_sem);
        !            56:     sndbufpt = sndbuf_base = sndbuffer[which_buffer ^= 1];
        !            57: }
        !            58: 
1.1.1.2   root       59: void close_sound (void)
1.1       root       60: {
                     61:     if (have_sound)
1.1.1.2   root       62:        close (sound_fd);
1.1.1.9 ! root       63: 
        !            64:     write_comm_pipe_int (&to_sound_pipe, 1, 1);
        !            65:     uae_sem_wait (&sound_comm_sem);
        !            66:     uae_sem_destroy (&sound_comm_sem);
1.1       root       67: }
                     68: 
1.1.1.3   root       69: /* Try to determine whether sound is available.  This is only for GUI purposes.  */
1.1.1.2   root       70: int setup_sound (void)
1.1       root       71: {
                     72:     sound_fd = open ("/dev/dsp", O_WRONLY);
1.1.1.3   root       73: 
                     74:     sound_available = 0;
                     75: 
                     76:     if (sound_fd < 0) {
                     77:        perror ("Can't open /dev/dsp");
                     78:        if (errno == EBUSY) {
                     79:            /* We can hope, can't we ;) */
                     80:            sound_available = 1;
                     81:            return 1;
                     82:        }
1.1       root       83:        return 0;
1.1.1.3   root       84:     }
1.1       root       85: 
                     86:     if (ioctl (sound_fd, SNDCTL_DSP_GETFMTS, &formats) == -1) {
1.1.1.3   root       87:        perror ("ioctl failed - can't use sound");
                     88:        close (sound_fd);
1.1       root       89:        return 0;
                     90:     }
                     91: 
                     92:     sound_available = 1;
1.1.1.3   root       93:     close (sound_fd);
1.1       root       94:     return 1;
                     95: }
                     96: 
1.1.1.9 ! root       97: static void open_sound (void)
1.1       root       98: {
                     99:     int tmp;
                    100:     int rate;
                    101:     int dspbits;
                    102: 
1.1.1.3   root      103:     sound_fd = open ("/dev/dsp", O_WRONLY);
                    104:     have_sound = !(sound_fd < 0);
                    105:     if (! have_sound) {
                    106:        perror ("Can't open /dev/dsp");
                    107:        if (errno != EBUSY)
                    108:            sound_available = 0;
1.1.1.9 ! root      109:        return;
1.1.1.3   root      110:     }
                    111:     if (ioctl (sound_fd, SNDCTL_DSP_GETFMTS, &formats) == -1) {
                    112:        perror ("ioctl failed - can't use sound");
1.1.1.9 ! root      113:        goto out_err;
1.1.1.3   root      114:     }
                    115: 
1.1       root      116:     if (currprefs.sound_maxbsiz < 128 || currprefs.sound_maxbsiz > 16384) {
1.1.1.2   root      117:        fprintf (stderr, "Sound buffer size %d out of range.\n", currprefs.sound_maxbsiz);
1.1       root      118:        currprefs.sound_maxbsiz = 8192;
                    119:     }
                    120: 
1.1.1.2   root      121:     tmp = 0x00040000 + exact_log2 (currprefs.sound_maxbsiz);
1.1       root      122:     ioctl (sound_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
                    123:     ioctl (sound_fd, SNDCTL_DSP_GETBLKSIZE, &sndbufsize);
                    124: 
1.1.1.9 ! root      125:     dspbits = 16;
1.1       root      126:     ioctl (sound_fd, SNDCTL_DSP_SAMPLESIZE, &dspbits);
                    127:     ioctl (sound_fd, SOUND_PCM_READ_BITS, &dspbits);
1.1.1.9 ! root      128:     if (dspbits != 16) {
        !           129:        fprintf (stderr, "Can't use sound with 16 bits\n");
        !           130:        goto out_err;
1.1       root      131:     }
                    132: 
1.1.1.7   root      133:     tmp = currprefs.sound_stereo;
1.1       root      134:     ioctl (sound_fd, SNDCTL_DSP_STEREO, &tmp);
                    135: 
                    136:     rate = currprefs.sound_freq;
                    137:     ioctl (sound_fd, SNDCTL_DSP_SPEED, &rate);
                    138:     ioctl (sound_fd, SOUND_PCM_READ_RATE, &rate);
                    139:     /* Some soundcards have a bit of tolerance here. */
                    140:     if (rate < currprefs.sound_freq * 90 / 100 || rate > currprefs.sound_freq * 110 / 100) {
1.1.1.2   root      141:        fprintf (stderr, "Can't use sound with desired frequency %d\n", currprefs.sound_freq);
1.1.1.9 ! root      142:        goto out_err;
1.1       root      143:     }
                    144: 
1.1.1.9 ! root      145:     obtainedfreq = rate;
1.1       root      146: 
1.1.1.9 ! root      147:     if (!(formats & AFMT_S16_NE))
        !           148:        goto out_err;
        !           149:     init_sound_table16 ();
        !           150:     sample_handler = currprefs.sound_stereo ? sample16s_handler : sample16_handler;
        !           151: 
        !           152:     sound_available = 1;
        !           153:     printf ("Sound driver found and configured at %d Hz, buffer is %d bytes (%d ms).\n",
        !           154:            rate, sndbufsize, sndbufsize * 1000 / (rate * 2 * (currprefs.sound_stereo ? 2 : 1)));
        !           155:     sndbufpt = sndbuf_base = sndbuffer[which_buffer = 0];
        !           156: 
        !           157:     return;
        !           158: 
        !           159:   out_err:
        !           160:     close (sound_fd);
        !           161:     have_sound = 0;
        !           162:     return;
        !           163: }
        !           164: 
        !           165: static void *sound_thread (void *dummy)
        !           166: {
        !           167:     for (;;) {
        !           168:        int cmd = read_comm_pipe_int_blocking (&to_sound_pipe);
        !           169:        int n;
        !           170: 
        !           171:        switch (cmd) {
        !           172:        case 0:
        !           173:            open_sound ();
        !           174:            uae_sem_post (&sound_comm_sem);
        !           175:            break;
        !           176:        case 1:
        !           177:            uae_sem_post (&sound_comm_sem);
1.1       root      178:            return 0;
1.1.1.9 ! root      179:        case 2:
        !           180:            /* If trying for maximum CPU speed, don't block the main
        !           181:               thread, instead set the blocking_on_sound variable.  If
        !           182:               not trying for maximum CPU speed, synchronize here by
        !           183:               delaying the sem_post until after the write.  */
        !           184:            blocking_on_sound = dont_block;
        !           185:            if (dont_block)
        !           186:                uae_sem_post (&sound_comm_sem);
        !           187: 
        !           188:            write (sound_fd, sndbuffer[which_buffer], sndbufsize);
        !           189:            if (!dont_block)
        !           190:                uae_sem_post (&sound_comm_sem);
        !           191: 
        !           192:            blocking_on_sound = 0;
        !           193:            break;
        !           194:        }
1.1       root      195:     }
1.1.1.9 ! root      196: }
1.1.1.8   root      197: 
1.1.1.9 ! root      198: /* We use a thread so that we can use the time spent waiting for the sound
        !           199:    driver for executing m68k instructions, rather than just blocking.  */
        !           200: static void init_sound_thread (void)
        !           201: {
        !           202:     uae_thread_id tid;
        !           203: 
        !           204:     init_comm_pipe (&to_sound_pipe, 20, 1);
        !           205:     uae_sem_init (&sound_comm_sem, 0, 0);
        !           206:     uae_start_thread (sound_thread, NULL, &tid);
        !           207: }
        !           208: 
        !           209: int init_sound (void)
        !           210: {
        !           211:     init_sound_thread ();
        !           212:     write_comm_pipe_int (&to_sound_pipe, 0, 1);
        !           213:     uae_sem_wait (&sound_comm_sem);
        !           214: 
        !           215:     return have_sound;
1.1       root      216: }

unix.superglobalmegacorp.com

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