1 2 /* 3 * O2EM Free Odyssey2 / Videopac+ Emulator 4 * 5 * Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998 6 * 7 * Developed by Andre de la Rocha <adlroc@users.sourceforge.net> 8 * Arlindo M. de Oliveira <dgtec@users.sourceforge.net> 9 * 10 * http://o2em.sourceforge.net 11 * 12 * 13 * 14 * O2 audio emulation 15 */ 16 17 18 #include <stdint.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include "cpu.h" 22 #include "config.h" 23 #include "vmachine.h" 24 #include "audio.h" 25 26 #define SAMPLE_RATE 44100 27 #define PERIOD1 11 28 #define PERIOD2 44 29 30 #define SOUND_BUFFER_LEN 1056 31 32 #define AUD_CTRL 0xAA 33 #define AUD_D0 0xA7 34 #define AUD_D1 0xA8 35 #define AUD_D2 0xA9 36 37 extern int SND; 38 extern uint8_t soundBuffer[SOUND_BUFFER_LEN]; 39 40 int sound_IRQ; 41 42 static double flt_a=0.0, flt_b=0.0; 43 static unsigned char flt_prv = 0; 44 45 filter(unsigned char * buffer,unsigned long len)46static void filter(unsigned char *buffer, unsigned long len) 47 { 48 static unsigned char buf[SOUND_BUFFER_LEN]; 49 unsigned long i; 50 if (len>SOUND_BUFFER_LEN) 51 return; 52 53 memcpy(buf,buffer,len); 54 55 for (i=0; i<len; i++) 56 { 57 int t = (i==0)?(buf[0]-flt_prv):(buf[i]-buf[i-1]); 58 if (t) flt_b = (double)t; 59 flt_a += flt_b/4.0 - flt_a/80.0; 60 flt_b -= flt_b/4.0; 61 if ((flt_a>255.0)||(flt_a<-255.0)) 62 flt_a=0.0; 63 buffer[i] = (unsigned char)((flt_a+255.0)/2.0); 64 } 65 flt_prv = buf[len-1]; 66 } 67 audio_process(unsigned char * buffer)68void audio_process(unsigned char *buffer) 69 { 70 unsigned long aud_data = (VDCwrite[AUD_D2] | 71 (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16)); 72 73 int intena = VDCwrite[0xA0] & 0x04; 74 int pnt = 0; 75 int cnt = 0; 76 77 int noise = VDCwrite[AUD_CTRL] & 0x10; 78 int enabled = VDCwrite[AUD_CTRL] & 0x80; 79 int rndbit = (enabled && noise) ? (rand()%2) : 0; 80 81 while (pnt < SOUND_BUFFER_LEN) 82 { 83 int period, re_circ; 84 85 int pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1); 86 int volume = AudioVector[pos] & 0x0F; 87 enabled = AudioVector[pos] & 0x80; 88 period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2; 89 re_circ = AudioVector[pos] & 0x40; 90 91 buffer[pnt++] = (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0; 92 cnt++; 93 94 if (cnt >= period) 95 { 96 cnt=0; 97 aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >> 1); 98 rndbit = (enabled && noise) ? (rand()%2) : 0; 99 100 if (enabled && intena && (!sound_IRQ)) 101 { 102 sound_IRQ = 1; 103 ext_IRQ(); 104 } 105 } 106 } 107 108 if (app_data.filter) 109 filter(buffer, SOUND_BUFFER_LEN); 110 } 111 112 113 update_audio(void)114void update_audio(void) 115 { 116 audio_process(soundBuffer); 117 } 118 119 init_audio(void)120void init_audio(void) 121 { 122 sound_IRQ=0; 123 if ((app_data.sound_en) || (app_data.voice)) 124 init_sound_stream(); 125 } 126 127 init_sound_stream(void)128void init_sound_stream(void) 129 { 130 #if 0 131 int vol; 132 #endif 133 if (app_data.sound_en) 134 { 135 #if 0 136 if (app_data.filter) 137 vol = (255*app_data.svolume)/100; 138 else 139 vol = (255*app_data.svolume)/200; 140 #endif 141 flt_a = flt_b = 0.0; 142 flt_prv = 0; 143 } 144 } 145 146 mute_audio(void)147void mute_audio(void) 148 { 149 SND=0; 150 } 151 close_audio(void)152void close_audio(void) 153 { 154 app_data.sound_en=0; 155 } 156 157 158