|
|
1.1 ! root 1: /*****************************************************************************/ ! 2: /* Generator - Sega Genesis emulation - (c) James Ponder 1997-1998 */ ! 3: /*****************************************************************************/ ! 4: /* */ ! 5: /* sound.c */ ! 6: /* */ ! 7: /*****************************************************************************/ ! 8: ! 9: #include <string.h> ! 10: #include <stdio.h> ! 11: #include <sys/types.h> ! 12: #include <sys/stat.h> ! 13: #include <fcntl.h> ! 14: #include <errno.h> ! 15: #include <sys/ioctl.h> ! 16: #include <unistd.h> ! 17: #include <math.h> ! 18: ! 19: #include "generator.h" ! 20: #include "gensound.h" ! 21: #include "vdp.h" ! 22: #include "ui.h" ! 23: ! 24: #ifdef JFM ! 25: # include "jfm.h" ! 26: #else ! 27: # include "support.h" ! 28: # include "fm.h" ! 29: #endif ! 30: ! 31: #include <sys/soundcard.h> ! 32: ! 33: /*** variables externed ***/ ! 34: ! 35: int sound_feedback = 0; /* -1, running out of sound ! 36: +0, lots of sound, do something */ ! 37: unsigned int sound_threshold; /* bytes in buffer we're trying to maintain */ ! 38: ! 39: /* SN76489 snd_cpu; */ ! 40: ! 41: /*** forward references ***/ ! 42: ! 43: /* void snd_sndout(int chan, int freq, int vol); */ ! 44: ! 45: /*** file scoped variables ***/ ! 46: ! 47: #define SOUND_MAXRATE 44100 ! 48: #define SOUND_FRAGMENTS 12 ! 49: #define SOUND_THRESHOLD 10 ! 50: ! 51: static unsigned int sound_sampsperfield = 0; ! 52: static int sound_dev = 0; ! 53: /* static int sound_dump = 0; */ ! 54: static uint16 soundbuf[2][SOUND_MAXRATE/50]; /* pal is lowest framerate */ ! 55: static int sound_format; ! 56: static int sound_stereo; ! 57: static int sound_speed; ! 58: static int sound_frag; ! 59: static int sound_fragsize; ! 60: static int sound_inited = 0; /* flag to say whether we've inited */ ! 61: ! 62: #ifdef JFM ! 63: static t_jfm_ctx *sound_ctx; ! 64: #endif ! 65: ! 66: /*** sound_init - initialise this sub-unit ***/ ! 67: ! 68: int sound_init(void) ! 69: { ! 70: audio_buf_info sound_info; ! 71: ! 72: LOG_NORMAL(("Initialising sound...")); ! 73: sound_sampsperfield = SOUND_SAMPLERATE / vdp_framerate; ! 74: ! 75: /* sound_dump = open("/tmp/sound_dump", O_CREAT|O_WRONLY|O_TRUNC); */ ! 76: ! 77: if ((sound_dev = open(SOUND_DEVICE, O_WRONLY, 0)) == -1) { ! 78: LOG_CRITICAL(("open " SOUND_DEVICE " failed: %s", strerror(errno))); ! 79: return 1; ! 80: } ! 81: sound_frag = (SOUND_FRAGMENTS<<16 | ! 82: (int)(ceil(log10(sound_sampsperfield*4)/log10(2)))); ! 83: if (ioctl(sound_dev, SNDCTL_DSP_SETFRAGMENT, &sound_frag) == -1) { ! 84: LOG_CRITICAL(("Error setting fragment size: %s", strerror(errno))); ! 85: return 1; ! 86: } ! 87: sound_format = AFMT_S16_LE; ! 88: if (ioctl(sound_dev, SNDCTL_DSP_SETFMT, &sound_format) == -1) { ! 89: LOG_CRITICAL(("Error setting sound device format: %s", strerror(errno))); ! 90: return 1; ! 91: } ! 92: if (sound_format != AFMT_S16_LE && sound_format != AFMT_S16_BE) { ! 93: LOG_CRITICAL(("Sound device format not supported (must be 16 bit)")); ! 94: return 1; ! 95: } ! 96: sound_stereo = 1; ! 97: if (ioctl(sound_dev, SNDCTL_DSP_STEREO, &sound_stereo) == -1) { ! 98: LOG_CRITICAL(("Error setting stereo: %s", strerror(errno))); ! 99: return 1; ! 100: } ! 101: if (sound_stereo != 1) { ! 102: LOG_CRITICAL(("Sound device does not support stereo")); ! 103: return 1; ! 104: } ! 105: sound_speed = SOUND_SAMPLERATE; ! 106: if (ioctl(sound_dev, SNDCTL_DSP_SPEED, &sound_speed) == -1) { ! 107: LOG_CRITICAL(("Error setting sound speed: %s", strerror(errno))); ! 108: return 1; ! 109: } ! 110: if (sound_speed != SOUND_SAMPLERATE) { ! 111: if (abs(sound_speed-SOUND_SAMPLERATE) > 50) { ! 112: LOG_NORMAL(("Warning: Sample rate not exactly 22050")); ! 113: } else { ! 114: LOG_CRITICAL(("Sound device does not support sample rate %d " ! 115: "(returned %d)", SOUND_SAMPLERATE, sound_speed)); ! 116: return 1; ! 117: } ! 118: } ! 119: if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &sound_info) == -1) { ! 120: LOG_CRITICAL(("Error getting output space info", strerror(errno))); ! 121: return 1; ! 122: } ! 123: LOG_NORMAL(("Total allocated fragments = %d (requested %d)", ! 124: sound_info.fragstotal, SOUND_FRAGMENTS)); ! 125: LOG_NORMAL(("Fragment size = %d (requested %d)", sound_info.fragsize, ! 126: sound_sampsperfield*4)); ! 127: LOG_NORMAL(("Bytes free in buffer = %d", sound_info.bytes)); ! 128: sound_threshold = sound_sampsperfield*4*SOUND_THRESHOLD; ! 129: LOG_NORMAL(("Theshold = %d (%d fields of sound === %dms latency)", ! 130: sound_threshold, SOUND_THRESHOLD, ! 131: (int)(1000*(float)SOUND_THRESHOLD/(float)vdp_framerate))); ! 132: if ((signed)sound_threshold >= sound_info.bytes) { ! 133: LOG_CRITICAL(("Threshold exceeds bytes free in buffer")); ! 134: return 1; ! 135: } ! 136: #ifdef JFM ! 137: if ((sound_ctx = jfm_init(0, 2612, vdp_clock/7, sound_speed, ! 138: NULL, NULL)) == NULL) ! 139: #else ! 140: if (YM2612Init(1, vdp_clock/7, sound_speed, NULL, NULL)) ! 141: #endif ! 142: return 1; ! 143: LOG_NORMAL(("YM2612 Initialised @ sample rate %d", sound_speed)); ! 144: return 0; ! 145: } ! 146: ! 147: /*** sound_final - finalise this sub-unit ***/ ! 148: ! 149: void sound_final(void) ! 150: { ! 151: #ifdef JFM ! 152: jfm_final(sound_ctx); ! 153: #else ! 154: YM2612Shutdown(); ! 155: #endif ! 156: if (sound_dev) ! 157: close(sound_dev); ! 158: } ! 159: ! 160: /*** sound_reset - reset sound sub-unit ***/ ! 161: ! 162: int sound_reset(void) ! 163: { ! 164: sound_final(); ! 165: return sound_init(); ! 166: } ! 167: ! 168: /*** sound_genreset - reset genesis sound ***/ ! 169: ! 170: void sound_genreset(void) ! 171: { ! 172: #ifdef JFM ! 173: jfm_reset(sound_ctx); ! 174: #else ! 175: YM2612ResetChip(0); ! 176: #endif ! 177: } ! 178: ! 179: /*** sound_process - process sound ***/ ! 180: ! 181: void sound_process(void) ! 182: { ! 183: static uint16 *tbuf[2]; ! 184: int s1 = (sound_sampsperfield*(vdp_line))/vdp_totlines; ! 185: int s2 = (sound_sampsperfield*(vdp_line+1))/vdp_totlines; ! 186: ! 187: tbuf[0] = soundbuf[0] + s1; ! 188: tbuf[1] = soundbuf[1] + s1; ! 189: ! 190: /* printf("YM2612: %d to %d\n", s1, s2); */ ! 191: ! 192: if (s2 > s1) ! 193: #ifdef JFM ! 194: jfm_update(sound_ctx, (void **)tbuf, s2 - s1); ! 195: #else ! 196: YM2612UpdateOne(0, (void **)tbuf, s2 -s1); ! 197: #endif ! 198: } ! 199: ! 200: /*** sound_endfield - end frame and output sound ***/ ! 201: ! 202: void sound_endfield(void) ! 203: { ! 204: unsigned int i; ! 205: uint16 buffer[(SOUND_MAXRATE/50)*2]; /* pal is slowest framerate */ ! 206: #ifdef WORDS_BIGENDIAN ! 207: int endian = 1; ! 208: #else ! 209: int endian = 0; ! 210: #endif ! 211: audio_buf_info sound_info; ! 212: unsigned int pending; ! 213: ! 214: if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &sound_info) == -1) ! 215: ui_err("Error getting output space info", strerror(errno)); ! 216: pending = (sound_info.fragstotal*sound_info.fragsize)-sound_info.bytes; ! 217: if (pending < sound_threshold) ! 218: sound_feedback = -1; ! 219: else ! 220: sound_feedback = 0; ! 221: LOG_DEBUG1(("END FIELD! 0 to %d (%d)", sound_sampsperfield, sound_feedback)); ! 222: if (sound_format == AFMT_S16_LE && endian == 0) { ! 223: /* device matches endianness of host */ ! 224: for (i = 0; i < sound_sampsperfield; i++) { ! 225: buffer[i*2] = soundbuf[0][i]; ! 226: buffer[i*2+1] = soundbuf[1][i]; ! 227: } ! 228: } else { ! 229: /* device is odd and is different to host endianness */ ! 230: for (i = 0; i < sound_sampsperfield; i++) { ! 231: buffer[i*2] = (soundbuf[0][i] >> 8) | ((soundbuf[0][i] << 8) & 0xff00); ! 232: buffer[i*2+1] = (soundbuf[1][i] >> 8) | ((soundbuf[1][i] << 8) & 0xff00); ! 233: } ! 234: } ! 235: if (write(sound_dev, buffer, sound_sampsperfield*4) == -1) { ! 236: if (errno != EINTR) ! 237: ui_err("Error writing to sound device: %s", strerror(errno)); ! 238: } ! 239: /* ! 240: if (write(sound_dump, buffer, sound_sampsperfield*4) == -1) ! 241: ui_err("Error writing to dump file: %s", strerror(errno)); ! 242: */ ! 243: } ! 244: ! 245: #ifdef JFM ! 246: ! 247: /*** sound_ym2612fetch - fetch byte from ym2612 chip ***/ ! 248: ! 249: uint8 sound_ym2612fetch(uint8 addr) ! 250: { ! 251: return jfm_read(sound_ctx, addr); ! 252: } ! 253: ! 254: /*** sound_ym2612store - store a byte to the ym2612 chip ***/ ! 255: ! 256: void sound_ym2612store(uint8 addr, uint8 data) ! 257: { ! 258: jfm_write(sound_ctx, addr, data); ! 259: } ! 260: ! 261: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.