|
|
1.1.1.2 ! root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */ 1.1 root 2: 3: #include <sys/types.h> 4: #include <sys/stat.h> 1.1.1.2 ! root 5: #include <sys/ioctl.h> ! 6: #include <sys/time.h> ! 7: #include <string.h> ! 8: #include <stdio.h> 1.1 root 9: #include <fcntl.h> 10: #include <errno.h> 11: #include <unistd.h> 12: #include <math.h> 13: 14: #include "generator.h" 15: #include "gensound.h" 16: #include "vdp.h" 17: #include "ui.h" 18: 19: #ifdef JFM 20: # include "jfm.h" 21: #else 22: # include "support.h" 23: # include "fm.h" 24: #endif 25: 26: #include <sys/soundcard.h> 27: 28: /*** variables externed ***/ 29: 1.1.1.2 ! root 30: int sound_feedback = 0; /* -1, running out of sound ! 31: +0, lots of sound, do something */ ! 32: int sound_debug = 0; /* 0 for no debug, 1 for debug */ ! 33: int sound_minfields = 5; /* minimum fields to try to keep buffered */ ! 34: int sound_maxfields = 10; /* max fields to buffer before blocking */ ! 35: uint8 sound_regs1[256]; ! 36: uint8 sound_regs2[256]; ! 37: uint8 sound_address1 = 0; ! 38: uint8 sound_address2 = 0; ! 39: uint8 sound_keys[8]; 1.1 root 40: 41: /* SN76489 snd_cpu; */ 42: 43: /*** forward references ***/ 44: 45: /* void snd_sndout(int chan, int freq, int vol); */ 46: 47: /*** file scoped variables ***/ 48: 49: #define SOUND_MAXRATE 44100 50: #define SOUND_FRAGMENTS 12 51: 52: static unsigned int sound_sampsperfield = 0; 1.1.1.2 ! root 53: static int sound_dev = -1; 1.1 root 54: /* static int sound_dump = 0; */ 55: static uint16 soundbuf[2][SOUND_MAXRATE/50]; /* pal is lowest framerate */ 1.1.1.2 ! root 56: static int sound_active = 0; 1.1 root 57: static int sound_format; 58: static int sound_stereo; 59: static int sound_speed; 60: static int sound_frag; 61: static int sound_fragsize; 1.1.1.2 ! root 62: static unsigned int sound_threshold; /* bytes in buffer we're trying for */ 1.1 root 63: 64: #ifdef JFM 65: static t_jfm_ctx *sound_ctx; 66: #endif 67: 68: /*** sound_init - initialise this sub-unit ***/ 69: 70: int sound_init(void) 71: { 72: audio_buf_info sound_info; 73: 1.1.1.2 ! root 74: /* The threshold parameter specifies how many fields worth of sound we ! 75: should try and keep around (a display field is 1/50th or 1/60th of a ! 76: second) - generator works by trying to keep threshold number of fields ! 77: worth of sound around, and drops plotting frames to keep up on slow ! 78: machines */ ! 79: ! 80: if (sound_active) ! 81: sound_final(); ! 82: LOG_VERBOSE(("Initialising sound...")); 1.1 root 83: sound_sampsperfield = SOUND_SAMPLERATE / vdp_framerate; 84: 85: /* sound_dump = open("/tmp/sound_dump", O_CREAT|O_WRONLY|O_TRUNC); */ 86: 87: if ((sound_dev = open(SOUND_DEVICE, O_WRONLY, 0)) == -1) { 88: LOG_CRITICAL(("open " SOUND_DEVICE " failed: %s", strerror(errno))); 89: return 1; 90: } 1.1.1.2 ! root 91: sound_frag = (sound_maxfields<<16 | 1.1 root 92: (int)(ceil(log10(sound_sampsperfield*4)/log10(2)))); 93: if (ioctl(sound_dev, SNDCTL_DSP_SETFRAGMENT, &sound_frag) == -1) { 94: LOG_CRITICAL(("Error setting fragment size: %s", strerror(errno))); 1.1.1.2 ! root 95: close(sound_dev); 1.1 root 96: return 1; 97: } 98: sound_format = AFMT_S16_LE; 99: if (ioctl(sound_dev, SNDCTL_DSP_SETFMT, &sound_format) == -1) { 100: LOG_CRITICAL(("Error setting sound device format: %s", strerror(errno))); 1.1.1.2 ! root 101: close(sound_dev); 1.1 root 102: return 1; 103: } 104: if (sound_format != AFMT_S16_LE && sound_format != AFMT_S16_BE) { 105: LOG_CRITICAL(("Sound device format not supported (must be 16 bit)")); 1.1.1.2 ! root 106: close(sound_dev); 1.1 root 107: return 1; 108: } 109: sound_stereo = 1; 110: if (ioctl(sound_dev, SNDCTL_DSP_STEREO, &sound_stereo) == -1) { 111: LOG_CRITICAL(("Error setting stereo: %s", strerror(errno))); 1.1.1.2 ! root 112: close(sound_dev); 1.1 root 113: return 1; 114: } 115: if (sound_stereo != 1) { 116: LOG_CRITICAL(("Sound device does not support stereo")); 1.1.1.2 ! root 117: close(sound_dev); 1.1 root 118: return 1; 119: } 120: sound_speed = SOUND_SAMPLERATE; 121: if (ioctl(sound_dev, SNDCTL_DSP_SPEED, &sound_speed) == -1) { 122: LOG_CRITICAL(("Error setting sound speed: %s", strerror(errno))); 1.1.1.2 ! root 123: close(sound_dev); 1.1 root 124: return 1; 125: } 126: if (sound_speed != SOUND_SAMPLERATE) { 127: if (abs(sound_speed-SOUND_SAMPLERATE) > 50) { 128: LOG_NORMAL(("Warning: Sample rate not exactly 22050")); 129: } else { 130: LOG_CRITICAL(("Sound device does not support sample rate %d " 131: "(returned %d)", SOUND_SAMPLERATE, sound_speed)); 1.1.1.2 ! root 132: close(sound_dev); 1.1 root 133: return 1; 134: } 135: } 136: if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &sound_info) == -1) { 137: LOG_CRITICAL(("Error getting output space info", strerror(errno))); 1.1.1.2 ! root 138: close(sound_dev); 1.1 root 139: return 1; 140: } 1.1.1.2 ! root 141: LOG_VERBOSE(("Total allocated fragments = %d (requested %d)", ! 142: sound_info.fragstotal, sound_maxfields)); ! 143: LOG_VERBOSE(("Fragment size = %d (requested %d)", sound_info.fragsize, ! 144: sound_sampsperfield*4)); ! 145: LOG_VERBOSE(("Bytes free in buffer = %d", sound_info.bytes)); ! 146: sound_threshold = sound_sampsperfield*4*sound_minfields; ! 147: LOG_VERBOSE(("Theshold = %d (%d fields of sound === %dms latency)", ! 148: sound_threshold, sound_minfields, ! 149: (int)(1000*(float)sound_minfields/(float)vdp_framerate))); 1.1 root 150: if ((signed)sound_threshold >= sound_info.bytes) { 151: LOG_CRITICAL(("Threshold exceeds bytes free in buffer")); 1.1.1.2 ! root 152: close(sound_dev); 1.1 root 153: return 1; 154: } 155: #ifdef JFM 156: if ((sound_ctx = jfm_init(0, 2612, vdp_clock/7, sound_speed, 1.1.1.2 ! root 157: NULL, NULL)) == NULL) { 1.1 root 158: #else 1.1.1.2 ! root 159: if (YM2612Init(1, vdp_clock/7, sound_speed, NULL, NULL)) { 1.1 root 160: #endif 1.1.1.2 ! root 161: close(sound_dev); 1.1 root 162: return 1; 1.1.1.2 ! root 163: } ! 164: LOG_VERBOSE(("YM2612 Initialised @ sample rate %d", sound_speed)); ! 165: sound_active = 1; 1.1 root 166: return 0; 167: } 168: 169: /*** sound_final - finalise this sub-unit ***/ 170: 171: void sound_final(void) 172: { 1.1.1.2 ! root 173: if (!sound_active) ! 174: return; ! 175: LOG_VERBOSE(("Finalising sound...")); 1.1 root 176: #ifdef JFM 177: jfm_final(sound_ctx); 178: #else 179: YM2612Shutdown(); 180: #endif 1.1.1.2 ! root 181: if (sound_dev != -1) 1.1 root 182: close(sound_dev); 1.1.1.2 ! root 183: sound_dev = -1; ! 184: sound_active = 0; ! 185: LOG_VERBOSE(("Finalised sound.")); 1.1 root 186: } 187: 188: /*** sound_reset - reset sound sub-unit ***/ 189: 190: int sound_reset(void) 191: { 192: sound_final(); 193: return sound_init(); 194: } 195: 196: /*** sound_genreset - reset genesis sound ***/ 197: 198: void sound_genreset(void) 199: { 200: #ifdef JFM 201: jfm_reset(sound_ctx); 202: #else 203: YM2612ResetChip(0); 204: #endif 205: } 206: 207: /*** sound_process - process sound ***/ 208: 209: void sound_process(void) 210: { 211: static uint16 *tbuf[2]; 212: int s1 = (sound_sampsperfield*(vdp_line))/vdp_totlines; 213: int s2 = (sound_sampsperfield*(vdp_line+1))/vdp_totlines; 214: 215: tbuf[0] = soundbuf[0] + s1; 216: tbuf[1] = soundbuf[1] + s1; 217: 218: /* printf("YM2612: %d to %d\n", s1, s2); */ 219: 220: if (s2 > s1) 221: #ifdef JFM 222: jfm_update(sound_ctx, (void **)tbuf, s2 - s1); 223: #else 224: YM2612UpdateOne(0, (void **)tbuf, s2 -s1); 225: #endif 226: } 227: 228: /*** sound_endfield - end frame and output sound ***/ 229: 230: void sound_endfield(void) 231: { 232: unsigned int i; 233: uint16 buffer[(SOUND_MAXRATE/50)*2]; /* pal is slowest framerate */ 234: #ifdef WORDS_BIGENDIAN 235: int endian = 1; 236: #else 237: int endian = 0; 238: #endif 239: audio_buf_info sound_info; 240: unsigned int pending; 1.1.1.2 ! root 241: struct timeval tv; 1.1 root 242: 243: if (ioctl(sound_dev, SNDCTL_DSP_GETOSPACE, &sound_info) == -1) 244: ui_err("Error getting output space info", strerror(errno)); 245: pending = (sound_info.fragstotal*sound_info.fragsize)-sound_info.bytes; 246: if (pending < sound_threshold) 247: sound_feedback = -1; 248: else 249: sound_feedback = 0; 1.1.1.2 ! root 250: if (sound_debug) { ! 251: LOG_VERBOSE(("End of field - sound card says output buffer left = %d bytes", ! 252: sound_info.bytes)); ! 253: LOG_VERBOSE(("Sound card says %d frags @ %d bytes each = %d bytes", ! 254: sound_info.fragstotal, sound_info.fragsize, ! 255: sound_info.fragstotal*sound_info.fragsize)); ! 256: LOG_VERBOSE(("Therefore, pending = %d, compare with threshold %d = %d", ! 257: pending, sound_threshold, sound_feedback)); ! 258: } 1.1 root 259: if (sound_format == AFMT_S16_LE && endian == 0) { 260: /* device matches endianness of host */ 261: for (i = 0; i < sound_sampsperfield; i++) { 262: buffer[i*2] = soundbuf[0][i]; 263: buffer[i*2+1] = soundbuf[1][i]; 264: } 265: } else { 266: /* device is odd and is different to host endianness */ 267: for (i = 0; i < sound_sampsperfield; i++) { 268: buffer[i*2] = (soundbuf[0][i] >> 8) | ((soundbuf[0][i] << 8) & 0xff00); 269: buffer[i*2+1] = (soundbuf[1][i] >> 8) | ((soundbuf[1][i] << 8) & 0xff00); 270: } 271: } 1.1.1.2 ! root 272: if (sound_debug) { ! 273: gettimeofday(&tv, NULL); ! 274: LOG_REQUEST(("%ld:%ld - before write", tv.tv_sec, tv.tv_usec)); ! 275: } 1.1 root 276: if (write(sound_dev, buffer, sound_sampsperfield*4) == -1) { 277: if (errno != EINTR) 278: ui_err("Error writing to sound device: %s", strerror(errno)); 279: } 280: /* 281: if (write(sound_dump, buffer, sound_sampsperfield*4) == -1) 282: ui_err("Error writing to dump file: %s", strerror(errno)); 283: */ 1.1.1.2 ! root 284: if (sound_debug) { ! 285: gettimeofday(&tv, NULL); ! 286: LOG_REQUEST(("%ld:%ld - after write", tv.tv_sec, tv.tv_usec)); ! 287: } 1.1 root 288: } 289: 290: /*** sound_ym2612fetch - fetch byte from ym2612 chip ***/ 291: 292: uint8 sound_ym2612fetch(uint8 addr) 293: { 1.1.1.2 ! root 294: #ifdef JFM 1.1 root 295: return jfm_read(sound_ctx, addr); 1.1.1.2 ! root 296: #else ! 297: return YM2612Read(0, addr); ! 298: #endif 1.1 root 299: } 300: 301: /*** sound_ym2612store - store a byte to the ym2612 chip ***/ 302: 303: void sound_ym2612store(uint8 addr, uint8 data) 304: { 1.1.1.2 ! root 305: switch (addr) { ! 306: case 0: ! 307: sound_address1 = data; ! 308: break; ! 309: case 1: ! 310: if (sound_address1 == 0x28 && (data & 3) != 3) ! 311: sound_keys[data & 7] = data >> 4; ! 312: if (sound_address1 == 0x2a) { ! 313: sound_keys[7] = 0; ! 314: } ! 315: if (sound_address1 == 0x2b) ! 316: sound_keys[7] = data & 0x80 ? 0xf : 0; ! 317: sound_regs1[sound_address1] = data; ! 318: break; ! 319: case 2: ! 320: sound_address2 = data; ! 321: break; ! 322: case 3: ! 323: sound_regs2[sound_address2] = data; ! 324: break; ! 325: } ! 326: #ifdef JFM 1.1 root 327: jfm_write(sound_ctx, addr, data); 1.1.1.2 ! root 328: #else ! 329: YM2612Write(0, addr, data); ! 330: #endif 1.1 root 331: } 332:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.