MCUME/MCUME_teensy41/teensyo2em/audio.c

184 wiersze
3.9 KiB
C

/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* O2 audio emulation
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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; i<len; i++){
t = (i==0)?(buf[0]-flt_prv):(buf[i]-buf[i-1]);
if (t) flt_b = (double)t;
flt_a += flt_b/4.0 - flt_a/80.0;
flt_b -= flt_b/4.0;
if ((flt_a>255.0)||(flt_a<-255.0)) flt_a=0.0;
buffer[i] = (unsigned char)((flt_a+255.0)/2.0);
}
flt_prv = buf[len-1];
}