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