Exemple #1
0
        internal static MidiFile Load(string filePath)
        {
            try
            {
                MMSong mmSong = JsonExtensions.DeserializeFromFileCompressed <MMSong>(filePath);

                if (mmSong.schemaVersion < 1 && mmSong.schemaVersion > 2)
                {
                    throw new FileFormatException("Error: This mmsong file format is not understood.");
                }
                // For now, just play the first available song.
                // if (mmSong.songs.Count != 1) throw new FileFormatException("Error: BMP currently only supports mmsong files with 1 song in them.");

                MMSong.Song song = mmSong.songs[0];

                MidiFile sequence = new MidiFile();
                sequence.Chunks.Add(new TrackChunk());
                sequence.TimeDivision = new TicksPerQuarterNoteTimeDivision(600);
                using (TempoMapManager tempoMapManager = sequence.ManageTempoMap()) tempoMapManager.SetTempo(0, Tempo.FromBeatsPerMinute(100));

                foreach (MMSong.Bard bard in song.bards)
                {
                    List <Note> notes   = new List <Note>();
                    bool        failure = false;

                    switch (bard.instrument)
                    {
                    case Instrument.Cymbal:
                    case Instrument.Trumpet:
                    case Instrument.Trombone:
                    case Instrument.Horn:
                    case Instrument.Tuba:
                    case Instrument.Saxophone:
                    case Instrument.Violin:
                    case Instrument.Viola:
                    case Instrument.Cello:
                    case Instrument.DoubleBass:
                        bard.sequence = bard.sequence.ToDictionary(
                            x => x.Key + 2,
                            x => x.Value);
                        break;

                    default:
                        break;
                    }

                    if (bard.sequence.Count % 2 == 0)
                    {
                        long lastTime = 0;
                        int  lastNote = 254;
                        foreach (KeyValuePair <long, int> sEvent in bard.sequence)
                        {
                            if (!failure)
                            {
                                if (lastNote == 254)
                                {
                                    if (sEvent.Value <= 60 && sEvent.Value >= 24 && ((sEvent.Key * 25 % 100) == 50 || (sEvent.Key * 25) % 100 == 0))
                                    {
                                        lastNote = sEvent.Value + 24;
                                        lastTime = sEvent.Key * 25;
                                    }
                                    else
                                    {
                                        failure = true;
                                    }
                                }
                                else
                                {
                                    if (sEvent.Value == 254)
                                    {
                                        long dur = (sEvent.Key * 25) - lastTime;
                                        notes.Add(new Note((SevenBitNumber)lastNote, dur, lastTime)
                                        {
                                            Channel     = (FourBitNumber)14,
                                            Velocity    = (SevenBitNumber)(int)127,
                                            OffVelocity = (SevenBitNumber)(int)0
                                        });
                                        lastNote = 254;
                                        lastTime = sEvent.Key * 25;
                                    }
                                    else
                                    {
                                        failure = true;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        failure = true;
                    }

                    if (failure)
                    {
                        throw new FileFormatException("Error: This mmsong file is corrupted");
                    }

                    TrackChunk currentChunk = new TrackChunk(new SequenceTrackNameEvent(bard.instrument.ToString()));
                    currentChunk.AddNotes(notes);
                    notes = null;
                    sequence.Chunks.Add(currentChunk);
                    currentChunk = null;
                }

                using (var manager = new TimedEventsManager(sequence.GetTrackChunks().First().Events))
                    manager.Events.Add(new TimedEvent(new MarkerEvent(), (sequence.GetDuration <MetricTimeSpan>().TotalMicroseconds / 1000) + 100));

                return(sequence);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }