// // Generated by dtk // Translation Unit: JASChannel.cpp // #include "JSystem/JAudio/JASChannel.h" #include "JSystem/JAudio/JASCalc.h" #include "JSystem/JAudio/JASChAllocQueue.h" #include "JSystem/JAudio/JASChGlobal.h" #include "JSystem/JAudio/JASChannelMgr.h" #include "JSystem/JAudio/JASDSPChannel.h" #include "JSystem/JAudio/JASDSPInterface.h" #include "JSystem/JAudio/JASDriverTables.h" #include "JSystem/JAudio/JASDriverIF.h" #include "JSystem/JUtility/JUTAssert.h" #include "dolphin/types.h" namespace JASystem { enum CalcSource { CALC_Sound = 0, CALC_Effect = 1, CALC_Channel = 2, }; enum CalcStyle { CALC_NONE = 0, // don't add that component CALC_ADD = 1, // simply add that component CALC_WEIGHT = 2, // add component weighted by power }; u8 Driver::calc_sw_table[27][3] = { // sound, effect, channel { CALC_NONE, CALC_NONE, CALC_NONE }, // 0, null { CALC_NONE, CALC_NONE, CALC_ADD }, // 1, add only channel { CALC_NONE, CALC_NONE, CALC_ADD }, // 2, add only channel { CALC_NONE, CALC_ADD, CALC_NONE }, // 3, add only effect { CALC_NONE, CALC_ADD, CALC_ADD }, // 4, add effect and channel { CALC_NONE, CALC_ADD, CALC_WEIGHT }, // 5, add effect, weight channel { CALC_NONE, CALC_ADD, CALC_NONE }, // 6, add only effect { CALC_NONE, CALC_WEIGHT, CALC_ADD }, // 7, weight effect, add channel { CALC_NONE, CALC_WEIGHT, CALC_WEIGHT }, // 8, weight effect and channel { CALC_ADD, CALC_NONE, CALC_NONE }, // 9, add only sound { CALC_ADD, CALC_NONE, CALC_ADD }, // 10, add sound and channel { CALC_ADD, CALC_NONE, CALC_WEIGHT }, // 11, add sound, weight channel { CALC_ADD, CALC_ADD, CALC_NONE }, // 12, add sound and effect { CALC_ADD, CALC_ADD, CALC_ADD }, // 13, add all { CALC_ADD, CALC_ADD, CALC_WEIGHT }, // 14, add sound and effect, weight channel { CALC_ADD, CALC_WEIGHT, CALC_NONE }, // 15, add sound, weight effect { CALC_ADD, CALC_WEIGHT, CALC_ADD }, // 16, add sound and channel, weight effect { CALC_ADD, CALC_WEIGHT, CALC_WEIGHT }, // 17, add sound, weight effect and channel { CALC_ADD, CALC_NONE, CALC_NONE }, // 18, add only sound { CALC_WEIGHT, CALC_NONE, CALC_ADD }, // 19, weight sound, add channel { CALC_WEIGHT, CALC_NONE, CALC_WEIGHT }, // 20, weight sound and channel { CALC_WEIGHT, CALC_ADD, CALC_NONE }, // 21, weight sound, add effect { CALC_WEIGHT, CALC_ADD, CALC_ADD }, // 22, weight sound, add effect and channel { CALC_WEIGHT, CALC_ADD, CALC_WEIGHT }, // 23, weight sound and channel, weight effect { CALC_WEIGHT, CALC_WEIGHT, CALC_NONE }, // 24, weight sound and effect { CALC_WEIGHT, CALC_WEIGHT, CALC_ADD }, // 25, weight sound and effect, add channel { CALC_WEIGHT, CALC_WEIGHT, CALC_WEIGHT }, // 26, weight all }; /* 8028B3E8-8028B5A4 .text init__Q28JASystem8TChannelFv */ void TChannel::init() { field_0x28 = NULL; field_0x2c = NULL; field_0x30 = 0; field_0x34 = 0; field_0x10 = NULL; field_0xc = 0; field_0x14 = 0; field_0x18 = 0; field_0x1c = 0; field_0xd4 = 0; if (!field_0x4) { mMixConfigs[0].mWhole = 0x150; mMixConfigs[1].mWhole = 0x210; mMixConfigs[2].mWhole = 0x352; mMixConfigs[3].mWhole = 0x412; mMixConfigs[4].mWhole = 0; mMixConfigs[5].mWhole = 0; field_0x48 = 0x10101; field_0x4c = 600; mCalcTypes[0] = CALC_WeightAll; // Pan mCalcTypes[1] = CALC_AddChannelOnly; // FxMix mCalcTypes[2] = CALC_AddChannelOnly; } else { for (int i = 0; i < 6; i++) { mMixConfigs[i].mWhole = field_0x4->field_0x4e[i]; } field_0x48 = field_0x4->field_0x68; field_0x4c = field_0x4->field_0x6c; for (int i = 0; i < 3; i++) { mCalcTypes[i] = field_0x4->mCalcTypes[i]; } } for (u32 i = 0; i < 4; i++) { JUT_ASSERT(155, osc[i]); osc[i]->setOsc(NULL); osc[i]->init(); } mPauseFlag = 0; field_0xc8++; if (s32(field_0xc8) == 0) { field_0xc8 = 1; } field_0xe8 = 0; } /* 8028B5A4-8028B620 .text setOscillator__Q28JASystem8TChannelFUlPQ28JASystem11TOscillator */ void TChannel::setOscillator(u32 oscnum, TOscillator* param_2) { JUT_ASSERT(173, oscnum < (4)); osc[oscnum] = param_2; } /* 8028B620-8028B6A8 .text setOscInit__Q28JASystem8TChannelFUlPCQ38JASystem11TOscillator4Osc_ */ void TChannel::setOscInit(u32 oscnum, const TOscillator::Osc_* param_2) { JUT_ASSERT(183, oscnum < (4)); osc[oscnum]->setOsc(param_2); osc[oscnum]->initStart(); } /* 8028B6A8-8028B73C .text forceStopOsc__Q28JASystem8TChannelFUl */ bool TChannel::forceStopOsc(u32 numosc) { JUT_ASSERT(195, numosc < (4)); return osc[numosc]->isOsc() ? osc[numosc]->forceStop() : false; } /* 8028B73C-8028B7D0 .text releaseOsc__Q28JASystem8TChannelFUl */ bool TChannel::releaseOsc(u32 numosc) { JUT_ASSERT(209, numosc < (4)); return osc[numosc]->isOsc() ? osc[numosc]->release() : false; } /* 8028B7D0-8028B850 .text directReleaseOsc__Q28JASystem8TChannelFUlUs */ void TChannel::directReleaseOsc(u32 oscnum, u16 param_2) { JUT_ASSERT(224, oscnum < (4)); osc[oscnum]->releaseDirect(param_2); } /* 8028B850-8028B8E4 .text bankOscToOfs__Q28JASystem8TChannelFUl */ f32 TChannel::bankOscToOfs(u32 oscnum) { JUT_ASSERT(234, oscnum < (4)); // Probably uses inline JASystem::TOscillator::bankOscToOfs return osc[oscnum]->isOsc() ? osc[oscnum]->getOffset() : 1.0f; } /* 8028B8E4-8028BA98 .text effectOsc__Q28JASystem8TChannelFUlf */ void TChannel::effectOsc(u32 oscnum, f32 effect) { JUT_ASSERT(246, oscnum < (4)); switch (osc[oscnum]->getOsc()->field_0x0) { case 1: field_0x94 *= effect; break; case 0: field_0x98 *= effect; break; case 2: effect -= 0.5; // Must be double literal to match mPanVec.mEffect += effect; mPanVec.mEffect = Driver::Clamp01(mPanVec.mEffect); break; case 3: mFxmixVec.mEffect += effect; mFxmixVec.mEffect = Driver::Clamp01(mFxmixVec.mEffect); break; case 4: mDolbyVec.mEffect += effect; mDolbyVec.mEffect = Driver::Clamp01(mDolbyVec.mEffect); break; } } /* 8028BA98-8028BB14 .text getOscState__Q28JASystem8TChannelCFUl */ u8 TChannel::getOscState(u32 oscnum) const { JUT_ASSERT(274, oscnum < (4)); return osc[oscnum]->mState; } /* 8028BB14-8028BB98 .text isOsc__Q28JASystem8TChannelFUl */ BOOL TChannel::isOsc(u32 oscnum) { JUT_ASSERT(284, oscnum < (4)); return osc[oscnum]->isOsc(); } /* 8028BB98-8028BC78 .text copyOsc__Q28JASystem8TChannelFUlPQ38JASystem11TOscillator4Osc_ */ void TChannel::copyOsc(u32 oscnum, TOscillator::Osc_* param_2) { JUT_ASSERT(295, oscnum < (4)); if (isOsc(oscnum)) { *param_2 = *osc[oscnum]->getOsc(); } else { OSReport("osc[%d] is NULL\n", oscnum); } } /* 8028BC78-8028BD10 .text overwriteOsc__Q28JASystem8TChannelFUlPQ38JASystem11TOscillator4Osc_ */ void TChannel::overwriteOsc(u32 oscnum, TOscillator::Osc_* param_2) { JUT_ASSERT(308, oscnum < (4)); setOscInit(oscnum, param_2); effectOsc(oscnum, bankOscToOfs(oscnum)); } /* 8028BD10-8028BDA4 .text setKeySweepTarget__Q28JASystem8TChannelFUcUl */ void TChannel::setKeySweepTarget(u8 key, u32 target) { s32 r0; if (field_0xc == 2 || field_0x10 == 0) r0 = key; else r0 = key + 0x3C - field_0x10->field_0x2; if (r0 < 0) r0 = 0; else if (r0 > 0x7F) r0 = 0x7F; f32 val = Driver::C5BASE_PITCHTABLE[r0]; val *= field_0x50; if (target == 0) { field_0x58 = val; field_0x2c = NULL; return; } field_0x9c = val; field_0xa2 = target; field_0x2c = &TChannel::extraUpdate; } /* 8028BDA4-8028BDAC .text setPauseFlag__Q28JASystem8TChannelFUc */ void TChannel::setPauseFlag(u8 param_1) { mPauseFlag = param_1; } /* 8028BDAC-8028BDBC .text setPauseFlagReq__Q28JASystem8TChannelFUc */ void TChannel::setPauseFlagReq(u8 param_1) { mPauseFlag = param_1; field_0x3 = 1; } /* 8028BDBC-8028BE64 .text setPanPower__Q28JASystem8TChannelFffff */ void TChannel::setPanPower(f32 param_1, f32 param_2, f32 param_3, f32 param_4) { f32 px = param_1 + param_2 + param_3; if (px == 0.0f) { OSReport("----- JASChannel::setPanPower : px == 0.0\n"); px = 1.0f; } mPanPower.mSound = param_1 / px; mPanPower.mEffect = param_2 / px; mPanPower.mChannel = param_3 / px; } /* 8028BE64-8028BEB8 .text checkLogicalChannel__Q28JASystem8TChannelFv */ BOOL TChannel::checkLogicalChannel() { if (!field_0x10 && field_0xc == 0) { OSReport("----- checkLC : 波形がアサインされていません\n"); return false; } return true; } /* 8028BEB8-8028BF40 .text play__Q28JASystem8TChannelFUl */ BOOL TChannel::play(u32 param_1) { if (param_1 == 0) { param_1 = -1; } field_0x30 = param_1; field_0x34 = field_0x30; field_0x28 = &updatecallLogicalChannel; field_0x20 = NULL; if (!checkLogicalChannel()) { return false; } TDSPQueue::enQueue(this); field_0x4->addListTail(this, 3); return true; } /* 8028BF40-8028BFAC .text stop__Q28JASystem8TChannelFUs */ void TChannel::stop(u16 param_1) { if (!field_0x20) { updatecallLogicalChannel(this, 6); } else if (param_1 == 0) { updatecallLogicalChannel(this, 0); } else { directReleaseOsc(0, param_1); updatecallLogicalChannel(this, 0); } } /* 8028BFAC-8028C108 .text updateJcToDSP__Q28JASystem8TChannelFv */ void TChannel::updateJcToDSP() { DSPInterface::DSPBuffer* dspBuffer = field_0x20->field_0xc; if (field_0xd4) { for (u8 i = 0; i < 6; i++) { dspBuffer->setMixerVolumeOnly(i, field_0xbc[i]); } dspBuffer->setPitch(mPitch); dspBuffer->setPauseFlag(mPauseFlag); dspBuffer->flushChannel(); } else { for (u8 i = 0; i < 6; i++) { dspBuffer->setMixerVolume(i, field_0xbc[i], field_0x4->field_0x5a[i]); } dspBuffer->setPitch(mPitch); if (field_0x4->field_0x61 & 0x20) { dspBuffer->setIIRFilterParam(field_0x4->field_0x3c); } if (field_0x4->field_0x61 & 0x1f) { dspBuffer->setFIR8FilterParam(field_0x4->field_0x2c); } dspBuffer->setFilterMode(field_0x4->field_0x61); dspBuffer->setDistFilter(field_0x4->field_0x4c); dspBuffer->setPauseFlag(mPauseFlag); field_0x20->field_0xc->flushChannel(); } } /* 8028C108-8028C140 .text forceStopLogicalChannel__Q28JASystem8TChannelFv */ bool TChannel::forceStopLogicalChannel() { if (!field_0x20) { return false; } field_0x20->forceStop(); return true; } /* 8028C140-8028C1C0 .text stopLogicalChannel__Q28JASystem8TChannelFv */ BOOL TChannel::stopLogicalChannel() { if (!field_0x20) { OSReport("----- stopLC : DSP Ch is not assigned\n"); return FALSE; } field_0x20->mCallback = NULL; field_0x20->setCBInterval(0); field_0x20->stop(); TDSPChannel::free(field_0x20, u32(this)); field_0x20 = NULL; return TRUE; } /* 8028C1C0-8028C3A8 .text playLogicalChannel__Q28JASystem8TChannelFv */ BOOL TChannel::playLogicalChannel() { if (!field_0x20) { OSReport("----- playLC DSP Ch が割当てられていません\n"); return FALSE; } if (!checkLogicalChannel()) return FALSE; field_0x20->mCallback = &TChannel::updatecallDSPChannel; field_0x20->setCBInterval(1); DSPInterface::DSPBuffer* buf = field_0x20->field_0xc; switch (field_0xc) { case 0: buf->setWaveInfo(field_0x10, field_0x14, field_0xe8); break; case 2: buf->setOscInfo(field_0x14); break; } for (u8 i = 0; i < 6; ++i) { // Something ungodly is occurring here. union { u16 asS16; struct { u8 hi; u8 lo; } asP; } s; s.asS16 = mMixConfigs[i].mWhole; u32 om = Driver::getOutputMode(); if (om == 0) { switch (s.asP.hi) { case 8: s.asP.hi = 0xB; break; case 9: s.asP.hi = 0x2; break; } } else if (om == 1) { if (s.asP.hi == 8) s.asP.hi = 0xB; } buf->setBusConnect(i, s.asP.hi); } field_0xa4 = field_0x4; for (u32 i = 0; i < 4; ++i) { if (isOsc(i)) { effectOsc(i, bankOscToOfs(i)); } } updateEffectorParam(); updateJcToDSPInit(); field_0x20->setPriority(field_0x48); field_0x20->setPriorityTime(field_0x4c); field_0x20->play(); return TRUE; } /* 8028C3A8-8028C62C .text updateEffectorParam__Q28JASystem8TChannelFv */ void TChannel::updateEffectorParam() { f32 pan; f32 fxmix; f32 dolby = 0.0f; if (field_0xa4 == field_0x4) { field_0xa8 = field_0x4->field_0x1c; field_0xac = field_0x4->field_0x18; mPanVec.mChannel = field_0x4->field_0x20; mFxmixVec.mChannel = field_0x4->field_0x24; mDolbyVec.mChannel = field_0x4->field_0x28; for (int i = 0; i < 3; i++) { mCalcTypes[i] = field_0x4->mCalcTypes[i]; } } switch (Driver::getOutputMode()) { case 0: pan = 0.5f; dolby = 0.0f; fxmix = calcEffect(&mFxmixVec, &mPanPower, mCalcTypes[1]); break; case 1: pan = (mCalcTypes[0] == CALC_None) ? 0.5f : calcPan(&mPanVec, &mPanPower, mCalcTypes[0]); fxmix = calcEffect(&mFxmixVec, &mPanPower, mCalcTypes[1]); dolby = 0.0f; break; case 2: pan = (mCalcTypes[0] == CALC_None) ? 0.5f : calcPan(&mPanVec, &mPanPower, mCalcTypes[0]); fxmix = calcEffect(&mFxmixVec, &mPanPower, mCalcTypes[1]); dolby = calcEffect(&mDolbyVec, &mPanPower, mCalcTypes[2]); break; } f32 volume = field_0xac * (field_0x5c * field_0x98); pan = Driver::Clamp01(pan); fxmix = Driver::Clamp01(fxmix); dolby = Driver::Clamp01(dolby); mPitch = 4096.0f * (field_0xa8 * (field_0x58 * field_0x94)); if (mMixConfigs[0].mWhole != 0xFFFF) { updateMixer(volume, pan, fxmix, dolby); } else { updateAutoMixer(volume, pan, fxmix, dolby); } } /* 8028C62C-8028C6C4 .text killBrokenLogicalChannels__Q28JASystem8TChannelFPQ28JASystem11TDSPChannel */ void TChannel::killBrokenLogicalChannels(TDSPChannel* dspChannel) { TChannelMgr* mgr; for (u32 i = 0; i < 256; i++) { TChannel* channel = TGlobalChannel::getChannelHandle(i); if (channel == NULL) continue; if (channel->field_0x20 != dspChannel) continue; mgr = channel->field_0x4; if (mgr == NULL) continue; channel->stopLogicalChannel(); if (!mgr->moveListHead(channel, 0)) { OSReport("----- killBrokenLogicalChannels : Cutできない\n"); } } } /* 8028C6C4-8028CABC .text updatecallDSPChannel__Q28JASystem8TChannelFPQ28JASystem11TDSPChannelUl */ int TChannel::updatecallDSPChannel(TDSPChannel* dspChannel, u32 param_2) { TChannel* channel = dspChannel->getLogicalChannel(); TChannelMgr* mgr = channel->field_0x4; u32 i; u32 r27 = 0; if (channel == NULL) { OSReport("-----Error JASDriver::commonCallbackLC DSPchのsignがNULL\n"); dspChannel->mCallback = NULL; dspChannel->mPriority = 0; killBrokenLogicalChannels(dspChannel); return 0; } if (channel->field_0x20 != dspChannel) { if (channel->field_0x20 != NULL && channel == channel->field_0x20->getLogicalChannel()) { killBrokenLogicalChannels(dspChannel); } else { channel->stopLogicalChannel(); if (!mgr->moveListHead(channel, 0)) { OSReport("----- updatecallDSPChannel : Cutできない\n"); } } dspChannel->forceDelete(); return 0; } else { if (param_2 == 2) { if (channel->field_0x28 != NULL) { channel->field_0x28(channel, 1); } else { channel->stopLogicalChannel(); if (!mgr->moveListHead(channel, 0)) { OSReport("----- updatecallDSPChannel : Cutできない\n"); } } return 0; } if (channel->field_0x10 != NULL && channel->field_0x10->field_0x24[0] == 0) { dspChannel->forceStop(); return -1; } if (param_2 == 4) { u8 priority = channel->getLifeTimePriority(); if (channel->field_0x20 != NULL) { if (priority < channel->field_0x20->getPriority()) { channel->field_0x20->setPriority(priority); } } return 0; } if (param_2 == 3) { channel->forceStopOsc(0); if (!mgr->moveListHead(channel, 3)) { OSReport("----- updatecallDSPChannel : Cutできない\n"); return 1; } param_2 = 0; } if (param_2 == 0) { channel->field_0x94 = 1.0f; channel->field_0x98 = 1.0f; channel->mPanVec.mEffect = 0.5f; channel->mFxmixVec.mEffect = 0.0f; channel->mDolbyVec.mEffect = 0.0f; for (i = 0; i < 4; i++) { if (!channel->isOsc(i)) continue; channel->effectOsc(i, channel->bankOscToOfs(i)); if (i == 0 && channel->getOscState(i) == 0) { if (channel->field_0x28 == NULL) { OSReport("----- updatecallDSPCh JC停止のためのUPDATECALLがNULL\n"); if (!channel->stopLogicalChannel()) { dspChannel->stop(); } if (!mgr->moveListHead(channel, 0)) { OSReport("----- updatecallDSPChannel : Cutできない update\n"); } return 0; } channel->field_0x28(channel, 2); return 0; } r27++; } if (r27 != 0) { channel->updateEffectorParam(); channel->field_0x3 = 1; } if (channel->field_0x2c != NULL) { if (channel->field_0x2c(channel, 0) == 1) { channel->field_0x3++; } } u8 updateInterval = Driver::getUpdateInterval(); if (channel->field_0x28 == NULL) { return updateInterval; } if (channel->field_0x34 > 0) { if (channel->field_0x34 > updateInterval) { channel->field_0x34 -= updateInterval; } else { channel->field_0x34 = 0; } } } if (channel->field_0x34 == 0) { channel->field_0x28(channel, 0); channel->field_0x34 = channel->field_0x30; } if (channel->field_0x3 != 0) { channel->updateJcToDSP(); channel->field_0x3 = 0; } return Driver::getUpdateInterval(); } dspChannel->forceDelete(); } /* 8028CABC-8028CB88 .text calcEffect__Q28JASystem8TChannelFPCQ38JASystem6Driver10PanMatrix_PCQ38JASystem6Driver10PanMatrix_Uc */ f32 TChannel::calcEffect(const Driver::PanMatrix_* params, const Driver::PanMatrix_* power, u8 calcType) { f32 value = 0.0f; const u8* calcTypes = Driver::calc_sw_table[calcType]; switch (calcTypes[CALC_Sound]) { case CALC_NONE: break; case CALC_ADD: value += params->mSound; break; case CALC_WEIGHT: value += params->mSound * power->mSound; break; } switch (calcTypes[CALC_Effect]) { case CALC_NONE: break; case CALC_ADD: value += params->mEffect; break; case CALC_WEIGHT: value += params->mEffect * power->mEffect; break; } switch (calcTypes[CALC_Channel]) { case CALC_NONE: break; case CALC_ADD: value += params->mChannel; break; case CALC_WEIGHT: value += params->mChannel * power->mChannel; break; } return value; } /* 8028CB88-8028CC90 .text calcPan__Q28JASystem8TChannelFPCQ38JASystem6Driver10PanMatrix_PCQ38JASystem6Driver10PanMatrix_Uc */ f32 TChannel::calcPan(const Driver::PanMatrix_* params, const Driver::PanMatrix_* power, u8 calcType) { f32 value = 0.0f; const u8* calcTypes = Driver::calc_sw_table[calcType]; switch (calcTypes[CALC_Sound]) { case CALC_NONE: break; case CALC_ADD: value += (params->mSound - 0.5f); break; case CALC_WEIGHT: value += (params->mSound - 0.5f) * power->mSound; break; } switch (calcTypes[CALC_Effect]) { case CALC_NONE: break; case CALC_ADD: value += (params->mEffect - 0.5f); break; case CALC_WEIGHT: value += (params->mEffect - 0.5f) * power->mEffect; break; } switch (calcTypes[CALC_Channel]) { case CALC_NONE: break; case CALC_ADD: value += (params->mChannel - 0.5f); break; case CALC_WEIGHT: value += (params->mChannel - 0.5f) * power->mChannel; break; } value += 0.5f; return value; } /* 8028CC90-8028CD90 .text updateJcToDSPInit__Q28JASystem8TChannelFv */ void TChannel::updateJcToDSPInit() { DSPInterface::DSPBuffer* buf = field_0x20->field_0xc; if (mMixConfigs[0].mWhole == 0xFFFF) { field_0x20->field_0xc->initAutoMixer(); } else { buf->setMixerInitDelayMax(field_0x4->field_0x60); for (u8 i = 0; i < 6; ++i) buf->setMixerInitVolume(i, field_0xbc[i], field_0x4->field_0x5a[i]); } buf->setPitch(mPitch); if (field_0x4->field_0x61 & 0x20) buf->setIIRFilterParam(field_0x4->field_0x3c); if (field_0x4->field_0x61 & 0x1F) buf->setFIR8FilterParam(field_0x4->field_0x2c); buf->setFilterMode(field_0x4->field_0x61); buf->setPauseFlag(mPauseFlag); } /* 8028CD90-8028CEA8 .text updateAutoMixer__Q28JASystem8TChannelFffff */ void TChannel::updateAutoMixer(f32 volume, f32 pan, f32 fxmix, f32 dolby) { field_0x20->field_0xc->setAutoMixer( Driver::Clamp01(volume) * Driver::getAutoLevel(), pan * 127.5f, dolby * 127.5f, fxmix * 127.5f, mMixConfigs[1].mWhole ); } /* 8028CEA8-8028D128 .text updateMixer__Q28JASystem8TChannelFffff */ void TChannel::updateMixer(f32 volume, f32 pan, f32 fxmix, f32 dolby) { for (u32 i = 0; i < 6; i++) { f32 vol = volume; MixConfig config = mMixConfigs[i]; if (config.mParts.u == 0) { field_0xbc[i] = 0; } else { f32 scale; if (config.mParts.l0 != 0) { switch (config.mParts.l0) { case 1: scale = pan; break; case 2: scale = fxmix; break; case 3: scale = dolby; break; case 5: scale = 1.0f - pan; break; case 6: scale = 1.0f - fxmix; break; case 7: scale = 1.0f - dolby; break; } vol *= Calc::sinfT(scale); } if (config.mParts.l1 != 0) { switch (config.mParts.l1) { case 1: scale = pan; break; case 2: scale = fxmix; break; case 3: scale = dolby; break; case 5: scale = 1.0f - pan; break; case 6: scale = 1.0f - fxmix; break; case 7: scale = 1.0f - dolby; break; } switch (config.mParts.l1) { case 3: case 7: vol *= Calc::sinfDolby2(scale); break; default: vol *= Calc::sinfT(scale); break; } } field_0xbc[i] = Driver::Clamp01(vol) * Driver::getChannelLevel(); } } } /* 8028D128-8028D218 .text extraUpdate__Q28JASystem8TChannelFPQ28JASystem8TChannelUl */ u32 TChannel::extraUpdate(TChannel* channel, u32) { if (channel->field_0xa2 != 0) { f32 f31 = channel->field_0x9c - channel->field_0x58; u8 updateInterval = Driver::getUpdateInterval(); if (channel->field_0xa2 <= updateInterval) { channel->field_0xa2 = 1; } f31 /= channel->field_0xa2; channel->field_0x58 += f31 * updateInterval; if ((channel->field_0xa2 - updateInterval) <= 0) { channel->field_0xa2 = 0; } else { channel->field_0xa2 -= updateInterval; } if (channel->field_0xa2 == 0) { channel->field_0x2c = NULL; } return 1; } else { return 0; } } /* 8028D218-8028D3C0 .text updatecallLogicalChannel__Q28JASystem8TChannelFPQ28JASystem8TChannelUl */ BOOL TChannel::updatecallLogicalChannel(TChannel* channel, u32 param) { TChannelMgr* mgr = channel->field_0x4; if (param == 0) { for (u32 i = 0; i < 4; ++i) channel->releaseOsc(i); if (channel->field_0x20) channel->field_0x20->mPriority = channel->getReleasePriority(); if (!mgr->moveListTail(channel, 2)) { OSReport("----- updatecallLC : CUT失敗(release)\n"); } channel->field_0x30 = -1; return FALSE; } else if (param == 1 || param == 2 || param == 6) { if (mgr->field_0x4 != 0) { if (mgr->cutList(channel) == -1) { OSReport("----- updatecallLC : CUT失敗(extra)\n"); } else { --mgr->field_0x4; if (u32 thing = channel->field_0xcc) { channel->field_0xcc = 0; mgr->checkLimitStop(channel, thing); } TGlobalChannel::release(channel); } } else { int r29 = channel->field_0xcc; if (!mgr->moveListHead(channel, 0)) { OSReport("----- updatecallLC : CUT失敗(not extra)\n"); } mgr->checkLimitStop(channel, r29); } if (param != 6) channel->stopLogicalChannel(); else TDSPQueue::deleteQueue(channel); channel->field_0x1 = 0xFF; channel->field_0x30 = 0xFFFFFFFF; channel->field_0x28 = NULL; } return FALSE; } }; // namespace JASystem