Exemple #1
0
        public static Model Parse(string filename, bool computeNoteLenghts = true, bool computePitchBends = true,
                                  bool computeRealVolumes    = true, bool determineInstruments = false, bool normalizeMetre = false,
                                  bool prolongSustainedNotes = false, bool showBeats           = false, bool analyzeKeys    = false,
                                  bool analyzeChords         = false, bool playChords = false, bool discretizeBends = false, Tone?transposeTo = null)
        {
            if (playChords)
            {
                analyzeChords = true;
            }
            if (analyzeChords)
            {
                analyzeKeys = true;
            }
            if (discretizeBends)
            {
                computePitchBends = true;
            }
            if (transposeTo != null)
            {
                analyzeKeys = true;
            }

            var midi = new Model();

            using (var reader = new MidiBigEndianReader(File.Open(filename, FileMode.Open)))
            {
                ParseHeaderChunk(reader, midi);

                foreach (var track in midi.Tracks)
                {
                    ParseTrackChunk(reader, track);
                }

                if (computeNoteLenghts || normalizeMetre || showBeats)
                {
                    TimeCalculator.ComputeRealTimes(midi);
                    TimeCalculator.CreateNoteLengths(midi);
                }
                midi.Length = midi.EventsOfType <EndOfTrack>().Max(e => e.AbsoluteRealTime);

                if (computeRealVolumes || normalizeMetre || showBeats)
                {
                    var collector = new VolumeChangeCollector(midi);
                    collector.DetermineVolumes();
                }


                if (prolongSustainedNotes || normalizeMetre || showBeats)
                {
                    var sustainer = new Sustainer(midi);
                    sustainer.ProlongSustainedNotes();
                }

                if (normalizeMetre)
                {
                    Normalizer.CalculateMetre(midi);
                    Normalizer.Normalize(midi, prolongSustainedNotes);
                }
                else if (showBeats)
                {
                    Normalizer.CalculateMetre(midi);
                    Normalizer.AddBeats(midi, prolongSustainedNotes);
                }

                if (computePitchBends)
                {
                    PitchBendCalculator.JoinPitchBends(midi);
                    PitchBendCalculator.DeterminePitchRanges(midi);
                    if (discretizeBends)
                    {
                        PitchBendCalculator.DiscretizeBends(midi);
                    }
                }

                if (determineInstruments)
                {
                    var collector = new InstrumentChangeCollector(midi);
                    collector.DetermineInstruments();
                }

                if (analyzeKeys)
                {
                    if (!normalizeMetre && !showBeats)
                    {
                        Normalizer.CalculateMetre(midi);
                    }

                    if (midi.EventsOfType <KeySignature>().Any(k => k.Key.Tone != Tone.C || k.Key.Scale != Scale.Major))
                    {
                        midi.Key = midi.EventsOfType <KeySignature>().First().Key;
                        midi.IsKeyFoundByMidiItself = true;
                    }
                    else
                    {
                        MLKeyFinder.DetectKey(midi);
                        midi.IsKeyFoundByMidiItself = false;
                    }
                }

                if (analyzeChords)
                {
                    var analyzer = new ChordAnalyzer(midi);
                    analyzer.Analyze();

                    if (playChords)
                    {
                        analyzer.AddChordNotesToModel();
                    }
                }

                if (transposeTo != null)
                {
                    Transposer.Transpose(midi, (Tone)transposeTo);
                }

                ChannelPlayabilityChecker.Check(midi);
            }

            return(midi);
        }