Annotation of generator/src/gensound.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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