audio.c
1 2 /* 3 * O2EM Freeware 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 * 9 * http://o2em.sourceforge.net 10 * 11 * 12 * 13 * O2 audio emulation 14 */ 15 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include "cpu.h" 21 #include "types.h" 22 #include "config.h" 23 #include "vmachine.h" 24 #include "audio.h" 25 26 //#define SAMPLE_RATE 44100 27 #define PERIOD1 11 //11 28 #define PERIOD2 44 //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 38 int sound_IRQ; 39 //static short *stream=NULL; 40 //static AUDIOSTREAM *stream=NULL; 41 //FILE *sndlog=NULL; 42 43 static double flt_a=0.0, flt_b=0.0; 44 static unsigned char flt_prv = 0; 45 46 47 static void filter(unsigned char *buf, unsigned long len); 48 49 50 //void audio_process(unsigned char *buffer){ 51 #ifdef GP32 52 void audio_process(unsigned short *buffer, int len) 53 #else 54 void audio_process(short *buffer, int len) 55 #endif 56 { 57 unsigned long aud_data; 58 #ifdef GP32 59 unsigned short s; 60 #else 61 short s; 62 #endif 63 int volume, re_circ, noise, enabled, intena, period, pnt, cnt, rndbit, pos; 64 65 aud_data = (VDCwrite[AUD_D2] | (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16)); 66 67 intena = VDCwrite[0xA0] & 0x04; 68 69 pnt = cnt = 0; 70 71 noise = VDCwrite[AUD_CTRL] & 0x10; 72 enabled = VDCwrite[AUD_CTRL] & 0x80; 73 rndbit = (enabled && noise) ? (rand()%2) : 0; 74 75 while (pnt < len/*SOUND_BUFFER_LEN*/) { 76 pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1); 77 volume = AudioVector[pos] & 0x0F; 78 enabled = AudioVector[pos] & 0x80; 79 period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2; 80 re_circ = AudioVector[pos] & 0x40; 81 82 #ifdef GP32 83 s= ( (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0) << 8; 84 #else 85 s= (( (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0) - 128) << 8 ; 86 #endif 87 *buffer++ = s; 88 *buffer++ = s; 89 pnt++; 90 cnt++; 91 92 if (cnt >= period) { 93 cnt=0; 94 aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >>= 1); 95 rndbit = (enabled && noise) ? (rand()%2) : 0; 96 97 if (enabled && intena && (!sound_IRQ)) { 98 sound_IRQ = 1; 99 ext_IRQ(); 100 } 101 } 102 } 103 104 // if (app_data.filter) filter(buffer, SOUND_BUFFER_LEN); 105 } 106 107 108 void update_audio(void) { 109 // unsigned char *p; 110 if (app_data.sound_en) { 111 // p = (unsigned char *)get_audio_stream_buffer(stream); 112 // if (p) { 113 // audio_process(p); 114 // if (sndlog) fwrite(p,1,SOUND_BUFFER_LEN,sndlog); 115 // free_audio_stream_buffer(stream); 116 // } 117 } 118 } 119 120 121 void init_audio(void) { 122 // int i; 123 124 sound_IRQ=0; 125 // set_volume(255,255); 126 init_sound_stream(); 127 128 // sndlog = NULL; 129 } 130 131 132 void init_sound_stream(void){ 133 int vol; 134 if (app_data.sound_en){ 135 if (app_data.filter) 136 vol = (255*app_data.svolume)/100; 137 else 138 vol = (255*app_data.svolume)/200; 139 // stream = play_audio_stream(SOUND_BUFFER_LEN,8,0,SAMPLE_RATE,vol,128); 140 // if (!stream) { 141 // printf("Error creating audio stream!\n"); 142 // app_data.sound_en=0; 143 // } 144 flt_a = flt_b = 0.0; 145 flt_prv = 0; 146 } 147 } 148 149 150 void mute_audio(void){ 151 if (app_data.sound_en /*&& stream*/){ 152 // stop_audio_stream(stream); 153 // stream=NULL; 154 } 155 } 156 157 158 void close_audio(void) { 159 if (app_data.sound_en /*&& stream*/) { 160 // stop_audio_stream(stream); 161 } 162 app_data.sound_en=0; 163 } 164 165 166 static void filter(unsigned char *buffer, unsigned long len){ 167 static unsigned char buf[SOUND_BUFFER_LEN]; 168 int t; 169 unsigned long i; 170 if (len>SOUND_BUFFER_LEN) return; 171 memcpy(buf,buffer,len); 172 for (i=0; i<len; i++){ 173 t = (i==0)?(buf[0]-flt_prv):(buf[i]-buf[i-1]); 174 if (t) flt_b = (double)t; 175 flt_a += flt_b/4.0 - flt_a/80.0; 176 flt_b -= flt_b/4.0; 177 if ((flt_a>255.0)||(flt_a<-255.0)) flt_a=0.0; 178 buffer[i] = (unsigned char)((flt_a+255.0)/2.0); 179 } 180 flt_prv = buf[len-1]; 181 } 182 183