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

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

unix.superglobalmegacorp.com

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