AxibugEmuOnline/References/VirtuaNESex_src_191105/NES/ApuEX/APU_VRC7.cpp
2024-08-05 17:58:53 +08:00

86 lines
2.0 KiB
C++

//////////////////////////////////////////////////////////////////////////
// //
// Konami VRC7 //
// Norix //
// written 2001/09/18 //
// last modify ----/--/-- //
//////////////////////////////////////////////////////////////////////////
#include "APU_VRC7.h"
APU_VRC7::APU_VRC7()
{
OPLL_init( 3579545, (uint32)22050 ); // 仮のサンプリングレート
VRC7_OPLL = OPLL_new();
if( VRC7_OPLL ) {
OPLL_reset( VRC7_OPLL );
OPLL_reset_patch( VRC7_OPLL, OPLL_VRC7_TONE );
VRC7_OPLL->masterVolume = 128;
}
// 仮設定
Reset( APU_CLOCK, 22050 );
}
APU_VRC7::~APU_VRC7()
{
if( VRC7_OPLL ) {
OPLL_delete( VRC7_OPLL );
VRC7_OPLL = NULL;
// OPLL_close(); // 無くても良い(中身無し)
}
}
void APU_VRC7::Reset( FLOAT fClock, INT nRate )
{
if( VRC7_OPLL ) {
OPLL_reset( VRC7_OPLL );
OPLL_reset_patch( VRC7_OPLL, OPLL_VRC7_TONE );
VRC7_OPLL->masterVolume = 128;
}
address = 0;
Setup( fClock, nRate );
}
void APU_VRC7::Setup( FLOAT fClock, INT nRate )
{
OPLL_setClock( (uint32)(fClock*2.0f), (uint32)nRate );
}
void APU_VRC7::Write( WORD addr, BYTE data )
{
if( VRC7_OPLL ) {
if( addr == 0x9010 ) {
address = data;
} else if( addr == 0x9030 ) {
OPLL_writeReg( VRC7_OPLL, address, data );
}
}
}
INT APU_VRC7::Process( INT channel )
{
if( VRC7_OPLL )
return OPLL_calc( VRC7_OPLL );
return 0;
}
INT APU_VRC7::GetFreq( INT channel )
{
if( VRC7_OPLL && channel < 8 ) {
INT fno = (((INT)VRC7_OPLL->reg[0x20+channel]&0x01)<<8)
+ (INT)VRC7_OPLL->reg[0x10+channel];
INT blk = (VRC7_OPLL->reg[0x20+channel]>>1) & 0x07;
float blkmul[] = { 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f };
if( VRC7_OPLL->reg[0x20+channel] & 0x10 ) {
return (INT)((256.0*(double)fno*blkmul[blk]) / ((double)(1<<18)/(3579545.0/72.0)));
}
}
return 0;
}