123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- #include <math.h>
- #include "surroundopl.h"
- CSurroundopl::CSurroundopl(Copl *a, Copl *b, bool use16bit, double opl_freq, double freq_offset)
- : use16bit(use16bit), bufsize(4096), a(a), b(b), opl_freq(opl_freq), freq_offset(freq_offset)
- {
- currType = TYPE_OPL2;
- this->lbuf = new short[this->bufsize];
- this->rbuf = new short[this->bufsize];
- };
- CSurroundopl::~CSurroundopl()
- {
- delete[] this->rbuf;
- delete[] this->lbuf;
- delete a;
- delete b;
- }
- void CSurroundopl::update(short *buf, int samples)
- {
- if (samples * 2 > this->bufsize) {
-
- delete[] this->rbuf;
- delete[] this->lbuf;
- this->bufsize = samples * 2;
- this->lbuf = new short[this->bufsize];
- this->rbuf = new short[this->bufsize];
- }
- a->update(this->lbuf, samples);
- b->update(this->rbuf, samples);
-
- for (int i = 0; i < samples; i++) {
- if (this->use16bit) {
- buf[i * 2] = this->lbuf[i];
- buf[i * 2 + 1] = this->rbuf[i];
- } else {
- ((char *)buf)[i * 2] = ((char *)this->lbuf)[i];
- ((char *)buf)[i * 2 + 1] = ((char *)this->rbuf)[i];
- }
- }
- }
- void CSurroundopl::write(int reg, int val)
- {
- a->write(reg, val);
-
- int iChannel = -1;
- int iRegister = reg;
- int iValue = val;
- if ((iRegister >> 4 == 0xA) || (iRegister >> 4 == 0xB)) iChannel = iRegister & 0x0F;
-
-
-
- this->iFMReg[iRegister] = iValue;
- if ((iChannel >= 0)) {
- unsigned char iBlock = (this->iFMReg[0xB0 + iChannel] >> 2) & 0x07;
- unsigned short iFNum = ((this->iFMReg[0xB0 + iChannel] & 0x03) << 8) | this->iFMReg[0xA0 + iChannel];
-
- double dbOriginalFreq = opl_freq * (double)iFNum * pow(2.0, iBlock - 20);
- unsigned char iNewBlock = iBlock;
- unsigned short iNewFNum;
-
-
-
- #define calcFNum() ((dbOriginalFreq + (dbOriginalFreq / freq_offset)) / (opl_freq * pow(2.0, iNewBlock - 20)))
- double dbNewFNum = calcFNum();
-
- if (dbNewFNum > 1023 - NEWBLOCK_LIMIT) {
-
- if (iNewBlock > 6) {
-
-
-
- iNewBlock = iBlock;
- iNewFNum = iFNum;
- } else {
- iNewBlock++;
- iNewFNum = (unsigned short)calcFNum();
- }
- } else if (dbNewFNum < 0 + NEWBLOCK_LIMIT) {
-
- if (iNewBlock == 0) {
-
-
-
- iNewBlock = iBlock;
- iNewFNum = iFNum;
- } else {
- iNewBlock--;
- iNewFNum = (unsigned short)calcFNum();
- }
- } else {
-
- iNewFNum = (unsigned short)dbNewFNum;
- }
-
- if (iNewFNum > 1023) {
-
-
-
- iNewBlock = iBlock;
- iNewFNum = iFNum;
- }
- if ((iRegister >= 0xB0) && (iRegister <= 0xB8)) {
-
- iValue = (iValue & ~0x1F) | (iNewBlock << 2) | ((iNewFNum >> 8) & 0x03);
- this->iCurrentTweakedBlock[iChannel] = iNewBlock;
- this->iCurrentFNum[iChannel] = (unsigned char)iNewFNum;
- if (this->iTweakedFMReg[0xA0 + iChannel] != (iNewFNum & 0xFF)) {
-
- unsigned char iAdditionalReg = 0xA0 + iChannel;
- unsigned char iAdditionalValue = iNewFNum & 0xFF;
- b->write(iAdditionalReg, iAdditionalValue);
- this->iTweakedFMReg[iAdditionalReg] = iAdditionalValue;
- }
- } else if ((iRegister >= 0xA0) && (iRegister <= 0xA8)) {
-
- iValue = iNewFNum & 0xFF;
-
- unsigned char iNewB0Value = (this->iFMReg[0xB0 + iChannel] & ~0x1F) | (iNewBlock << 2) | ((iNewFNum >> 8) & 0x03);
- if (
- (iNewB0Value & 0x20) &&
- (this->iTweakedFMReg[0xB0 + iChannel] != iNewB0Value)
- ) {
-
- unsigned char iAdditionalReg = 0xB0 + iChannel;
- b->write(iAdditionalReg, iNewB0Value);
- this->iTweakedFMReg[iAdditionalReg] = iNewB0Value;
- }
- }
- }
-
- b->write(iRegister, iValue);
- this->iTweakedFMReg[iRegister] = iValue;
- };
- void CSurroundopl::init()
- {
- a->init();
- b->init();
- }
|