Пример #1
0
        private long GetAbsoluteTime(double startTime)
        {
            TempoIndex currentTempo = _tempoIdx.First();

            // Finds last tempo change before event
            foreach (TempoIndex idx in _tempoIdx.Skip(1))
            {
                if (idx.RealTime <= startTime)
                {
                    currentTempo = idx;
                }
                else
                {
                    break;
                }
            }

            double difference    = startTime - currentTempo.RealTime;
            long   absoluteTicks = currentTempo.AbsoluteTime + (1000L * (long)difference * DELTA_TICKS_PER_QUARTER) / currentTempo.MicroPerQuarter;

            // Applies quantization and snaps to grid
            int q = DELTA_TICKS_PER_MEASURE / QUANTIZATION;

            if (absoluteTicks % q != 0)
            {
                long before = absoluteTicks % q;
                long after  = q - before;

                if (before < after)
                {
                    absoluteTicks -= before;
                }
                else
                {
                    absoluteTicks += after;
                }
            }

            return(absoluteTicks);
        }
Пример #2
0
        private List <MidiEvent> CreateTempoTrack(List <XmkTempo> tempos, List <XmkTimeSignature> timeSignatures)
        {
            List <MidiEvent> track = new List <MidiEvent>();

            _tempoIdx.Clear();
            track.Add(new NAudio.Midi.TextEvent("xmkTempo", MetaEventType.SequenceTrackName, 0));

            if (tempos.Count <= 0 || tempos[0].Start > 0.0f)
            {
                var idxEntry = new TempoIndex(0, 0, 120);
                //track.Add(new NAudio.Midi.TempoEvent(idxEntry.MicroPerQuarter, idxEntry.AbsoluteTime));
                _tempoIdx.Add(idxEntry);
            }

            long GetAbsoluteTime(double startTime, TempoIndex currentTempo)
            {
                double difference    = startTime - currentTempo.RealTime;
                long   absoluteTicks = currentTempo.AbsoluteTime + (1000L * (long)difference * DELTA_TICKS_PER_QUARTER) / currentTempo.MicroPerQuarter;

                // Applies quantization and snaps to grid
                int q = DELTA_TICKS_PER_MEASURE / QUANTIZATION;

                if (absoluteTicks % q != 0)
                {
                    long before = absoluteTicks % q;
                    long after  = q - before;

                    if (before < after)
                    {
                        absoluteTicks -= before;
                    }
                    else
                    {
                        absoluteTicks += after;
                    }
                }

                return(absoluteTicks);
            }

            // Adds tempo changes
            if (tempos.Count > 0)
            {
                var firstTempo = tempos.First();
                var idxEntry   = new TempoIndex()
                {
                    AbsoluteTime = _tempoIdx.Count > 0 ? GetAbsoluteTime(firstTempo.Start * 1000, _tempoIdx.Last()) : 0,
                    RealTime     = firstTempo.Start * 1000,
                    BPM          = firstTempo.BPM
                };

                track.Add(new NAudio.Midi.TempoEvent(idxEntry.MicroPerQuarter, idxEntry.AbsoluteTime));
                _tempoIdx.Add(idxEntry);

                foreach (var tempoEntry in tempos.Skip(1))
                {
                    idxEntry = new TempoIndex()
                    {
                        AbsoluteTime = GetAbsoluteTime(tempoEntry.Start * 1000, _tempoIdx.Last()),
                        RealTime     = tempoEntry.Start * 1000,
                        BPM          = tempoEntry.BPM
                    };

                    track.Add(new NAudio.Midi.TempoEvent(idxEntry.MicroPerQuarter, idxEntry.AbsoluteTime));
                    _tempoIdx.Add(idxEntry);
                }
            }

            // Adds time signature changes
            foreach (var ts in timeSignatures)
            {
                int den = (int)Math.Log(ts.Denominator, 2);

                track.Add(new TimeSignatureEvent(ts.Ticks / 2, ts.Numerator, den, 24, 8));
            }

            // Sort by absolute time (And ensure track name is first event)
            track.Sort((x, y) => (int)(x is NAudio.Midi.TextEvent &&
                                       ((NAudio.Midi.TextEvent)x).MetaEventType == MetaEventType.SequenceTrackName
                                       ? int.MinValue : x.AbsoluteTime - y.AbsoluteTime));

            // Adds end track
            track.Add(new MetaEvent(MetaEventType.EndTrack, 0, track.Last().AbsoluteTime));
            return(track);
        }
Пример #3
0
        private List <MidiEvent> CreateTempoTrack(List <XmkTempo> tempos, List <XmkTimeSignature> timeSignatures)
        {
            List <MidiEvent> track = new List <MidiEvent>();

            _tempoIdx.Clear();
            track.Add(new NAudio.Midi.TextEvent("xmkTempo", MetaEventType.SequenceTrackName, 0));

            if (tempos.Count <= 0 || tempos[0].Start > 0.0f)
            {
                var idxEntry = new TempoIndex(0, 0, 120, (60000000 / 120));
                //track.Add(new NAudio.Midi.TempoEvent(idxEntry.MicroPerQuarter, idxEntry.AbsoluteTime));
                _tempoIdx.Add(idxEntry);
            }

            // Adds tempo changes
            if (tempos.Count > 0)
            {
                var firstTempo = tempos.First();
                var idxEntry   = new TempoIndex()
                {
                    AbsoluteTime    = _tempoIdx.Count > 0 ? (firstTempo.Ticks / 2) : 0,
                    RealTime        = firstTempo.Start * 1000,
                    BPM             = firstTempo.BPM,
                    MicroPerQuarter = (int)firstTempo.MicroPerQuarter
                };

                track.Add(new NAudio.Midi.TempoEvent(idxEntry.MicroPerQuarter, idxEntry.AbsoluteTime));
                _tempoIdx.Add(idxEntry);

                foreach (var tempoEntry in tempos.Skip(1))
                {
                    idxEntry = new TempoIndex()
                    {
                        AbsoluteTime    = (tempoEntry.Ticks / 2),
                        RealTime        = tempoEntry.Start * 1000,
                        BPM             = tempoEntry.BPM,
                        MicroPerQuarter = (int)tempoEntry.MicroPerQuarter
                    };

                    track.Add(new NAudio.Midi.TempoEvent(idxEntry.MicroPerQuarter, idxEntry.AbsoluteTime));
                    _tempoIdx.Add(idxEntry);
                }
            }

            // Adds time signature changes
            foreach (var ts in timeSignatures)
            {
                int den = (int)Math.Log(ts.Denominator, 2);

                track.Add(new TimeSignatureEvent(ts.Ticks / 2, ts.Numerator, den, 24, 8));
            }

            // Sort by absolute time (And ensure track name is first event)
            track.Sort((x, y) => (int)(x is NAudio.Midi.TextEvent &&
                                       ((NAudio.Midi.TextEvent)x).MetaEventType == MetaEventType.SequenceTrackName
                                       ? int.MinValue : x.AbsoluteTime - y.AbsoluteTime));

            // Adds end track
            track.Add(new MetaEvent(MetaEventType.EndTrack, 0, track.Last().AbsoluteTime));
            return(track);
        }