// --------------------------------------------------------------------------- // 合成 // in: buffer 合成先 // nsamples 合成サンプル数 // public void Mix(int[] buffer, int nsamples) { fm6[0].Mix(buffer, nsamples, regtc); fm6[1].Mix(buffer, nsamples, regtc); psg2[0].Mix(buffer, nsamples); psg2[1].Mix(buffer, nsamples); psg2[2].Mix(buffer, nsamples); psg2[3].Mix(buffer, nsamples); adpcmb[0].Mix(buffer, nsamples); adpcmb[1].Mix(buffer, nsamples); adpcmb[2].Mix(buffer, nsamples); RhythmMix(buffer, nsamples); adpcma.Mix(buffer, (uint)nsamples); ep3band.Mix(buffer, nsamples); compressor.Mix(buffer, nsamples); }
protected void MixSubS(int activech, int[] dest, int[] buf) { int v; int L, R; if ((activech & 0x001) != 0) { v = ch[0].Calc(); L = v; R = v; distortion.Mix(efcStartCh + 0, ref L, ref R); chorus.Mix(efcStartCh + 0, ref L, ref R); hpflpf.Mix(efcStartCh + 0, ref L, ref R); compressor.Mix(efcStartCh + 0, ref L, ref R); buf[0] = (int)((dest[0] >> 1) * L * panL[0]) * reversePhase.FM[num][0][0]; buf[1] = (int)((dest[0] & 0x1) * R * panR[0]) * reversePhase.FM[num][0][1]; buf[2] = (int)(buf[0] * reverb.SendLevel[efcStartCh + 0]); buf[3] = (int)(buf[1] * reverb.SendLevel[efcStartCh + 0]); } if ((activech & 0x004) != 0) { v = ch[1].Calc(); L = v; R = v; distortion.Mix(efcStartCh + 1, ref L, ref R); chorus.Mix(efcStartCh + 1, ref L, ref R); hpflpf.Mix(efcStartCh + 1, ref L, ref R); compressor.Mix(efcStartCh + 1, ref L, ref R); L = (int)((dest[1] >> 1) * L * panL[1]) * reversePhase.FM[num][1][0]; R = (int)((dest[1] & 0x1) * R * panR[1]) * reversePhase.FM[num][1][1]; buf[0] += L; buf[1] += R; buf[2] += (int)(L * reverb.SendLevel[efcStartCh + 1]); buf[3] += (int)(R * reverb.SendLevel[efcStartCh + 1]); } if ((activech & 0x010) != 0) { v = ch[2].Calc(); L = v; R = v; distortion.Mix(efcStartCh + 2, ref L, ref R); chorus.Mix(efcStartCh + 2, ref L, ref R); hpflpf.Mix(efcStartCh + 2, ref L, ref R); compressor.Mix(efcStartCh + 2, ref L, ref R); L = (int)((dest[2] >> 1) * L * panL[2]) * reversePhase.FM[num][2][0]; R = (int)((dest[2] & 0x1) * R * panR[2]) * reversePhase.FM[num][2][1]; buf[0] += L; buf[1] += R; buf[2] += (int)(L * reverb.SendLevel[efcStartCh + 2]); buf[3] += (int)(R * reverb.SendLevel[efcStartCh + 2]); } if ((activech & 0x040) != 0) { v = ch[3].Calc(); L = v; R = v; distortion.Mix(efcStartCh + 3, ref L, ref R); chorus.Mix(efcStartCh + 3, ref L, ref R); hpflpf.Mix(efcStartCh + 3, ref L, ref R); compressor.Mix(efcStartCh + 3, ref L, ref R); L = (int)((dest[3] >> 1) * L * panL[3]) * reversePhase.FM[num][3][0]; R = (int)((dest[3] & 0x1) * R * panR[3]) * reversePhase.FM[num][3][1]; buf[0] += L; buf[1] += R; buf[2] += (int)(L * reverb.SendLevel[efcStartCh + 3]); buf[3] += (int)(R * reverb.SendLevel[efcStartCh + 3]); } if ((activech & 0x100) != 0) { v = ch[4].Calc(); L = v; R = v; distortion.Mix(efcStartCh + 4, ref L, ref R); chorus.Mix(efcStartCh + 4, ref L, ref R); hpflpf.Mix(efcStartCh + 4, ref L, ref R); compressor.Mix(efcStartCh + 4, ref L, ref R); L = (int)((dest[4] >> 1) * L * panL[4]) * reversePhase.FM[num][4][0]; R = (int)((dest[4] & 0x1) * R * panR[4]) * reversePhase.FM[num][4][1]; buf[0] += L; buf[1] += R; buf[2] += (int)(L * reverb.SendLevel[efcStartCh + 4]); buf[3] += (int)(R * reverb.SendLevel[efcStartCh + 4]); } if ((activech & 0x400) != 0) { v = ch[5].Calc(); L = v; R = v; distortion.Mix(efcStartCh + 5, ref L, ref R); chorus.Mix(efcStartCh + 5, ref L, ref R); hpflpf.Mix(efcStartCh + 5, ref L, ref R); compressor.Mix(efcStartCh + 5, ref L, ref R); L = (int)((dest[5] >> 1) * L * panL[5]) * reversePhase.FM[num][5][0]; R = (int)((dest[5] & 0x1) * R * panR[5]) * reversePhase.FM[num][5][1]; buf[0] += L; buf[1] += R; buf[2] += (int)(L * reverb.SendLevel[efcStartCh + 5]); buf[3] += (int)(R * reverb.SendLevel[efcStartCh + 5]); } }
// --------------------------------------------------------------------------- // ADPCMA 合成 // public void Mix(int[] buffer, uint count) { if (tvol < 128 && (key & 0x3f) != 0) { //Sample* limit = buffer + count * 2; uint limit = count * 2; int revSampleL = 0; int revSampleR = 0; for (int i = 0; i < 6; i++) { Channel r = channel[i]; if ((key & (1 << i)) != 0 && (byte)r.level < 128) { //uint maskl = (uint)(r.panL == 0f ? -1 : 0); //uint maskr = (uint)(r.panR == 0f ? -1 : 0); int db = fmvgen.Limit(tl + tvol + r.level + r.volume, 127, -31); int vol = fmgen.OPNABase.tltable[fmvgen.FM_TLPOS + (db << (fmvgen.FM_TLBITS - 7))] >> 4; //Sample* dest = buffer; uint dest = 0; for (; dest < limit; dest += 2) { r.step += (uint)step; if (r.pos >= r.stop) { //SetStatus((uint)(0x100 << i)); key &= (byte)~(1 << i); break; } for (; r.step > 0x10000; r.step -= 0x10000) { int data; if ((r.pos & 1) == 0) { r.nibble = buf[r.pos >> 1]; data = (int)(r.nibble >> 4); } else { data = (int)(r.nibble & 0x0f); } r.pos++; r.adpcmx += jedi_table[r.adpcmd + data]; r.adpcmx = (short)fmvgen.Limit(r.adpcmx, 2048 * 3 - 1, -2048 * 3); r.adpcmd += (short)decode_tableA1[data]; r.adpcmd = (short)fmvgen.Limit(r.adpcmd, 48 * 16, 0); } int sampleL = (int)((r.adpcmx * vol) >> 10); int sampleR = (int)((r.adpcmx * vol) >> 10); distortion.Mix(revStartCh + i, ref sampleL, ref sampleR); chorus.Mix(revStartCh + i, ref sampleL, ref sampleR); hpflpf.Mix(revStartCh + i, ref sampleL, ref sampleR); compressor.Mix(revStartCh + i, ref sampleL, ref sampleR); sampleL = (int)(sampleL * r.panL) * reversePhase.AdpcmA[i][0]; sampleR = (int)(sampleR * r.panR) * reversePhase.AdpcmA[i][1]; fmvgen.StoreSample(ref buffer[dest + 0], sampleL); fmvgen.StoreSample(ref buffer[dest + 1], sampleR); revSampleL += (int)(sampleL * reverb.SendLevel[revStartCh + i] * 0.6); revSampleR += (int)(sampleR * reverb.SendLevel[revStartCh + i] * 0.6); //visRtmVolume[0] = (int)(sample & maskl); //visRtmVolume[1] = (int)(sample & maskr); } } } reverb.StoreDataC(revSampleL, revSampleR); } }
public void Mix(int[] dest, int count) { uint maskl = (uint)((control2 & 0x80) != 0 ? -1 : 0); uint maskr = (uint)((control2 & 0x40) != 0 ? -1 : 0); if (adpcmmask_) { maskl = maskr = 0; } if (adpcmplay) { int ptrDest = 0; // LOG2("ADPCM Play: %d DeltaN: %d\n", adpld, deltan); if (adpld <= 8192) // fplay < fsamp { for (; count > 0; count--) { if (adplc < 0) { adplc += 8192; DecodeADPCMB(); if (!adpcmplay) { break; } } int s = (adplc * apout0 + (8192 - adplc) * apout1) >> 13; int sL = (int)(s & maskl); int sR = (int)(s & maskr); distortion.Mix(efcCh, ref sL, ref sR); chorus.Mix(efcCh, ref sL, ref sR); hpflpf.Mix(efcCh, ref sL, ref sR); compressor.Mix(efcCh, ref sL, ref sR); sL = (int)(sL * panL) * reversePhase.Adpcm[num][0]; sR = (int)(sR * panR) * reversePhase.Adpcm[num][1]; int revSampleL = (int)(sL * reverb.SendLevel[efcCh]); int revSampleR = (int)(sR * reverb.SendLevel[efcCh]); fmvgen.StoreSample(ref dest[ptrDest + 0], sL); fmvgen.StoreSample(ref dest[ptrDest + 1], sR); reverb.StoreDataC(revSampleL, revSampleR); //visAPCMVolume[0] = (int)(s & maskl); //visAPCMVolume[1] = (int)(s & maskr); ptrDest += 2; adplc -= adpld; } for (; count > 0 && apout0 != 0; count--) { if (adplc < 0) { apout0 = apout1; apout1 = 0; adplc += 8192; } int s = (adplc * apout1) >> 13; int sL = (int)(s & maskl); int sR = (int)(s & maskr); distortion.Mix(efcCh, ref sL, ref sR); chorus.Mix(efcCh, ref sL, ref sR); hpflpf.Mix(efcCh, ref sL, ref sR); compressor.Mix(efcCh, ref sL, ref sR); sL = (int)(sL * panL) * reversePhase.Adpcm[num][0]; sR = (int)(sR * panR) * reversePhase.Adpcm[num][1]; int revSampleL = (int)(sL * reverb.SendLevel[efcCh]); int revSampleR = (int)(sR * reverb.SendLevel[efcCh]); fmvgen.StoreSample(ref dest[ptrDest + 0], sL); fmvgen.StoreSample(ref dest[ptrDest + 1], sR); reverb.StoreDataC(revSampleL, revSampleR); //visAPCMVolume[0] = (int)(s & maskl); //visAPCMVolume[1] = (int)(s & maskr); ptrDest += 2; adplc -= adpld; } } else // fplay > fsamp (adpld = fplay/famp*8192) { int t = (-8192 * 8192) / adpld; for (; count > 0; count--) { int s = apout0 * (8192 + adplc); while (adplc < 0) { DecodeADPCMB(); if (!adpcmplay) { goto stop; } s -= apout0 * Math.Max(adplc, t); adplc -= t; } adplc -= 8192; s >>= 13; int sL = (int)(s & maskl); int sR = (int)(s & maskr); distortion.Mix(efcCh, ref sL, ref sR); chorus.Mix(efcCh, ref sL, ref sR); hpflpf.Mix(efcCh, ref sL, ref sR); compressor.Mix(efcCh, ref sL, ref sR); sL = (int)(sL * panL) * reversePhase.Adpcm[num][0]; sR = (int)(sR * panR) * reversePhase.Adpcm[num][1]; int revSampleL = (int)(sL * reverb.SendLevel[efcCh]); int revSampleR = (int)(sR * reverb.SendLevel[efcCh]); fmvgen.StoreSample(ref dest[ptrDest + 0], sL); fmvgen.StoreSample(ref dest[ptrDest + 1], sR); reverb.StoreDataC(revSampleL, revSampleR); //visAPCMVolume[0] = (int)(s & maskl); //visAPCMVolume[1] = (int)(s & maskr); ptrDest += 2; } stop: ; } } if (!adpcmplay) { apout0 = apout1 = adpcmout = 0; adplc = 0; } }
public override void Mix(int[] dest, int nsamples) { byte r7 = (byte)~reg[7]; if (((r7 & 0x3f) | ((reg[8] | reg[9] | reg[10]) & 0x1f)) != 0) { chenable[0] = (byte)((((r7 & 0x01) != 0) && (speriod[0] <= (uint)(1 << toneshift))) ? 15 : 0); chenable[1] = (byte)((((r7 & 0x02) != 0) && (speriod[1] <= (uint)(1 << toneshift))) ? 15 : 0); chenable[2] = (byte)((((r7 & 0x04) != 0) && (speriod[2] <= (uint)(1 << toneshift))) ? 15 : 0); nenable[0] = (byte)((r7 & 0x08) != 0 ? 1 : 0); nenable[1] = (byte)((r7 & 0x10) != 0 ? 1 : 0); nenable[2] = (byte)((r7 & 0x20) != 0 ? 1 : 0); p[0] = ((mask & 1) != 0 && (reg[8] & 0x10) != 0) ? (uint?)null : 0; p[1] = ((mask & 2) != 0 && (reg[9] & 0x10) != 0) ? (uint?)null : 1; p[2] = ((mask & 4) != 0 && (reg[10] & 0x10) != 0) ? (uint?)null : 2; if (!phaseResetBefore[0] && phaseReset[0] != 0 && (r7 & 0x09) != 0) { scount[0] = 0; phaseResetBefore[0] = true; } if (!phaseResetBefore[1] && phaseReset[1] != 0 && (r7 & 0x12) != 0) { scount[1] = 0; phaseResetBefore[1] = true; } if (!phaseResetBefore[2] && phaseReset[2] != 0 && (r7 & 0x24) != 0) { scount[2] = 0; phaseResetBefore[2] = true; } int noise, sample, sampleL, sampleR, revSampleL, revSampleR; uint env; int nv = 0; if (p[0] != null && p[1] != null && p[2] != null) { // エンベロープ無し if ((r7 & 0x38) == 0) { int ptrDest = 0; // ノイズ無し for (int i = 0; i < nsamples; i++) { sampleL = 0; sampleR = 0; revSampleL = 0; revSampleR = 0; for (int j = 0; j < (1 << oversampling); j++) { for (int k = 0; k < 3; k++) { sample = tblGetSample[duty[k]](k, olevel[k]); int L = sample; int R = sample; distortion.Mix(efcStartCh + k, ref L, ref R); chorus.Mix(efcStartCh + k, ref L, ref R); hpflpf.Mix(efcStartCh + k, ref L, ref R); compressor.Mix(efcStartCh + k, ref L, ref R); L = (panpot[k] & 2) != 0 ? L : 0; R = (panpot[k] & 1) != 0 ? R : 0; L *= reversePhase.SSG[num][k][0]; R *= reversePhase.SSG[num][k][1]; revSampleL += (int)(L * reverb.SendLevel[efcStartCh + k] * 0.6); revSampleR += (int)(R * reverb.SendLevel[efcStartCh + k] * 0.6); sampleL += L; sampleR += R; scount[k] += speriod[k]; } } sampleL /= (1 << oversampling); sampleR /= (1 << oversampling); revSampleL /= (1 << oversampling); revSampleR /= (1 << oversampling); StoreSample(ref dest[ptrDest + 0], sampleL); StoreSample(ref dest[ptrDest + 1], sampleR); reverb.StoreDataC(revSampleL, revSampleR); ptrDest += 2; visVolume = sampleL; } } else { int ptrDest = 0; // ノイズ有り for (int i = 0; i < nsamples; i++) { sampleL = 0; sampleR = 0; revSampleL = 0; revSampleR = 0; sample = 0; for (int j = 0; j < (1 << oversampling); j++) { noise = (int)(noisetable[((uint)ncountDbl >> (int)((noiseshift + oversampling + 6)) & (noisetablesize - 1))] >> (int)((uint)ncountDbl >> (noiseshift + oversampling + 1))); ncountDbl += ((double)nperiod / ((reg[6] & 0x20) != 0 ? ncountDiv : 1.0)); for (int k = 0; k < 3; k++) { sample = tblGetSample[duty[k]](k, olevel[k]); int L = sample; int R = sample; //ノイズ nv = ((int)(scount[k] >> (toneshift + oversampling)) & 0 | (nenable[k] & noise)) - 1; sample = (int)((olevel[k] + nv) ^ nv); L += sample; R += sample; distortion.Mix(efcStartCh + k, ref L, ref R); chorus.Mix(efcStartCh + k, ref L, ref R); hpflpf.Mix(efcStartCh + k, ref L, ref R); compressor.Mix(efcStartCh + k, ref L, ref R); L = (panpot[k] & 2) != 0 ? L : 0; R = (panpot[k] & 1) != 0 ? R : 0; L *= reversePhase.SSG[num][k][0]; R *= reversePhase.SSG[num][k][1]; revSampleL += (int)(L * reverb.SendLevel[efcStartCh + k] * 0.6); revSampleR += (int)(R * reverb.SendLevel[efcStartCh + k] * 0.6); sampleL += L; sampleR += R; scount[k] += speriod[k]; } } sampleL /= (1 << oversampling); sampleR /= (1 << oversampling); StoreSample(ref dest[ptrDest + 0], sampleL); StoreSample(ref dest[ptrDest + 1], sampleR); reverb.StoreDataC(revSampleL, revSampleR); ptrDest += 2; visVolume = sampleL; } } // エンベロープの計算をさぼった帳尻あわせ ecount = (uint)((ecount >> 8) + (eperiod >> (8 - oversampling)) * nsamples); if (ecount >= (1 << (envshift + 6 + oversampling - 8))) { if ((reg[0x0d] & 0x0b) != 0x0a) { ecount |= (1 << (envshift + 5 + oversampling - 8)); } ecount &= (1 << (envshift + 6 + oversampling - 8)) - 1; } ecount <<= 8; } else { int ptrDest = 0; // エンベロープあり for (int i = 0; i < nsamples; i++) { sampleL = 0; sampleR = 0; revSampleL = 0; revSampleR = 0; for (int j = 0; j < (1 << oversampling); j++) { env = envelop[ecount >> (envshift + oversampling)]; ecount += eperiod; if (ecount >= (1 << (envshift + 6 + oversampling))) { if ((reg[0x0d] & 0x0b) != 0x0a) { ecount |= (1 << (envshift + 5 + oversampling)); } ecount &= (1 << (envshift + 6 + oversampling)) - 1; } noise = (int)(noisetable[((uint)ncountDbl >> (int)((noiseshift + oversampling + 6)) & (noisetablesize - 1))] >> (int)((uint)ncountDbl >> (noiseshift + oversampling + 1))); ncountDbl += (nperiod / ((reg[6] & 0x20) != 0 ? ncountDiv : 1.0)); for (int k = 0; k < 3; k++) { uint lv = (p[k] == null ? env : olevel[k]); sample = tblGetSample[duty[k]](k, lv); int L = sample; int R = sample; //ノイズ nv = ((int)(scount[k] >> (toneshift + oversampling)) & 0 | (nenable[k] & noise)) - 1; sample = (int)((lv + nv) ^ nv); L += sample; R += sample; distortion.Mix(efcStartCh + k, ref L, ref R); chorus.Mix(efcStartCh + k, ref L, ref R); hpflpf.Mix(efcStartCh + k, ref L, ref R); compressor.Mix(efcStartCh + k, ref L, ref R); L = (panpot[k] & 2) != 0 ? L : 0; R = (panpot[k] & 1) != 0 ? R : 0; L *= reversePhase.SSG[num][k][0]; R *= reversePhase.SSG[num][k][1]; revSampleL += (int)(L * reverb.SendLevel[efcStartCh + k] * 0.6); revSampleR += (int)(R * reverb.SendLevel[efcStartCh + k] * 0.6); sampleL += L; sampleR += R; scount[k] += speriod[k]; } } sampleL /= (1 << oversampling); sampleR /= (1 << oversampling); revSampleL /= (1 << oversampling); revSampleR /= (1 << oversampling); StoreSample(ref dest[ptrDest + 0], sampleL); StoreSample(ref dest[ptrDest + 1], sampleR); reverb.StoreDataC(revSampleL, revSampleR); ptrDest += 2; visVolume = sampleL; } } } }