public void Write(R1Jaguar_MusicDescriptor file, string outPath) { #if ISWINDOWS Sequence s = new Sequence(); Track t = new Track(); s.Add(CreateTrack(file)); // This plugin doesn't overwrite files if (File.Exists(outPath)) { File.Delete(outPath); } s.Save(outPath); #endif }
private Track CreateTrack(R1Jaguar_MusicDescriptor jagFile) { Track t = new Track(); TempoChangeBuilder b = new TempoChangeBuilder(); b.Tempo = 22000; b.Build(); t.Insert(0, b.Result); ChannelMessageBuilder builder = new ChannelMessageBuilder(); Dictionary <int, int> curNoteOnChannel = new Dictionary <int, int>(); int timeScale = 1; for (int i = 0; i < jagFile.MusicData.Length; i++) { R1Jaguar_MusicData e = jagFile.MusicData[i]; if (e.Time != int.MaxValue) { int channelByte = BitHelpers.ExtractBits(e.Command, 8, 24); if (channelByte == 0x7F) // special point in the song { int idByte = BitHelpers.ExtractBits(e.Command, 8, 0); if (idByte == 0xFF && i >= jagFile.MusicData.Length - 2) // End point { t.EndOfTrackOffset = e.Time / timeScale; break; } else { // Loop point, or command to return to loop point } } else { int channel = BitHelpers.ExtractBits(e.Command, 4, 26); int command = BitHelpers.ExtractBits(e.Command, 1, 31); if (command == 1) { // Note off if (curNoteOnChannel.ContainsKey(channel)) { builder.Command = ChannelCommand.NoteOff; int note = curNoteOnChannel.TryGetValue(channel, out int val) ? val : 0; if (note >= 128) { builder.MidiChannel = 9; builder.Data1 = note - 128; } else { builder.MidiChannel = channel; builder.Data1 = note; } builder.Data2 = 127; builder.Build(); t.Insert(e.Time / timeScale, builder.Result); } // Program change int instrument = BitHelpers.ExtractBits(e.Command, 5, 21); if (PercussionInstruments[instrument] != Percussion.None) { builder.MidiChannel = 9; } else { builder.MidiChannel = channel; builder.Command = ChannelCommand.ProgramChange; builder.Data1 = GeneralMidiInstruments[instrument] == Instrument.None ? 0 : (int)GeneralMidiInstruments[instrument]; if (GeneralMidiInstruments[instrument] == Instrument.Sitar) { Controller.print("unknown @ " + jagFile.MusicDataPointer); } builder.Build(); t.Insert(e.Time / timeScale, builder.Result); } // Note on builder.Command = ChannelCommand.NoteOn; int freq = BitHelpers.ExtractBits(e.Command, 13, 8); int vel = BitHelpers.ExtractBits(e.Command, 7, 0); //bool hasVelocity = BitHelpers.ExtractBits(e.Command, 1, 7) == 1; builder.Data1 = GetMidiPitch(freq, 349f); //builder.Data2 = UnityEngine.Mathf.RoundToInt(127f * (vel / 7f)); float velf = ((vel + 1) / 128f); // hack int veli = Mathf.RoundToInt(velf * 127f); /*if (!hasVelocity) { * veli = 127; * }*/ if (PercussionInstruments[instrument] != Percussion.None) { builder.Data1 = (int)PercussionInstruments[instrument]; builder.Data2 = PercussionInstruments[instrument] == Percussion.None ? 0 : veli; curNoteOnChannel[channel] = builder.Data1 + 128; } else { builder.Data2 = GeneralMidiInstruments[instrument] == Instrument.None ? 0 : veli; curNoteOnChannel[channel] = builder.Data1; } builder.Build(); t.Insert(e.Time / timeScale, builder.Result); } else { builder.Command = ChannelCommand.NoteOff; int note = curNoteOnChannel.TryGetValue(channel, out int val) ? val : 0; if (note >= 128) { builder.MidiChannel = 9; builder.Data1 = note - 128; } else { builder.MidiChannel = channel; builder.Data1 = note; } builder.Data2 = 127; curNoteOnChannel.Remove(channel); builder.Build(); t.Insert(e.Time / timeScale, builder.Result); } } } } return(t); }