예제 #1
0
        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
        }
예제 #2
0
        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);
        }