Annotation of generator/src/gensound.c, revision 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.