Annotation of generator/main/gensoundp-unix.c, revision 1.1.1.3

1.1       root        1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
                      2: 
                      3: #include <sys/types.h>
                      4: #include <sys/stat.h>
                      5: #include <sys/ioctl.h>
                      6: #include <unistd.h>
                      7: #include <fcntl.h>
                      8: #include <errno.h>
                      9: #include <string.h>
                     10: #include <math.h>
                     11: 
                     12: #include "generator.h"
                     13: #include "gensound.h"
                     14: #include "gensoundp.h"
                     15: #include "vdp.h"
                     16: #include "ui.h"
                     17: 
                     18: #ifdef JFM
                     19: #  include "jfm.h"
                     20: #else
                     21: #  include "support.h"
                     22: #  include "fm.h"
                     23: #endif
                     24: 
1.1.1.3 ! root       25: #if defined(__NetBSD__) || defined(__OpenBSD__)
        !            26:   #include <soundcard.h>
        !            27:   #define SOUND_DEVICE "/dev/sound"
        !            28: #else
        !            29:   #include <sys/soundcard.h>
        !            30:   #define SOUND_DEVICE "/dev/dsp"
        !            31: #endif
1.1       root       32: 
                     33: /*** variables externed ***/
                     34: 
                     35: /*** forward references ***/
                     36: 
                     37: /*** file scoped variables ***/
                     38: 
                     39: static int soundp_dev = -1;
                     40: static int soundp_format;
                     41: static int soundp_stereo;
                     42: static int soundp_frag;
                     43: static unsigned int soundp_speed;
                     44: 
                     45: #ifdef JFM
                     46: static t_jfm_ctx *sound_ctx;
                     47: #endif
                     48: 
                     49: /*** soundp_start - start sound hardware ***/
                     50: 
                     51: int soundp_start(void)
                     52: {
                     53:   audio_buf_info sound_info;
                     54: 
                     55:   if ((soundp_dev = open(SOUND_DEVICE, O_WRONLY, 0)) == -1) {
                     56:     LOG_CRITICAL(("open " SOUND_DEVICE " failed: %s", strerror(errno)));
                     57:     return 1;
                     58:   }
                     59:   soundp_frag = (sound_maxfields << 16 |
                     60:                  (int)(ceil(log10(sound_sampsperfield * 4) / log10(2))));
                     61:   if (ioctl(soundp_dev, SNDCTL_DSP_SETFRAGMENT, &soundp_frag) == -1) {
                     62:     LOG_CRITICAL(("Error setting fragment size: %s", strerror(errno)));
                     63:     close(soundp_dev);
                     64:     return 1;
                     65:   }
1.1.1.3 ! root       66: #ifdef WORDS_BIGENDIAN
        !            67:   soundp_format = AFMT_S16_BE;
        !            68: #else
1.1       root       69:   soundp_format = AFMT_S16_LE;
1.1.1.3 ! root       70: #endif
1.1       root       71:   if (ioctl(soundp_dev, SNDCTL_DSP_SETFMT, &soundp_format) == -1) {
                     72:     LOG_CRITICAL(("Error setting sound device format: %s", strerror(errno)));
                     73:     close(soundp_dev);
                     74:     return 1;
                     75:   }
                     76:   if (soundp_format != AFMT_S16_LE && soundp_format != AFMT_S16_BE) {
                     77:     LOG_CRITICAL(("Sound device format not supported (must be 16 bit)"));
                     78:     close(soundp_dev);
                     79:     return 1;
                     80:   }
                     81:   soundp_stereo = 1;
                     82:   if (ioctl(soundp_dev, SNDCTL_DSP_STEREO, &soundp_stereo) == -1) {
                     83:     LOG_CRITICAL(("Error setting stereo: %s", strerror(errno)));
                     84:     close(soundp_dev);
                     85:     return 1;
                     86:   }
                     87:   if (soundp_stereo != 1) {
                     88:     LOG_CRITICAL(("Sound device does not support stereo"));
                     89:     close(soundp_dev);
                     90:     return 1;
                     91:   }
                     92:   soundp_speed = sound_speed;
                     93:   if (ioctl(soundp_dev, SNDCTL_DSP_SPEED, &soundp_speed) == -1) {
                     94:     LOG_CRITICAL(("Error setting sound speed: %s", strerror(errno)));
                     95:     close(soundp_dev);
                     96:     return 1;
                     97:   }
                     98:   if (soundp_speed != sound_speed) {
                     99:     if (abs(soundp_speed - sound_speed) < 100) {
                    100:       LOG_NORMAL(("Warning: Sample rate not exactly 22050"));
                    101:     } else {
                    102:       LOG_CRITICAL(("Sound device does not support sample rate %d "
                    103:                     "(returned %d)", sound_speed, soundp_speed));
                    104:       close(soundp_dev);
                    105:       return 1;
                    106:     }
                    107:   }
                    108:   if (ioctl(soundp_dev, SNDCTL_DSP_GETOSPACE, &sound_info) == -1) {
                    109:     LOG_CRITICAL(("Error getting output space info", strerror(errno)));
                    110:     close(soundp_dev);
                    111:     return 1;
                    112:   }
                    113:   LOG_VERBOSE(("Total allocated fragments = %d (requested %d)",
                    114:                sound_info.fragstotal, sound_maxfields));
                    115:   LOG_VERBOSE(("Fragment size = %d (requested %d)", sound_info.fragsize,
                    116:                sound_sampsperfield * 4));
                    117:   LOG_VERBOSE(("Bytes free in buffer = %d", sound_info.bytes));
                    118:   LOG_VERBOSE(("Theshold = %d bytes (%d fields of sound === %dms latency)",
                    119:                sound_threshold * 4, sound_minfields,
                    120:                (int)(1000 * (float)sound_minfields / (float)vdp_framerate)));
                    121:   if ((signed)sound_threshold >= sound_info.bytes) {
                    122:     LOG_CRITICAL(("Threshold exceeds bytes free in buffer"));
                    123:     close(soundp_dev);
                    124:     return 1;
                    125:   }
                    126:   return 0;
                    127: }
                    128: 
                    129: /*** soundp_stop - stop sound hardware ***/
                    130: 
                    131: void soundp_stop(void)
                    132: {
                    133:   if (soundp_dev != -1)
                    134:     close(soundp_dev);
                    135:   soundp_dev = -1;
                    136: }
                    137: 
                    138: /*** sound_samplesbuffered - how many samples are currently buffered? ***/
                    139: 
                    140: int soundp_samplesbuffered(void)
                    141: {
                    142:   audio_buf_info sound_info;
                    143:   int pending;
                    144: 
                    145:   if (ioctl(soundp_dev, SNDCTL_DSP_GETOSPACE, &sound_info) == -1) {
                    146:     LOG_CRITICAL(("Error getting output space info: %s", strerror(errno)));
                    147:     return -1;
                    148:   }
                    149:   pending = (sound_info.fragstotal * sound_info.fragsize) - sound_info.bytes;
                    150:   return (pending / 4);         /* 2 bytes per sample, 2 channel stereo */
                    151: }
                    152: 
                    153: void soundp_output(uint16 *left, uint16 *right, unsigned int samples)
                    154: {
                    155:   uint16 buffer[(SOUND_MAXRATE / 50) * 2];      /* pal is slowest framerate */
                    156: #ifdef WORDS_BIGENDIAN
                    157:   int endian = 1;
                    158: #else
                    159:   int endian = 0;
                    160: #endif
                    161:   unsigned int i;
                    162: 
                    163:   if (samples > (sizeof(buffer) << 1)) {
                    164:     /* we only bother with coping with one fields worth of samples */
                    165:     LOG_CRITICAL(("Too many samples passed to soundp_output!"));
                    166:     return;
                    167:   }
1.1.1.3 ! root      168: #ifdef WORDS_BIGENDIAN
        !           169:   if (soundp_format == AFMT_S16_BE) {
        !           170: #else  
        !           171:   if (soundp_format == AFMT_S16_LE) {
        !           172: #endif  
1.1       root      173:     /* device matches endianness of host */
                    174:     for (i = 0; i < samples; i++) {
                    175:       buffer[i * 2] = left[i];
                    176:       buffer[i * 2 + 1] = right[i];
                    177:     }
                    178:   } else {
                    179:     /* device is odd and is different to host endianness */
                    180:     for (i = 0; i < samples; i++) {
                    181:       buffer[i * 2] = ((left[i] >> 8) | ((left[i] << 8) & 0xff00));
                    182:       buffer[i * 2 + 1] = ((right[i] >> 8) | ((right[i] << 8) & 0xff00));
                    183:     }
                    184:   }
                    185:   if (write(soundp_dev, buffer, samples * 4) == -1) {
1.1.1.3 ! root      186:     if (errno != EINTR && errno != EWOULDBLOCK)
1.1       root      187:       LOG_CRITICAL(("Error writing to sound device: %s", strerror(errno)));
                    188:   }
                    189: }

unix.superglobalmegacorp.com

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