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

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

unix.superglobalmegacorp.com

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