📄 adpcm.c
字号:
/* bail if we're not playing anything */ if (audio_sample_rate == 0) return; /* range check the numbers */ if (num >= num_voices) {#ifdef RAINE_DEBUG fprintf(stderr,"error: ADPCM_stop() called with channel = %d, but only %d channels allocated\n", num, num_voices);#endif return; } /* update the ADPCM voice */ stream_update(voice->stream, 0); /* stop playback */ voice->playing = 0;}/********************************************************************************************** ADPCM_setvol -- change volume on an ADPCM data channel***********************************************************************************************/void ADPCM_setvol(int num, int vol){ struct ADPCMVoice *voice = &adpcm[num]; /* bail if we're not playing anything */ if (audio_sample_rate == 0) return; /* range check the numbers */ if (num >= num_voices) {#ifdef RAINE_DEBUG fprintf(stderr,"error: ADPCM_setvol() called with channel = %d, but only %d channels allocated\n", num, num_voices);#endif return; } /* update the ADPCM voice */ stream_update(voice->stream, 0); voice->volume = vol;}/********************************************************************************************** ADPCM_playing -- returns true if an ADPCM data channel is still playing***********************************************************************************************/int ADPCM_playing(int num){ struct ADPCMVoice *voice = &adpcm[num]; /* bail if we're not playing anything */ if (audio_sample_rate == 0) return 0; /* range check the numbers */ if (num >= num_voices) {#ifdef RAINE_DEBUG fprintf(stderr,"error: ADPCM_playing() called with channel = %d, but only %d channels allocated\n", num, num_voices);#endif return 0; } /* update the ADPCM voice */ stream_update(voice->stream, 0); return voice->playing;}/********************************************************************************************** * * OKIM 6295 ADPCM chip: * * Command bytes are sent: * * 1xxx xxxx = start of 2-byte command sequence, xxxxxxx is the sample number to trigger * abcd vvvv = second half of command; one of the abcd bits is set to indicate which voice * the v bits seem to be volumed * * 0abc d000 = stop playing; one or more of the abcd bits is set to indicate which voice(s) * * Status is read: * * ???? abcd = one bit per voice, set to 0 if nothing is playing, or 1 if it is active ************************************************************************************************/static int okim6295_command[MAX_OKIM6295];static int okim6295_base[MAX_OKIM6295][MAX_OKIM6295_VOICES];/********************************************************************************************** OKIM6295_sh_start -- start emulation of an OKIM6295-compatible chip***********************************************************************************************/int OKIM6295_sh_start(const struct OKIM6295interface *intf){ char stream_name[40]; int i; /* reset the ADPCM system */ num_voices = intf->num * MAX_OKIM6295_VOICES; compute_tables(); /* initialize the voices */ //memset(adpcm, 0, sizeof(adpcm)); for (i = 0; i < num_voices; i++) { int chip = i / MAX_OKIM6295_VOICES; int voice = i % MAX_OKIM6295_VOICES; /* reset the OKI-specific parameters */ okim6295_command[chip] = -1; okim6295_base[chip][voice] = 0; /* generate the name and create the stream */ sprintf(stream_name, "M6295 #%d (voice %d)", chip, voice);#ifndef __RAINE__ adpcm[i].stream = stream_init(stream_name, intf->mixing_level[chip], audio_sample_rate, i, adpcm_update);#else adpcm[i].stream = stream_init(stream_name, audio_sample_rate, 16,i, adpcm_update);#endif if (adpcm[i].stream == -1){ return 1; } /* volume setup */ stream_set_volume(adpcm[i].stream,intf->mixing_level[chip]); // don't know if mixing_level is right here... /* initialize the rest of the structure */ if (intf->region[chip]) // If we have the info... adpcm[i].base = adpcm[i].region_base = load_region[intf->region[chip]]; adpcm[i].volume = 255; adpcm[i].signal = -2; if (audio_sample_rate) adpcm[i].source_step = (UINT32)((double)intf->frequency[chip] * (double)FRAC_ONE / (double)audio_sample_rate); } /* success */ return 0;}/********************************************************************************************** OKIM6295_sh_stop -- stop emulation of an OKIM6295-compatible chip***********************************************************************************************/void OKIM6295_sh_stop(void){}/********************************************************************************************** OKIM6295_sh_update -- update emulation of an OKIM6295-compatible chip***********************************************************************************************/void OKIM6295_sh_update(void){}/********************************************************************************************** OKIM6295_set_bank_base -- set the base of the bank for a given voice on a given chip***********************************************************************************************/void OKIM6295_set_bank_base(int which, int channel, int base){ struct ADPCMVoice *voice = &adpcm[which * MAX_OKIM6295_VOICES + channel]; /* handle the all voice case */ if (channel == ALL_VOICES) { int i; for (i = 0; i < MAX_OKIM6295_VOICES; i++) OKIM6295_set_bank_base(which, i, base); return; } /* update the stream and set the new base */ stream_update(voice->stream, 0); okim6295_base[which][channel] = base;}/********************************************************************************************** OKIM6295_set_frequency -- dynamically adjusts the frequency of a given ADPCM voice***********************************************************************************************/void OKIM6295_set_frequency(int which, int channel, int frequency){ struct ADPCMVoice *voice = &adpcm[which * MAX_OKIM6295_VOICES + channel]; /* handle the all voice case */ if (channel == ALL_VOICES) { int i; for (i = 0; i < MAX_OKIM6295_VOICES; i++) OKIM6295_set_frequency(which, i, frequency); return; } /* update the stream and set the new base */ stream_update(voice->stream, 0); if (audio_sample_rate) voice->source_step = (UINT32)((double)frequency * (double)FRAC_ONE / (double)audio_sample_rate);}/********************************************************************************************** OKIM6295_status_r -- read the status port of an OKIM6295-compatible chip***********************************************************************************************/static int OKIM6295_status_r(int num){ int i, result; /* range check the numbers */ if (num >= num_voices / MAX_OKIM6295_VOICES) {#ifdef RAINE_DEBUG fprintf(stderr,"error: OKIM6295_status_r() called with chip = %d, but only %d chips allocated\n",num, num_voices / MAX_OKIM6295_VOICES);#endif return 0x0f; } /* set the bit to 1 if something is playing on a given channel */ result = 0; for (i = 0; i < MAX_OKIM6295_VOICES; i++) { struct ADPCMVoice *voice = &adpcm[num * MAX_OKIM6295_VOICES + i]; /* update the stream */ stream_update(voice->stream, 0); /* set the bit if it's playing */ if (voice->playing) result |= 1 << i; } return result;}/********************************************************************************************** OKIM6295_data_w -- write to the data port of an OKIM6295-compatible chip***********************************************************************************************/static void OKIM6295_data_w(int num, int data){ /* range check the numbers */ if (num >= num_voices / MAX_OKIM6295_VOICES) {#ifdef RAINE_DEBUG fprintf(stderr,"error: OKIM6295_data_w() called with chip = %d, but only %d chips allocated\n", num, num_voices / MAX_OKIM6295_VOICES);#endif return; } /* if a command is pending, process the second half */ if (okim6295_command[num] != -1) { int temp = data >> 4, i, start, stop; unsigned char *base; /* determine which voice(s) (voice is set by a 1 bit in the upper 4 bits of the second byte) */ for (i = 0; i < MAX_OKIM6295_VOICES; i++, temp >>= 1) if (temp & 1) { struct ADPCMVoice *voice = &adpcm[num * MAX_OKIM6295_VOICES + i]; /* update the stream */ stream_update(voice->stream, 0); /* determine the start/stop positions */ base = &voice->region_base[okim6295_base[num][i] + okim6295_command[num] * 8]; start = (base[0] << 16) + (base[1] << 8) + base[2]; stop = (base[3] << 16) + (base[4] << 8) + base[5]; /* set up the voice to play this sample */ if (start < 0x40000 && stop < 0x40000) { voice->playing = 1; voice->base = &voice->region_base[okim6295_base[num][i] + start]; voice->sample = 0; voice->count = 2 * (stop - start + 1); /* also reset the ADPCM parameters */ voice->signal = -2; voice->step = 0; voice->volume = volume_table[data & 0x0f]; } /* invalid samples go here */ else {#ifdef RAINE_DEBUG fprintf(stderr,"OKIM6295: requested to play invalid sample %02x\n",okim6295_command[num]);#endif voice->playing = 0; } } /* reset the command */ okim6295_command[num] = -1; } /* if this is the start of a command, remember the sample number for next time */ else if (data & 0x80) { okim6295_command[num] = data & 0x7f; } /* otherwise, see if this is a silence command */ else { int temp = data >> 3, i; /* determine which voice(s) (voice is set by a 1 bit in bits 3-6 of the command */ for (i = 0; i < 4; i++, temp >>= 1) if (temp & 1) { struct ADPCMVoice *voice = &adpcm[num * MAX_OKIM6295_VOICES + i]; /* update the stream, then turn it off */ stream_update(voice->stream, 0); voice->playing = 0; } }}/********************************************************************************************** OKIM6295_status_0_r -- generic status read functions OKIM6295_status_1_r***********************************************************************************************/READ_HANDLER( OKIM6295_status_0_r ){ return OKIM6295_status_r(0);}READ_HANDLER( OKIM6295_status_1_r ){ return OKIM6295_status_r(1);}/********************************************************************************************** OKIM6295_data_0_w -- generic data write functions OKIM6295_data_1_w***********************************************************************************************/WRITE_HANDLER( OKIM6295_data_0_w ){ OKIM6295_data_w(0, data);}WRITE_HANDLER( OKIM6295_data_1_w ){ OKIM6295_data_w(1, data);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -