|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.