private static List <byte> ConvertYM3812KeyOnStateToYM2151KeyOnCommands(YM3812 ym3812) { List <byte> result = new List <byte>(); for (int channel = 0; channel < 9; channel++) { if (channel <= 7) { //C2 M2 C1 M1 byte operatormask = (byte)KeyEnableByOperator.C1 + (byte)KeyEnableByOperator.M1; if (ym3812.KeyOffHappened(channel)) { //$08 -SSSSCCC Key On(Play Sound) C = Channel S = Slot(C2 M2 C1 M1) byte register = (byte)(0x08); byte value = operatormask; value += (byte)(channel & 0b00000111); result.Add(register); result.Add(value); } if (ym3812.KeyOnHappened(channel)) { //$08 -SSSSCCC Key On(Play Sound) C = Channel S = Slot(C2 M2 C1 M1) byte register = (byte)(0x08); byte value = operatormask; value += (byte)(channel & 0b00000111); result.Add(register); result.Add(value); } } } return(result); }
public static void YM3812Notes(VGMRead reader) { Console.WriteLine("YM3812 Notes"); YM3812 chip = new YM3812(); foreach (var command in reader.VGMCommands) { if (command is YM3812Command) { chip.ConsumeCommand((YM3812Command)command); } if (command is VGMwait || command is VGMendofsounddata) { string line = "| "; for (int i = 0; i < 8; i++) { line += (chip.KeyOn(i) ? "O" : " ") + " " + Tools.FrequencyToNote(chip.Freq(i)) + " " + ((int)Math.Round(chip.Freq(i))).ToString("D4") + " | "; } if (command is VGMwait) { line += Statistics.VGMWait2mSec(((VGMwait)command).waitsamples).ToString("0000"); } Console.WriteLine(line); } } }
public static void ChannelStats(VGMRead reader) { Console.CursorVisible = false; Console.SetWindowSize(200, 50); //Console.SetWindowSize(20, 20); //Console.SetWindowPosition(100, 20); Console.SetCursorPosition(0, 0); Console.WriteLine("ChannelStats"); DrawStatic(); YM3812 chip = new YM3812(); int position = 0; foreach (var command in reader.VGMCommands) { if (command is YM3812Command) { chip.ConsumeCommand((YM3812Command)command); } if (command is VGMwait || command is VGMendofsounddata) { for (int i = 0; i < 9; i++) { var channelstat = chip.GetChannelStats(i); DrawChannelStat(channelstat); } Console.SetCursorPosition(20, 0); Console.WriteLine(position); Console.SetCursorPosition(0, 25); if (command is VGMwait) { int w = (int)(((VGMwait)command).waitsamples / 44.100); position += w; Thread.Sleep(w); } } } Console.CursorVisible = true; }
public static void ConvertYM3812stateToYM2151state(YM3812 ym3812, YM2151 ym2151) { for (int channel = 0; channel < 9; channel++) { //int channel = 0; //var chs = ym3812.GetChannelStats(4); var chs = ym3812.GetChannelStats(channel); if (channel <= 7) { //Operator settings { int opnum = 0; TrackConv.YM2151operator op0 = new TrackConv.YM2151operator(); LoadFromYM3812Operator(op0, chs.OPR1); int slot = opnum * 8 + channel; SetYM2151Operator(ym2151, slot, op0); opnum = 2; TrackConv.YM2151operator op2 = new TrackConv.YM2151operator(); LoadFromYM3812Operator(op2, chs.OPR2); slot = opnum * 8 + channel; SetYM2151Operator(ym2151, slot, op2); } //PMS and AMS { byte PMS = chs.OPR2.Vibrato ? (byte)0x04 : (byte)0x00; byte AMS = chs.OPR2.AmpMod ? (byte)0x02 : (byte)0x00; //$38-$3F -PPP--AA Channel 0-7 PMS / AMS P = PMS , A = AMS byte register = (byte)(0x38 + channel); byte value = 0; value += (byte)(PMS << 4); value += AMS; ym2151.registers[register] = value; } //Connection and feedback { byte CON = 7; if (chs.Connection == 0) { CON = 6; } byte FB = (byte)chs.Feedback; //$20-$27 LRFFFCCC Channel 0-7 L = Left, R = Right, F = Feedback, C = Connection byte register = (byte)(0x20 + channel); byte value = 0b11000000; value += (byte)(FB << 3); value += CON; ym2151.registers[register] = value; } //Note (note octave cent) { var note = Tools.FrequencyToNote(chs.Freq); if (!note.OutOfRange) { int note_ = note.note; int octave_ = note.octave; int cent_ = note.cent; if (note.cent_sign < 0) { note_ -= 1; if (note_ < 0) { note_ = 11; octave_ -= 1; if (octave_ < 0) { note_ = 0; octave_ = 0; cent_ = -100; } } cent_ = 100 + cent_; } cent_ = cent_ * 64 / 100; //$28 -$2F -OOONNNN Chn0 - 7 KeyCode O = Octive, N = Note byte register = (byte)(0x28 + channel); byte value = 0; value += (byte)((note_ & 0b00000111) << 4); value += (byte)(octave_ & 0b00001111); ym2151.registers[register] = value; //$30 -$38 FFFFFF-- Chn0 - 7 F = keyFraction register = (byte)(0x30 + channel); value = 0; value += (byte)((cent_ & 0b00111111) << 2); ym2151.registers[register] = value; } } } } }
static void Main(string[] args) { //VGMRead reader = new VGMRead(@"C:\Users\mpathy\Desktop\TrackerMuzax\vgzs\03 Water.vgm"); VGMRead reader = new VGMRead(@"C:\Users\mpathy\Desktop\TrackerMuzax\vgzs\06 Chani's Eyes.vgm"); //VGMRead reader = new VGMRead(@"C:\Users\mpathy\Desktop\TrackerMuzax\vgzs\07 Sign of the Worm.vgm"); reader.Open(); //Statistics.VGMWaitTotal(reader); //Statistics.YM3812WaveformStatistics(reader); //Statistics.YM3812Notes(reader); //Visulaize.ChannelStats(reader); double waittickcorrection = 0; double x16tickinmillisec = 1000 / 60; YM3812 ym3812 = new YM3812(); YM2151 ym2151 = new YM2151(); List <byte> outbytes = new List <byte>(); //Start pause. //outbytes.AddRange(new byte[] { 0, 60 }); ym2151.Reset(); ym2151.NextTick(); ym3812.NextTick(); foreach (var command in reader.VGMCommands) { if (command is YM3812Command) { ym3812.ConsumeCommand((YM3812Command)command); } if (command is VGMwait || command is VGMendofsounddata) { ConvertYM3812stateToYM2151state(ym3812, ym2151); outbytes.AddRange(ym2151.GetChangedRegisters()); outbytes.AddRange(ConvertYM3812KeyOnStateToYM2151KeyOnCommands(ym3812)); if (command is VGMwait) { var waitmillisecs = ((VGMwait)command).waitsamples / 44.100; var unroundedwaitticks = waitmillisecs / x16tickinmillisec; unroundedwaitticks += waittickcorrection; var waitticks = Math.Round(unroundedwaitticks); waittickcorrection = unroundedwaitticks - waitticks; if (waitticks != 0) { while (waitticks > 0) { outbytes.Add(0); if (waitticks > 255) { outbytes.Add(255); } else { outbytes.Add((byte)waitticks); } waitticks -= 255; } } } ym2151.NextTick(); ym3812.NextTick(); } } //Trailing pause //outbytes.AddRange(new byte[] { 0, 60 }); Directory.SetCurrentDirectory(@"C:\Users\mpathy\Source\Repos\TrackConv\Player"); CX16BasicWriter.ToFile(outbytes); DumbBinWriter.ToFile(outbytes); VGMWriter.ToFile(outbytes); }