////////////////////////////////////////////////////////////////////////// // // // 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; }