示例#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_QUARTER / 32; // 1/128th 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(Tempo tempo, TimeSignature ts)
        {
            List <MidiEvent> track = new List <MidiEvent>();

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

            if (tempo.Events.Count <= 0 || tempo.Events[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;

                //int q = DELTA_TICKS_PER_QUARTER / 32; // 1/128th quantization
                //if (absoluteTicks % q != 0) absoluteTicks += q - (absoluteTicks % q);

                // Applies quantization and snaps to grid
                int q = DELTA_TICKS_PER_QUARTER / 32; // 1/128th 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 (tempo.Events.Count > 0)
            {
                var firstTempo = tempo.Events.First();
                var idxEntry   = new TempoIndex()
                {
                    AbsoluteTime = _tempoIdx.Count > 0 ? GetAbsoluteTime(firstTempo.Start, _tempoIdx.Last()) : 0,
                    RealTime     = firstTempo.Start,
                    BPM          = firstTempo.BPM
                };

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

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

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

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

                track.Add(new TimeSignatureEvent(this.GetAbsoluteTime(time.Start), time.Beat, den, 24, 8));
            }

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

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