?? streams.c
字號:
#ifdef __RAINE__#include "sasound.h"#else#include "driver.h"#endif#include <math.h>#include "newmem.h"#include "ingame.h"int SampleVol[MAX_STREAM_CHANNELS];static int SamplePan[MAX_STREAM_CHANNELS];static UINT8 init_timer[MAX_STREAM_CHANNELS];static int stream_joined_channels[MAX_STREAM_CHANNELS];static char stream_name[MAX_STREAM_CHANNELS][40];static void *stream_buffer[MAX_STREAM_CHANNELS];static UINT8 counter[MAX_STREAM_CHANNELS]; static int stream_buffer_len[MAX_STREAM_CHANNELS];static int remaining_cycles[MAX_STREAM_CHANNELS];static int base_len; // base length of sample for 1 framestatic int stream_sample_rate[MAX_STREAM_CHANNELS];static int stream_sample_bits[MAX_STREAM_CHANNELS];static int stream_buffer_pos[MAX_STREAM_CHANNELS];static int stream_sample_length[MAX_STREAM_CHANNELS]; /* in usec */static int stream_param[MAX_STREAM_CHANNELS];static void (*stream_callback[MAX_STREAM_CHANNELS])(int param,INT16 *buffer,int length);static void (*stream_callback_multi[MAX_STREAM_CHANNELS])(int param,INT16 **buffer,int length);int (*cpupos)(int len)=NULL;static int memory[MAX_STREAM_CHANNELS];static int r1[MAX_STREAM_CHANNELS];static int r2[MAX_STREAM_CHANNELS];static int r3[MAX_STREAM_CHANNELS];static int c[MAX_STREAM_CHANNELS];void streams_init_timers() { int n; // When the emulations pauses, streams are not restarted !!! // So I need this... for (n=0; n<MAX_STREAM_CHANNELS; n++){ init_timer[n] = 0; remaining_cycles[n] = 0; }}/*signal >--R1--+--R2--+ | | C R3---> amp | | GND GND*//* R1, R2, R3 in Ohm; C in pF *//* set C = 0 to disable the filter */void set_RC_filter(int channel,int R1,int R2,int R3,int C){ r1[channel] = R1; r2[channel] = R2; r3[channel] = R3; c[channel] = C;}void apply_RC_filter_8(int channel,signed char *buf,int len,int sample_rate){ float R1,R2,R3,C; float Req; int K; int i; if (c[channel] == 0) return; /* filter disabled */ R1 = r1[channel]; R2 = r2[channel]; R3 = r3[channel]; C = (float)c[channel] * 1E-12; /* convert pF to F */ /* Cut Frequency = 1/(2*Pi*Req*C) */ Req = (R1*(R2+R3))/(R1+R2+R3); K = 0x10000 * exp(-1 / (Req * C) / sample_rate); buf[0] = buf[0] + (memory[channel] - buf[0]) * K / 0x10000; for (i = 1;i < len;i++) buf[i] = buf[i] + (buf[i-1] - buf[i]) * K / 0x10000; memory[channel] = buf[len-1];}void apply_RC_filter_16(int channel,signed short *buf,int len,int sample_rate){ float R1,R2,R3,C; float Req; int K; int i; if (c[channel] == 0) return; /* filter disabled */ R1 = r1[channel]; R2 = r2[channel]; R3 = r3[channel]; C = (float)c[channel] * 1E-12; /* convert pF to F */ /* Cut Frequency = 1/(2*Pi*Req*C) */ Req = (R1*(R2+R3))/(R1+R2+R3); K = 0x10000 * exp(-1 / (Req * C) / sample_rate); buf[0] = buf[0] + (memory[channel] - buf[0]) * K / 0x10000; for (i = 1;i < len;i++) buf[i] = buf[i] + (buf[i-1] - buf[i]) * K / 0x10000; memory[channel] = buf[len-1];}void apply_volume_16( INT16 *buf, UINT32 len, int vol ){ // Normally, now that we have the same values as osd functions, // we should be abble to simply make a voice_set_volume here... // I keep this for the end ! if(vol != VOLUME_MAX){ // Add [J3d!]: Small speedup if( vol != VOLUME_MIN){ // Add [J3d!]: Another speedup if(len){ do{ *buf = (INT16)((((INT32)*buf) * vol)>>8); buf++; }while(--len); } } else{ memset(buf,0x00,len<<1); } }}void apply_volume_8( INT8 *buf, UINT32 len, int vol ){ if(vol != VOLUME_MAX){ // Add [J3d!]: Small speedup if( vol != VOLUME_MIN){ // Add [J3d!]: Another speedup if(len){ do{ *buf = (INT8)((((INT32)*buf) * vol)>>8); buf++; }while(--len); } } else{ memset(buf,0x00,len); } }}int streams_sh_start(void){ int i; for (i = 0;i < MAX_STREAM_CHANNELS;i++) { stream_joined_channels[i] = 1; stream_buffer[i] = 0; } return 0;}void streams_sh_stop(void){ int i; for (i = 0;i < MAX_STREAM_CHANNELS;i++) { if(stream_buffer[i]) FreeMem(stream_buffer[i]); stream_buffer[i] = 0; }}void streams_sh_update(void){ int channel,i;#ifndef __RAINE__ if (Machine->sample_rate == 0) return;#endif /* update all the output buffers */ for (channel = 0;channel < MAX_STREAM_CHANNELS;channel += stream_joined_channels[channel]){ if (stream_buffer[channel]){ int newpos; int buflen; newpos = stream_buffer_len[channel]; buflen = newpos - stream_buffer_pos[channel]; if (stream_joined_channels[channel] > 1){ INT16 *buf[MAX_STREAM_CHANNELS]; if (buflen > 0){#ifdef USE_8BITS if (stream_sample_bits[channel] == 16){#endif for (i = 0;i < stream_joined_channels[channel];i++) buf[i] = &((short *)stream_buffer[channel+i])[stream_buffer_pos[channel+i]];#ifdef USE_8BITS } else { for (i = 0;i < stream_joined_channels[channel];i++) buf[i] = &((char *)stream_buffer[channel+i])[stream_buffer_pos[channel+i]]; }#endif (*stream_callback_multi[channel])(stream_param[channel],buf,buflen); } for (i = 0;i < stream_joined_channels[channel];i++) stream_buffer_pos[channel+i] = 0; #if SOFT_VOL // In hardware mode, no mixing is necessary : // volume & pan are set at the begining and that's all ! if (stream_sample_bits[channel] == 16){ for (i = 0;i < stream_joined_channels[channel];i++)#ifndef __RAINE__ apply_RC_filter_16(channel+i,stream_buffer[channel+i],stream_buffer_len[channel+i],stream_sample_rate[channel+i]);#else apply_volume_16( stream_buffer[channel+i], stream_buffer_len[channel+i], SampleVol[channel+i] );#endif } else { for (i = 0;i < stream_joined_channels[channel];i++)#ifndef __RAINE__ apply_RC_filter_8(channel+i,stream_buffer[channel+i],stream_buffer_len[channel+i],stream_sample_rate[channel+i]);#else apply_volume_8( stream_buffer[channel+i], stream_buffer_len[channel+i], SampleVol[channel+i] );#endif }#endif // SOFT_VOL } else { // stream_joinded_channels if (buflen > 0){ void *buf; if (stream_sample_bits[channel] == 16) buf = &((short *)stream_buffer[channel])[stream_buffer_pos[channel]]; else buf = &((char *)stream_buffer[channel])[stream_buffer_pos[channel]]; (*stream_callback[channel])(stream_param[channel],buf,buflen); } stream_buffer_pos[channel] = 0;#if SOFT_VOL if (stream_sample_bits[channel] == 16)#ifndef __RAINE__ apply_RC_filter_16(channel,stream_buffer[channel],stream_buffer_len[channel],stream_sample_rate[channel]);#else apply_volume_16( stream_buffer[channel], stream_buffer_len[channel], SampleVol[channel] );#endif else#ifndef __RAINE__ apply_RC_filter_8(channel,stream_buffer[channel],stream_buffer_len[channel],stream_sample_rate[channel]);#else apply_volume_8( stream_buffer[channel], stream_buffer_len[channel], SampleVol[channel] );#endif#endif } } } for (channel = 0;channel < MAX_STREAM_CHANNELS;channel += stream_joined_channels[channel]){ if (stream_buffer[channel]){#ifdef USE_8BITS if (stream_sample_bits[channel] == 16){#endif for (i = 0;i < stream_joined_channels[channel];i++) osd_play_streamed_sample_16(channel+i,stream_buffer[channel+i], 2*stream_buffer_len[channel+i], stream_sample_rate[channel+i], 255, 128 );#ifdef USE_8BITS } else { for (i = 0;i < stream_joined_channels[channel];i++) osd_play_streamed_sample(channel+i,stream_buffer[channel+i], stream_buffer_len[channel+i], stream_sample_rate[channel+i], 255, 128 ); }#endif } }}int stream_init(const char *name,int sample_rate,int sample_bits, int param,void (*callback)(int param,INT16 *buffer,int length)){ int channel; channel = get_play_channels(1); stream_joined_channels[channel] = 1; strcpy(stream_name[channel],name);#ifndef __RAINE__ stream_buffer_len[channel] = sample_rate / Machine->drv->frames_per_second; /* adjust sample rate to make it a multiple of buffer_len */ sample_rate = stream_buffer_len[channel] * Machine->drv->frames_per_second;#else stream_buffer_len[channel] = audio_sample_rate / CPU_FPS; base_len = audio_sample_rate / CPU_FPS; // Needs +1 to adjust more precisely to what the result should be !!! /* adjust sample rate to make it a multiple of buffer_len */ sample_rate = stream_buffer_len[channel] * CPU_FPS;#endif if ((stream_buffer[channel] = AllocateMem((sample_bits/8)*stream_buffer_len[channel])) == 0) return -1; stream_sample_rate[channel] = sample_rate; stream_sample_bits[channel] = sample_bits; stream_buffer_pos[channel] = 0; if (sample_rate) stream_sample_length[channel] = 1000000 / sample_rate; else stream_sample_length[channel] = 0; stream_param[channel] = param; stream_callback[channel] = callback; init_timer[channel] = 0; return channel;}int stream_init_multi(int channels,const char **name,int sample_rate,int sample_bits, int param,void (*callback)(int param,INT16 **buffer,int length)){ int channel,i; channel = get_play_channels(channels); stream_joined_channels[channel] = channels; for (i = 0;i < channels;i++) { strcpy(stream_name[channel+i],name[i]);#ifndef __RAINE__ stream_buffer_len[channel+i] = sample_rate / Machine->drv->frames_per_second; /* adjust sample rate to make it a multiple of buffer_len */ sample_rate = stream_buffer_len[channel+i] * Machine->drv->frames_per_second;#else stream_buffer_len[channel+i] = audio_sample_rate / CPU_FPS; base_len = audio_sample_rate / CPU_FPS; /* adjust sample rate to make it a multiple of buffer_len */ sample_rate = stream_buffer_len[channel+i] * CPU_FPS;#endif if ((stream_buffer[channel+i] = AllocateMem((sample_bits/8)*stream_buffer_len[channel+i])) == 0) return -1; memset(stream_buffer[channel+i],0,(sample_bits/8)*stream_buffer_len[channel+i]); stream_sample_rate[channel+i] = sample_rate; stream_sample_bits[channel+i] = sample_bits; stream_buffer_pos[channel+i] = 0; if (sample_rate) stream_sample_length[channel+i] = 1000000 / sample_rate; else stream_sample_length[channel+i] = 0; init_timer[channel+i] = 0; } stream_param[channel] = param; stream_callback_multi[channel] = callback; return channel;}int stream_initm(const char *name,int mixing_level,int sample_rate, int param,void (*callback)(int param,INT16 *buffer,int length)){ int stream = stream_init(name,sample_rate,16,param,callback); stream_set_volume(stream,mixing_level & 0xff); stream_set_pan(stream,mixing_level >> 8); return stream;}int stream_init_multim(int channels,const char **name,int *mixing_level,int sample_rate, int param,void (*callback)(int param,INT16 **buffer,int length)){ int i,stream = stream_init_multi(channels,name,sample_rate,16,param,callback); for (i=0; i<channels; i++){ stream_set_volume(stream+i,mixing_level[i] & 0xff); stream_set_pan(stream+i,mixing_level[i] >> 8); } return stream;} /* min_interval is in usec */void stream_update(int channel,int min_interval){#ifndef __RAINE_ORG__ // int newpos; int buflen; //if (stream_buffer[channel] == 0) // return; buflen=0; /* get current position based on the timer */ if (cpupos) buflen=cpupos(stream_sample_length[channel]); if (buflen > 0 && buflen+stream_buffer_pos[channel] < stream_buffer_len[channel]) { //newpos = sound_scalebufferpos(stream_buffer_len[channel]); // buflen = newpos - stream_buffer_pos[channel]; if (stream_joined_channels[channel] > 1) { INT16 *buf[MAX_STREAM_CHANNELS]; int i; if (stream_sample_bits[channel] == 16) { for (i = 0;i < stream_joined_channels[channel];i++) buf[i] = &((short *)stream_buffer[channel+i])[stream_buffer_pos[channel+i]]; } else { for (i = 0;i < stream_joined_channels[channel];i++) buf[i] = (UINT16*)&((char *)stream_buffer[channel+i])[stream_buffer_pos[channel+i]]; } //osd_profiler(OSD_PROFILE_SOUND); (*stream_callback_multi[channel])(stream_param[channel],buf,buflen); //osd_profiler(OSD_PROFILE_END); for (i = 0;i < stream_joined_channels[channel];i++) stream_buffer_pos[channel+i] += buflen; } else { void *buf; if (stream_sample_bits[channel] == 16) buf = &((short *)stream_buffer[channel])[stream_buffer_pos[channel]]; else buf = &((char *)stream_buffer[channel])[stream_buffer_pos[channel]]; //osd_profiler(OSD_PROFILE_SOUND); (*stream_callback[channel])(stream_param[channel],buf,buflen); //osd_profiler(OSD_PROFILE_END); stream_buffer_pos[channel] += buflen; } }#endif}void stream_set_volume(int channel,int volume){ /* My goal is now to have the same volume/pan values for streams and for osd low level functions... */ SampleVol[channel] = volume & 0xff; saSetVolume(channel,volume);}int stream_get_volume(int channel){ return SampleVol[channel];}void stream_set_pan(int channel,int pan){ SamplePan[channel] = pan & 0xff;}int stream_get_pan(int channel){ return SamplePan[channel];}const char *stream_get_name(int channel){ if (stream_buffer[channel]) return stream_name[channel]; else return 0; /* unused channel */}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -