private void cmdRepeatEnd(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { n = 2; } n = checkRange(n, 1, 255); try { clsRepeat re = pw.stackRepeat.Pop(); if (re.repeatCount == -1) { //初回 re.repeatCount = n; } re.repeatCount--; if (re.repeatCount > 0) { pw.stackRepeat.Push(re); pw.setPos(re.pos); } } catch { msgBox.setWrnMsg("[と]の数があいません。", lineNumber); } }
private void cmdGatetime2(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なゲートタイム指定'Q'が指定されています。", lineNumber); n = 1; } n = checkRange(n, 1, 8); pw.gatetime = n; pw.gatetimePmode = true; }
private void cmdPan(partWork pw) { int n; int vch = pw.ch; pw.incPos(); if (pw.chip is YM2610B) { if (pw.Type == enmChannelType.FMOPN || pw.Type == enmChannelType.FMOPNex) { //効果音モードのチャンネル番号を指定している場合は3chへ変更する if (pw.ch >= 6 && pw.ch <= 8) { vch = 2; } if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なパン'p'が指定されています。", lineNumber); n = 3; } //強制的にモノラルにする if (monoPart != null && monoPart.Contains(ym2612[0].Ch[5].Name)) { n = 3; } n = checkRange(n, 1, 3); pw.pan = n; outOPNSetPanAMSFMS(pw, n, pw.ams, pw.fms); } else if (pw.Type == enmChannelType.ADPCMA) { if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なパン'p'が指定されています。", lineNumber); n = 3; } n = checkRange(n, 0, 3); pw.pan = n; } else if (pw.Type == enmChannelType.ADPCMB) { if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なパン'p'が指定されています。", lineNumber); n = 3; } n = checkRange(n, 0, 3); setAdpcmBPan(pw, n); } } else if (pw.chip is YM2612) { //効果音モードのチャンネル番号を指定している場合は3chへ変更する if (pw.ch >= 6 && pw.ch <= 8) { vch = 2; } if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なパン'p'が指定されています。", lineNumber); n = 10; } //強制的にモノラルにする if (monoPart != null && monoPart.Contains(ym2612[0].Ch[5].Name)) { n = 3; } n = checkRange(n, 1, 3); pw.pan = n; outOPNSetPanAMSFMS(pw, n, pw.ams, pw.fms); } else if (pw.chip is SN76489) { pw.getNum(out n); msgBox.setWrnMsg("PSGパートでは、pコマンドは無視されます。", lineNumber); } else if (pw.chip is RF5C164) { int l; int r; if (!pw.getNum(out l)) { msgBox.setErrMsg("不正なパン'p'が指定されています。", lineNumber); l = 15; } if (pw.getChar() != ',') { msgBox.setErrMsg("不正なパン'p'が指定されています。", lineNumber); l = 15; r = 15; } pw.incPos(); if (!pw.getNum(out r)) { msgBox.setErrMsg("不正なパン'p'が指定されています。", lineNumber); r = 15; } l = checkRange(l, 0, 15); r = checkRange(r, 0, 15); pw.pan = (r << 4) | l; setRf5c164CurrentChannel(pw); setRf5c164Pan(pw, pw.pan); } }
private void commander(partWork pw, char cmd) { switch (cmd) { case ' ': case '\t': pw.incPos(); break; case '!': // CompileSkip pw.dataEnd = true; pw.waitCounter = -1; break; case 'T': // tempo cmdTempo(pw); break; case '@': // instrument cmdInstrument(pw); break; case 'v': // volume cmdVolume(pw); break; case 'V': // totalVolume(Adpcm-A / Rhythm) cmdTotalVolume(pw); break; case 'o': // octave cmdOctave(pw); break; case '>': // octave Up cmdOctaveUp(pw); break; case '<': // octave Down cmdOctaveDown(pw); break; case ')': // volume Up cmdVolumeUp(pw); break; case '(': // volume Down cmdVolumeDown(pw); break; case 'l': // length cmdLength(pw); break; case '#': // length(clock) cmdClockLength(pw); break; case 'p': // pan cmdPan(pw); break; case 'D': // Detune cmdDetune(pw); break; case 'm': // pcm mode cmdMode(pw); break; case 'q': // gatetime cmdGatetime(pw); break; case 'Q': // gatetime cmdGatetime2(pw); break; case 'E': // envelope cmdEnvelope(pw); break; case 'L': // loop point cmdLoop(pw); break; case '[': // repeat cmdRepeatStart(pw); break; case ']': // repeat cmdRepeatEnd(pw); break; case '/': // repeat cmdRepeatExit(pw); break; case 'M': // lfo cmdLfo(pw); break; case 'S': // lfo switch cmdLfoSwitch(pw); break; case 'y': // y cmdY(pw); break; case 'w': // noise cmdNoise(pw); break; case 'P': // noise or tone mixer cmdMixer(pw); break; case 'K': // key shift cmdKeyShift(pw); break; case 'c': case 'd': case 'e': case 'f': case 'g': case 'a': case 'b': case 'r': cmdNote(pw, cmd); break; default: msgBox.setErrMsg(string.Format("未知のコマンド{0}を検出しました。", cmd), pw.getLineNumber()); pw.incPos(); break; } }
private void cmdDetune(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なディチューン'D'が指定されています。", lineNumber); n = 0; } n = checkRange(n, -127, 127); pw.detune = n; }
private void cmdTempo(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なテンポが指定されています。", lineNumber); n = 120; } n = checkRange(n, 1, 255); tempo = n; samplesPerClock = vgmSamplesPerSecond * 60 * 4 / (tempo * clockCount); }
private void cmdVolumeUp(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正な音量')'が指定されています。", lineNumber); n = 10; } n = checkRange(n, 1, pw.MaxVolume); pw.volume += n; n = checkRange(n, 0, pw.MaxVolume); }
private void cmdMixer(partWork pw) { int n = -1; pw.incPos(); if (pw.Type == enmChannelType.SSG) { if (pw.getNum(out n)) { n = checkRange(n, 0, 3); pw.mixer = n; } else { msgBox.setErrMsg("wコマンドに指定された値が不正です。", lineNumber); return; } } else { msgBox.setErrMsg("このチャンネルではPコマンドは使用できません。", lineNumber); return; } }
private void cmdMode(partWork pw) { int n; pw.incPos(); if (pw.chip is YM2612 && pw.Type == enmChannelType.FMPCM) { if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なPCMモード指定'm'が指定されています。", lineNumber); n = 0; } n = checkRange(n, 0, 1); pw.pcm = (n == 1); pw.freq = -1;//freqをリセット outYM2612SetCh6PCMMode(pw, pw.pcm); } else { pw.getNum(out n); msgBox.setWrnMsg("このパートは6chではないため、mコマンドは無視されます。", lineNumber); } }
private void cmdLfoSwitch(partWork pw) { pw.incPos(); char c = pw.getChar(); if (c < 'P' && c > 'S') { msgBox.setErrMsg("指定できるLFOのチャネルはP,Q,R,Sの4種類です。", lineNumber); return; } c -= 'P'; int n = -1; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("LFOの設定値に不正な値が指定されました。", lineNumber); return; } n = checkRange(n, 0, 2); //解析 ここまで pw.lfo[c].sw = (n == 0) ? false : true; if (pw.lfo[c].type == eLfoType.Hardware && pw.lfo[c].param != null) { if (pw.chip is YM2612) { if (pw.lfo[c].param[4] == 0) { outOPNSetHardLfo(pw, (n == 0) ? false : true, pw.lfo[c].param[1]); } else { outOPNSetHardLfo(pw, false, pw.lfo[c].param[1]); } } } }
private void cmdLoop(partWork pw) { pw.incPos(); loopOffset = (long)dat.Count; loopSamples = lSample; foreach (clsChip chip in chips) { foreach (partWork p in chip.lstPartWork) { p.freq = -1; if (p.chip is RF5C164 && rf5c164[p.isSecondary ? 1 : 0].use) { //rf5c164の設定済み周波数値を初期化(ループ時に直前の周波数を引き継いでしまうケースがあるため) p.rf5c164AddressIncrement = -1; int n = p.instrument; p.pcmStartAddress = -1; p.pcmLoopAddress = -1; if (n != -1) { setRf5c164CurrentChannel(p); setRf5c164SampleStartAddress(p, (int)instPCM[n].stAdr); setRf5c164LoopAddress(p, (int)(instPCM[n].loopAdr)); } } } } }
private void cmdLfo(partWork pw) { pw.incPos(); char c = pw.getChar(); if (c < 'P' && c > 'S') { msgBox.setErrMsg("指定できるLFOのチャネルはP,Q,R,Sの4種類です。", lineNumber); return; } c -= 'P'; pw.incPos(); char t = pw.getChar(); if (t != 'T' && t != 'V' && t != 'H') { msgBox.setErrMsg("指定できるLFOの種類はT,V,Hの3種類です。", lineNumber); return; } pw.lfo[c].type = (t == 'T') ? eLfoType.Tremolo : ((t == 'V') ? eLfoType.Vibrato : eLfoType.Hardware); pw.lfo[c].sw = false; pw.lfo[c].isEnd = true; pw.lfo[c].param = new List<int>(); int n = -1; do { pw.incPos(); if (pw.getNum(out n)) { pw.lfo[c].param.Add(n); } else { msgBox.setErrMsg("LFOの設定値に不正な値が指定されました。", lineNumber); return; } while (pw.getChar() == '\t' || pw.getChar() == ' ') { pw.incPos(); } } while (pw.getChar() == ','); if (pw.lfo[c].type == eLfoType.Tremolo || pw.lfo[c].type == eLfoType.Vibrato) { if (pw.lfo[c].param.Count < 4) { msgBox.setErrMsg("LFOの設定に必要なパラメータが足りません。", lineNumber); return; } if (pw.lfo[c].param.Count > 7) { msgBox.setErrMsg("LFOの設定に可能なパラメータ数を超えて指定されました。", lineNumber); return; } pw.lfo[c].param[0] = checkRange(pw.lfo[c].param[0], 0, (int)clockCount); pw.lfo[c].param[1] = checkRange(pw.lfo[c].param[1], 1, 255); pw.lfo[c].param[2] = checkRange(pw.lfo[c].param[2], -32768, 32787); pw.lfo[c].param[3] = Math.Abs(checkRange(pw.lfo[c].param[3], -32768, 32787)); if (pw.lfo[c].param.Count > 4) { pw.lfo[c].param[4] = checkRange(pw.lfo[c].param[4], 0, 4); } else { pw.lfo[c].param.Add(0); } if (pw.lfo[c].param.Count > 5) { pw.lfo[c].param[5] = checkRange(pw.lfo[c].param[5], 0, 1); } else { pw.lfo[c].param.Add(1); } if (pw.lfo[c].param.Count > 6) { pw.lfo[c].param[6] = checkRange(pw.lfo[c].param[6], -32768, 32787); } else { pw.lfo[c].param.Add(0); } } else { if (pw.lfo[c].param.Count < 4) { msgBox.setErrMsg("LFOの設定に必要なパラメータが足りません。", lineNumber); return; } if (pw.lfo[c].param.Count > 5) { msgBox.setErrMsg("LFOの設定に可能なパラメータ数を超えて指定されました。", lineNumber); return; } pw.lfo[c].param[0] = checkRange(pw.lfo[c].param[0], 0, (int)clockCount); pw.lfo[c].param[1] = checkRange(pw.lfo[c].param[1], 0, 7); pw.lfo[c].param[2] = checkRange(pw.lfo[c].param[2], 0, 7); pw.lfo[c].param[3] = checkRange(pw.lfo[c].param[3], 0, 3); if (pw.lfo[c].param.Count == 5) { pw.lfo[c].param[4] = checkRange(pw.lfo[c].param[4], 0, 1); } else { pw.lfo[c].param.Add(1); } } //解析 ここまで pw.lfo[c].sw = true; pw.lfo[c].isEnd = false; pw.lfo[c].value = (pw.lfo[c].param[0] == 0) ? pw.lfo[c].param[6] : 0;//ディレイ中は振幅補正は適用されない pw.lfo[c].waitCounter = pw.lfo[c].param[0]; pw.lfo[c].direction = pw.lfo[c].param[2] < 0 ? -1 : 1; }
private void cmdKeyShift(partWork pw) { int n = -1; pw.incPos(); if (pw.getNum(out n)) { pw.keyShift = checkRange(n, -128, 128); } else { msgBox.setErrMsg("Kコマンドに指定された値が不正です。", lineNumber); return; } }
private void cmdInstrument(partWork pw) { int n; pw.incPos(); if (pw.chip is YM2610B) { if (pw.ch < 9) { if (!pw.getNum(out n)) { msgBox.setErrMsg("不正な音色番号が指定されています。", lineNumber); n = 0; } n = checkRange(n, 0, 255); if (pw.instrument != n) { pw.instrument = n; if (pw.Type == enmChannelType.FMOPNex) { ym2610b[pw.chip.ChipID].lstPartWork[2].instrument = n; ym2610b[pw.chip.ChipID].lstPartWork[6].instrument = n; ym2610b[pw.chip.ChipID].lstPartWork[7].instrument = n; ym2610b[pw.chip.ChipID].lstPartWork[8].instrument = n; } if (!pw.pcm) { outFmSetInstrument(pw, n, pw.volume); } else { if (!instPCM.ContainsKey(n)) { msgBox.setErrMsg(string.Format("PCM定義に指定された音色番号({0})が存在しません。", n), lineNumber); } else { if (instPCM[n].chip != enmChipType.YM2610B) { msgBox.setErrMsg(string.Format("指定された音色番号({0})はYM2610B向けPCMデータではありません。", n), lineNumber); } } } } } else if (pw.Type == enmChannelType.SSG) { n = setEnvelopParamFromInstrument(pw); } else if (pw.Type == enmChannelType.ADPCMA) { if (pw.getChar() != 'E') { if (!pw.getNum(out n)) { msgBox.setErrMsg("不正な音色番号が指定されています。", lineNumber); n = 0; } n = checkRange(n, 0, 255); if (!instPCM.ContainsKey(n)) { msgBox.setErrMsg(string.Format("PCM定義に指定された音色番号({0})が存在しません。", n), lineNumber); } else { if (instPCM[n].chip != enmChipType.YM2610B || instPCM[n].loopAdr != 0) { msgBox.setErrMsg(string.Format("指定された音色番号({0})はYM2610B向けPCMデータではありません。", n), lineNumber); } pw.instrument = n; setYM2610BADPCMAAddress(pw, (int)instPCM[n].stAdr, (int)instPCM[n].edAdr); } } else { pw.incPos(); n = setEnvelopParamFromInstrument(pw); } } else if (pw.Type == enmChannelType.ADPCMB) { if (pw.getChar() != 'E') { if (!pw.getNum(out n)) { msgBox.setErrMsg("不正な音色番号が指定されています。", lineNumber); n = 0; } n = checkRange(n, 0, 255); if (!instPCM.ContainsKey(n)) { msgBox.setErrMsg(string.Format("PCM定義に指定された音色番号({0})が存在しません。", n), lineNumber); } else { if (instPCM[n].chip != enmChipType.YM2610B || instPCM[n].loopAdr != 1) { msgBox.setErrMsg(string.Format("指定された音色番号({0})はYM2610B向けPCMデータではありません。", n), lineNumber); } pw.instrument = n; setYM2610BADPCMBAddress(pw, (int)instPCM[n].stAdr, (int)instPCM[n].edAdr); } } else { pw.incPos(); n = setEnvelopParamFromInstrument(pw); } } } else if (pw.chip is YM2612) { if (!pw.getNum(out n)) { msgBox.setErrMsg("不正な音色番号が指定されています。", lineNumber); n = 0; } n = checkRange(n, 0, 255); if (pw.instrument != n) { pw.instrument = n; if (pw.Type == enmChannelType.FMOPNex) { ym2612[pw.chip.ChipID].lstPartWork[2].instrument = n; ym2612[pw.chip.ChipID].lstPartWork[6].instrument = n; ym2612[pw.chip.ChipID].lstPartWork[7].instrument = n; ym2612[pw.chip.ChipID].lstPartWork[8].instrument = n; } if (!pw.pcm) { outFmSetInstrument(pw, n, pw.volume); } else { if (!instPCM.ContainsKey(n)) { msgBox.setErrMsg(string.Format("PCM定義に指定された音色番号({0})が存在しません。", n), lineNumber); } else { if (instPCM[n].chip != enmChipType.YM2612) { msgBox.setErrMsg(string.Format("指定された音色番号({0})はYM2612向けPCMデータではありません。", n), lineNumber); } } } } } else if (pw.chip is SN76489) { //pw.incPos(); n = setEnvelopParamFromInstrument(pw); } else if (pw.chip is RF5C164) { if (pw.getChar() != 'E') { if (!pw.getNum(out n)) { msgBox.setErrMsg("不正な音色番号が指定されています。", lineNumber); n = 0; } n = checkRange(n, 0, 255); if (!instPCM.ContainsKey(n)) { msgBox.setErrMsg(string.Format("PCM定義に指定された音色番号({0})が存在しません。", n), lineNumber); } else { if (instPCM[n].chip != enmChipType.RF5C164) { msgBox.setErrMsg(string.Format("指定された音色番号({0})はRF5C164向けPCMデータではありません。", n), lineNumber); } pw.instrument = n; setRf5c164CurrentChannel(pw); setRf5c164SampleStartAddress(pw, (int)instPCM[n].stAdr); setRf5c164LoopAddress(pw, (int)(instPCM[n].loopAdr)); } } else { pw.incPos(); n = setEnvelopParamFromInstrument(pw); } } }
private void cmdRepeatExit(partWork pw) { int n = -1; pw.incPos(); clsRepeat rx = pw.stackRepeat.Pop(); if (rx.repeatCount == 1) { int i = 0; while (true) { char c = pw.getChar(); if (c == ']') { if (i == 0) { break; } else i--; } else if (c == '[') { i++; } pw.incPos(); } pw.incPos(); pw.getNum(out n); } else { pw.stackRepeat.Push(rx); } }
private void cmdNoise(partWork pw) { int n = -1; pw.incPos(); if (pw.Type == enmChannelType.DCSGNOISE || pw.Type == enmChannelType.SSG) { if (pw.getNum(out n)) { n = checkRange(n, 0, pw.Type == enmChannelType.DCSGNOISE ? 7 : 31); if (pw.Type == enmChannelType.DCSGNOISE) { pw.noise = n; // DCSGの場合は4Chに保存 } else { pw.chip.lstPartWork[0].noise = n;//その他SSGの場合は、そのChipの1Chに保存 outSsgNoise(pw, n); } } else { msgBox.setErrMsg("wコマンドに指定された値が不正です。", lineNumber); return; } } else { msgBox.setErrMsg("このチャンネルではwコマンドは使用できません。", lineNumber); return; } }
private void cmdRepeatStart(partWork pw) { pw.incPos(); clsRepeat rs = new clsRepeat(); rs.pos = pw.getPos(); rs.repeatCount = -1;//初期値 pw.stackRepeat.Push(rs); }
private void cmdNote(partWork pw, char cmd) { pw.incPos(); //+ -の解析 int shift = 0; while (pw.getChar() == '+' || pw.getChar() == '-') { shift += pw.getChar() == '+' ? 1 : -1; pw.incPos(); } if (cmd == 'r' && shift != 0) { msgBox.setWrnMsg("休符での+、-の指定は無視されます。", lineNumber); } int ml = 0; int n = -1; bool isMinus = false; bool isSecond = false; do { int m = 0; //数値の解析 if (!pw.getNum(out n)) { if (!isSecond) n = (int)pw.length; else if (!isMinus) { //タイとして'&'が使用されている pw.tie = true; } } else { if ((int)clockCount % n != 0) { msgBox.setWrnMsg(string.Format("割り切れない音長({0})の指定があります。音長は不定になります。", n), lineNumber); } n = (int)clockCount / n; } if (!pw.tie) { m += n; //符点の解析 while (pw.getChar() == '.') { if (n % 2 != 0) { msgBox.setWrnMsg("割り切れない.の指定があります。音長は不定です。", lineNumber); } n = n / 2; m += n; pw.incPos(); } if (isMinus) ml -= m; else ml += m; } //ベンドの解析 int bendDelayCounter = 0; int bendShift = 0; if (pw.getChar() == '_') { pw.incPos(); pw.octaveNow = pw.octaveNew; pw.bendOctave = pw.octaveNow; pw.bendNote = 'r'; pw.bendWaitCounter = -1; bool loop = true; while (loop) { char bCmd = pw.getChar(); switch (bCmd) { case 'c': case 'd': case 'e': case 'f': case 'g': case 'a': case 'b': loop = false; pw.incPos(); //+ -の解析 bendShift = 0; while (pw.getChar() == '+' || pw.getChar() == '-') { bendShift += pw.getChar() == '+' ? 1 : -1; pw.incPos(); } pw.bendShift = bendShift; bendDelayCounter = 0; n = -1; isMinus = false; isSecond = false; do { m = 0; //数値の解析 if (!pw.getNum(out n)) { if (!isSecond) { n = 0; break; } else if (!isMinus) { //タイとして'&'が使用されている pw.tie = true; break; } } else { if ((int)clockCount % n != 0) { msgBox.setWrnMsg(string.Format("割り切れない音長({0})の指定があります。音長は不定になります。", n), lineNumber); } n = (int)clockCount / n; } if (!pw.tie) { bendDelayCounter += n; //符点の解析 while (pw.getChar() == '.') { if (n % 2 != 0) { msgBox.setWrnMsg("割り切れない.の指定があります。音長は不定です。", lineNumber); } n = n / 2; m += n; pw.incPos(); } if (isMinus) bendDelayCounter -= m; else bendDelayCounter += m; } if (pw.getChar() == '&') { isMinus = false; } else if (pw.getChar() == '~') { isMinus = true; } else { break; } isSecond = true; pw.incPos(); } while (true); if (cmd != 'r') { pw.bendNote = bCmd; bendDelayCounter = checkRange(bendDelayCounter, 0, ml); pw.bendWaitCounter = bendDelayCounter; } else { msgBox.setErrMsg("休符にベンドの指定はできません。", lineNumber); } break; case 'o': pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なオクターブが指定されています。", lineNumber); n = 110; } n = checkRange(n, 1, 8); pw.bendOctave = n; break; case '>': pw.incPos(); pw.bendOctave++; pw.bendOctave = checkRange(pw.bendOctave, 1, 8); break; case '<': pw.incPos(); pw.bendOctave--; pw.bendOctave = checkRange(pw.bendOctave, 1, 8); break; default: loop = false; break; } } //音符の変化量 int ed = note.IndexOf(pw.bendNote) + 1 + (pw.bendOctave - 1) * 12 + pw.bendShift; ed = checkRange(ed, 0, 8 * 12 - 1); int st = note.IndexOf(cmd) + 1 + (pw.octaveNow - 1) * 12 + shift;// st = checkRange(st, 0, 8 * 12 - 1); int delta = ed - st; if (delta == 0 || bendDelayCounter == ml) { pw.bendNote = 'r'; pw.bendWaitCounter = -1; } else { //1音符当たりのウエイト float wait = (ml - bendDelayCounter - 1) / (float)delta; float tl = 0; float bf = Math.Sign(wait); List<int> lstBend = new List<int>(); for (int i = 0; i < Math.Abs(delta); i++) { bf += wait; tl += wait; int a = getPsgFNum(pw.octaveNow, cmd, shift + (i + 0) * Math.Sign(delta));// int b = getPsgFNum(pw.octaveNow, cmd, shift + (i + 1) * Math.Sign(delta));// if ( (pw.chip is YM2610B && pw.ch < 9) || (pw.chip is YM2612)) { int[] ftbl = (pw.chip is YM2612) ? OPN_FNumTbl_7670454 : OPN_FNumTbl_8000000; a = getFmFNum(ftbl, pw.octaveNow, cmd, shift + (i + 0) * Math.Sign(delta));// b = getFmFNum(ftbl, pw.octaveNow, cmd, shift + (i + 1) * Math.Sign(delta));// int oa = (a & 0xf000) / 0x1000; int ob = (b & 0xf000) / 0x1000; if (oa != ob) { if ((a & 0xfff) == ftbl[0]) { oa += Math.Sign(ob - oa); a = (a & 0xfff) * 2 + oa * 0x1000; } else if ((b & 0xfff) == ftbl[0]) { ob += Math.Sign(oa - ob); b = (b & 0xfff) * ((delta > 0) ? 2 : 1) + ob * 0x1000; } } } else if (pw.chip is YM2610B && pw.Type == enmChannelType.SSG) { a = getSsgFNum(pw.octaveNow, cmd, shift + (i + 0) * Math.Sign(delta));// b = getSsgFNum(pw.octaveNow, cmd, shift + (i + 1) * Math.Sign(delta));// } else if (pw.chip is SN76489) { a = getPsgFNum(pw.octaveNow, cmd, shift + (i + 0) * Math.Sign(delta));// b = getPsgFNum(pw.octaveNow, cmd, shift + (i + 1) * Math.Sign(delta));// } else if (pw.chip is RF5C164) { a = getRf5c164PcmNote(pw.octaveNow, cmd, shift + (i + 0) * Math.Sign(delta));// b = getRf5c164PcmNote(pw.octaveNow, cmd, shift + (i + 1) * Math.Sign(delta));// } if (Math.Abs(bf) >= 1.0f) { for (int j = 0; j < (int)Math.Abs(bf); j++) { int c = b - a; int d = (int)Math.Abs(bf); lstBend.Add((int)(a + ((float)c / (float)d) * (float)j)); } bf -= (int)bf; } } Stack<Tuple<int, int>> lb = new Stack<Tuple<int, int>>(); int of = -1; int cnt = 1; foreach (int f in lstBend) { if (of == f) { cnt++; continue; } lb.Push(new Tuple<int, int>(f, cnt)); of = f; cnt = 1; } pw.bendList = new Stack<Tuple<int, int>>(); foreach (Tuple<int, int> lbt in lb) { pw.bendList.Push(lbt); } Tuple<int, int> t = pw.bendList.Pop(); pw.bendFnum = t.Item1; pw.bendWaitCounter = t.Item2; } } if (pw.getChar() == '&') { isMinus = false; } else if (pw.getChar() == '~') { isMinus = true; } else { break; } isSecond = true; pw.incPos(); } while (true); if (ml < 1) { msgBox.setErrMsg("負の音長が指定されました。", lineNumber); ml = (int)pw.length; } //装飾の解析完了 //WaitClockの決定 pw.waitCounter = ml; if (cmd != 'r') { //発音周波数 if (pw.bendWaitCounter == -1) { pw.octaveNow = pw.octaveNew; pw.noteCmd = cmd; pw.shift = shift; } else { pw.octaveNew = pw.bendOctave;// pw.octaveNow = pw.bendOctave;// pw.noteCmd = pw.bendNote; pw.shift = pw.bendShift; } //発音周波数の決定とキーオン if (pw.chip is YM2610B) { //YM2610B if (pw.Type == enmChannelType.FMOPN || pw.Type == enmChannelType.FMOPNex) { setFmFNum(pw); //タイ指定では無い場合はキーオンする if (!pw.beforeTie) { setLfoAtKeyOn(pw); setFmVolume(pw); outFmKeyOn(pw); } } else if (pw.Type == enmChannelType.SSG) { setSsgFNum(pw); //タイ指定では無い場合はキーオンする if (!pw.beforeTie) { setEnvelopeAtKeyOn(pw); setLfoAtKeyOn(pw); outSsgKeyOn(pw); } } else if (pw.Type == enmChannelType.ADPCMA) { if (!pw.beforeTie) { pw.keyOn = true; //if ((((YM2610B)pw.chip).adpcmA_KeyOn & (1 << (pw.ch - 12))) != 0) //{ // ((YM2610B)pw.chip).adpcmA_KeyOff |= (byte)(1 << (pw.ch - 12)); // ((YM2610B)pw.chip).adpcmA_beforeKeyOn &= (byte)~(1 << (pw.ch - 12)); //} //((YM2610B)pw.chip).adpcmA_KeyOn |= (byte)(1 << (pw.ch - 12)); } } else if (pw.Type == enmChannelType.ADPCMB) { setAdpcmBFNum(pw); //タイ指定では無い場合はキーオンする if (!pw.beforeTie) { setEnvelopeAtKeyOn(pw); setLfoAtKeyOn(pw); outAdpcmBKeyOn(pw); } } } else if (pw.chip is YM2612) { //YM2612 if (!pw.pcm) { setFmFNum(pw); } else { getPcmNote(pw); } //タイ指定では無い場合はキーオンする if (!pw.beforeTie) { setLfoAtKeyOn(pw); setFmVolume(pw); outFmKeyOn(pw); } } else if (pw.chip is SN76489) { // SN76489 setPsgFNum(pw); //タイ指定では無い場合はキーオンする if (!pw.beforeTie) { setEnvelopeAtKeyOn(pw); setLfoAtKeyOn(pw); outPsgKeyOn(pw); } } else if (pw.chip is RF5C164) { // RF5C164 setRf5c164FNum(pw); //タイ指定では無い場合はキーオンする if (!pw.beforeTie) { setEnvelopeAtKeyOn(pw); setLfoAtKeyOn(pw); setRf5c164Envelope(pw, pw.volume); outRf5c164KeyOn(pw); } } //gateTimeの決定 if (pw.gatetimePmode) { pw.waitKeyOnCounter = pw.waitCounter * pw.gatetime / 8L; } else { pw.waitKeyOnCounter = pw.waitCounter - pw.gatetime; } if (pw.waitKeyOnCounter < 1) pw.waitKeyOnCounter = 1; //PCM専用のWaitClockの決定 if (pw.pcm) { pw.pcmWaitKeyOnCounter = -1; if (Version != 1.60f) { pw.pcmWaitKeyOnCounter = pw.waitKeyOnCounter; } pw.pcmSizeCounter = instPCM[pw.instrument].size; } } pw.clockCounter += pw.waitCounter; }
private void cmdTotalVolume(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正な音量が指定されています。", lineNumber); n = 63; } if ((pw.chip is YM2610B) && pw.Type== enmChannelType.ADPCMA) { ((YM2610B)pw.chip).adpcmA_TotalVolume = checkRange(n, 0, ((YM2610B)pw.chip).adpcmA_MAXTotalVolume); } }
private void cmdOctave(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なオクターブが指定されています。", lineNumber); n = 110; } n = checkRange(n, 1, 8); pw.octaveNew = n; }
private void cmdY(partWork pw) { int n = -1; byte adr = 0; byte dat = 0; pw.incPos(); if (pw.getNum(out n)) { adr = (byte)(n & 0xff); } pw.incPos(); if (pw.getNum(out n)) { dat = (byte)(n & 0xff); } if ((pw.chip is YM2610B) || (pw.chip is YM2612)) { outFmAdrPort((pw.ch > 3 && pw.ch < 6) ? pw.port1 : pw.port0, adr, dat); } else if (pw.chip is SN76489) { outPsgPort(pw.isSecondary, dat); } else if (pw.chip is RF5C164) { outRf5c164Port(pw.isSecondary, adr, dat); } }
private void cmdOctaveDown(partWork pw) { pw.incPos(); pw.octaveNew--; pw.octaveNew = checkRange(pw.octaveNew, 1, 8); }
private void cmdClockLength(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正な音長が指定されています。", lineNumber); n = 10; } n = checkRange(n, 1, 65535); pw.length = n; }
private void cmdOctaveUp(partWork pw) { pw.incPos(); pw.octaveNew++; pw.octaveNew = checkRange(pw.octaveNew, 1, 8); }
private void cmdEnvelope(partWork pw) { int n = -1; if ( ((pw.chip is YM2610B) && (pw.Type == enmChannelType.SSG || pw.Type == enmChannelType.FMOPNex)) || ((pw.chip is YM2612) && (pw.Type == enmChannelType.FMPCM || (pw.Type == enmChannelType.FMOPNex))) || (pw.chip is SN76489) || (pw.chip is RF5C164) ) { pw.incPos(); switch (pw.getChar()) { case 'O': pw.incPos(); if ( ((pw.chip is YM2610B) && pw.Type == enmChannelType.FMOPNex) || pw.chip is YM2612 ) { switch (pw.getChar()) { case 'N': pw.incPos(); pw.Ch3SpecialMode = true; outOPNSetCh3SpecialMode(pw, true); break; case 'F': pw.incPos(); pw.Ch3SpecialMode = false; outOPNSetCh3SpecialMode(pw, false); break; default: msgBox.setErrMsg(string.Format("未知のコマンド(EO{0})が指定されました。", pw.getChar()), lineNumber); pw.incPos(); break; } } else { switch (pw.getChar()) { case 'N': pw.incPos(); pw.envelopeMode = true; break; case 'F': pw.incPos(); pw.envelopeMode = false; break; default: msgBox.setErrMsg(string.Format("未知のコマンド(EO{0})が指定されました。", pw.getChar()), lineNumber); pw.incPos(); break; } } break; case 'X': char c = pw.getChar(); if ( ((pw.chip is YM2610B) && pw.Type == enmChannelType.FMOPNex) || pw.chip is YM2612 ) { pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なスロット指定'EX'が指定されています。", lineNumber); n = 0; } byte res = 0; while (n % 10 != 0) { if (n % 10 > 0 && n % 10 < 5) { res += (byte)(1 << (n % 10 - 1)); } else { msgBox.setErrMsg(string.Format("未知のコマンド(EX{0})が指定されました。", n), lineNumber); break; } n /= 10; } if (res != 0) { pw.slots = res; } } else { msgBox.setErrMsg("未知のコマンド(EX)が指定されました。", lineNumber); } break; default: if (pw.Type == enmChannelType.FMOPNex) { int[] s = new int[] { 0, 0, 0, 0 }; for (int i = 0; i < 4; i++) { if (pw.getNum(out n)) { s[i] = n; } else { msgBox.setErrMsg("Eコマンドの解析に失敗しました。", lineNumber); break; } if (i == 3) break; pw.incPos(); } pw.slotDetune = s; break; } else { msgBox.setErrMsg(string.Format("未知のコマンド(E{0})が指定されました。", pw.getChar()), lineNumber); pw.incPos(); } break; } } else { msgBox.setWrnMsg("このパートは効果音モードに対応したチャンネルが指定されていないため、Eコマンドは無視されます。", lineNumber); pw.incPos(); } }
private void cmdGatetime(partWork pw) { int n; pw.incPos(); if (!pw.getNum(out n)) { msgBox.setErrMsg("不正なゲートタイム指定'q'が指定されています。", lineNumber); n = 0; } n = checkRange(n, 0, 255); pw.gatetime = n; pw.gatetimePmode = false; }