/* * O2EM Freeware Odyssey2 / Videopac+ Emulator * * Created by Daniel Boris (c) 1997,1998 * * Developed by Andre de la Rocha * * http://o2em.sourceforge.net * * * * O2 audio emulation */ #include #include #include #include "cpu.h" #include "types.h" #include "config.h" #include "vmachine.h" #include "audio.h" //#define SAMPLE_RATE 44100 #define PERIOD1 11 //11 #define PERIOD2 44 //44 #define SOUND_BUFFER_LEN 1056 #define AUD_CTRL 0xAA #define AUD_D0 0xA7 #define AUD_D1 0xA8 #define AUD_D2 0xA9 int sound_IRQ; //static short *stream=NULL; //static AUDIOSTREAM *stream=NULL; //FILE *sndlog=NULL; static double flt_a=0.0, flt_b=0.0; static unsigned char flt_prv = 0; static void filter(unsigned char *buf, unsigned long len); //void audio_process(unsigned char *buffer){ #ifdef GP32 void audio_process(unsigned short *buffer, int len) #else void audio_process(short *buffer, int len) #endif { unsigned long aud_data; #ifdef GP32 unsigned short s; #else short s; #endif int volume, re_circ, noise, enabled, intena, period, pnt, cnt, rndbit, pos; aud_data = (VDCwrite[AUD_D2] | (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16)); intena = VDCwrite[0xA0] & 0x04; pnt = cnt = 0; noise = VDCwrite[AUD_CTRL] & 0x10; enabled = VDCwrite[AUD_CTRL] & 0x80; rndbit = (enabled && noise) ? (rand()%2) : 0; while (pnt < len/*SOUND_BUFFER_LEN*/) { pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1); volume = AudioVector[pos] & 0x0F; enabled = AudioVector[pos] & 0x80; period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2; re_circ = AudioVector[pos] & 0x40; #ifdef GP32 s= ( (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0) << 8; #else s= (( (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0) - 128) << 8 ; #endif *buffer++ = s; *buffer++ = s; pnt++; cnt++; if (cnt >= period) { cnt=0; aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >>= 1); rndbit = (enabled && noise) ? (rand()%2) : 0; if (enabled && intena && (!sound_IRQ)) { sound_IRQ = 1; ext_IRQ(); } } } // if (app_data.filter) filter(buffer, SOUND_BUFFER_LEN); } void update_audio(void) { // unsigned char *p; if (app_data.sound_en) { // p = (unsigned char *)get_audio_stream_buffer(stream); // if (p) { // audio_process(p); // if (sndlog) fwrite(p,1,SOUND_BUFFER_LEN,sndlog); // free_audio_stream_buffer(stream); // } } } void init_audio(void) { // int i; sound_IRQ=0; // set_volume(255,255); init_sound_stream(); // sndlog = NULL; } void init_sound_stream(void){ int vol; if (app_data.sound_en){ if (app_data.filter) vol = (255*app_data.svolume)/100; else vol = (255*app_data.svolume)/200; // stream = play_audio_stream(SOUND_BUFFER_LEN,8,0,SAMPLE_RATE,vol,128); // if (!stream) { // printf("Error creating audio stream!\n"); // app_data.sound_en=0; // } flt_a = flt_b = 0.0; flt_prv = 0; } } void mute_audio(void){ if (app_data.sound_en /*&& stream*/){ // stop_audio_stream(stream); // stream=NULL; } } void close_audio(void) { if (app_data.sound_en /*&& stream*/) { // stop_audio_stream(stream); } app_data.sound_en=0; } static void filter(unsigned char *buffer, unsigned long len){ static unsigned char buf[SOUND_BUFFER_LEN]; int t; unsigned long i; if (len>SOUND_BUFFER_LEN) return; memcpy(buf,buffer,len); for (i=0; i255.0)||(flt_a<-255.0)) flt_a=0.0; buffer[i] = (unsigned char)((flt_a+255.0)/2.0); } flt_prv = buf[len-1]; }