示例#1
0
        Track[] Parse(IVsqx vsq)
        {
            var resolution      = vsq.MasterTrack.Resolution;
            var measureTicks    = resolution * 4; // for 4/4
            var preMeasureTicks = Enumerable.Range(0, vsq.MasterTrack.PreMeasure)
                                  .Select((i) => vsq.MasterTrack.TimeSig.First((sig) => sig.Measure <= i))
                                  .Select((sig) => measureTicks / sig.Denominator * sig.Nume)
                                  .Sum();

            var firstTempo = vsq.MasterTrack.Tempo.First().PushTo(vsq.MasterTrack.Tempo.TakeWhile((t) => t.Tick <= preMeasureTicks)).Last();

            firstTempo.Tick = preMeasureTicks;
            var tempo = vsq.MasterTrack.Tempo.SkipWhile((t) => t.Tick < preMeasureTicks)
                        .SelectReferencePrev <IVSTempo, Tempo>((v, p) =>
                                                               new Tempo(v.Tick - preMeasureTicks, p.Select((pt) => pt.TotalTime + (v.Tick - preMeasureTicks - pt.Tick) / pt.TickPerTime).FirstOrDefault(), v.BPM * 0.01, resolution)
                                                               )
                        .ToRangeDictionary((v) => v.Tick, IntervalMode.OpenInterval);

            return(vsq.VSTrack.Select((t) =>
            {
                var parts = Optional <IVSPart[]> .FromNull(t.Part)
                            .SelectMany(_ => _)
                            .Select((p) =>
                {
                    var partTick = p.Tick - preMeasureTicks;
                    var partStartTime = tempo[partTick].TickToTime(partTick);

                    var pbs = GetControlChange(p, "S", 2.0, partTick, tempo);
                    var pitchBend = GetControlChange(p, "P", 0.0, partTick, tempo)
                                    .ToRangeDictionary((e) => e.Key, e => e.Value / 8192.0 * pbs[e.Key], IntervalMode.OpenInterval);
                    var portamento = GetControlChange(p, "T", 64.0, partTick, tempo);

                    var notes = p.Note
                                .Select((n) =>
                    {
                        var tick = partTick + n.Tick;
                        var time = tempo[tick].TickToTime(tick);
                        var length = tempo[tick + n.Duration].TickToTime(tick + n.Duration) - time;
                        var pot = new Portamento((int)portamento[tempo[tick + n.Duration].TickToTime(tick + n.Duration)]);
                        return new Note(n.Character, time - partStartTime, length, n.NoteNumber, GetVibratoInfo(n, partTick, length, tempo), pot);
                    })
                                .ToRangeDictionary((n) => n.Position, IntervalMode.OpenInterval);

                    return new Part(partStartTime, tempo[partTick + p.PlayTime].TickToTime(partTick + p.PlayTime) - partStartTime, notes, pitchBend);
                })
                            .ToRangeDictionary((p) => p.TrackPosition, IntervalMode.OpenInterval);

                return new Track(t.Name, parts);
            }).ToArray());
        }
示例#2
0
        Track[] Parse(Vpr vpr)
        {
            const int resolution = 480;

            IEnumerable <VprValue> vprTempo = vpr.MasterTrack.Tempo.Events;

            if ((vprTempo.OrderBy(t => t.Pos).FirstOrDefault()?.Pos ?? int.MaxValue) != 0)
            {
                vprTempo = new VprValue {
                    Pos = 0, Value = vpr.MasterTrack.Tempo.Global.Value
                }.PushTo(vprTempo);
            }
            var tempo = vprTempo
                        .SelectReferencePrev <VprValue, Tempo>((v, p) => new Tempo(v.Pos, p.Select((pt) => pt.TotalTime + v.Pos / pt.TickPerTime).FirstOrDefault(), v.Value * 0.01, resolution))
                        .ToRangeDictionary(v => v.Tick, IntervalMode.OpenInterval);

            return(vpr.Tracks.Where(t => t.Type == 0)
                   .Select(t =>
            {
                var parts = Optional <VprPart[]> .FromNull(t.Parts)
                            .SelectMany(_ => _)
                            .Select(p =>
                {
                    var partTick = p.Pos;
                    var partStartTime = tempo[partTick].TickToTime(partTick);

                    var pbs = GetControlChange(p, "pitchBendSens", 2.0, partTick, tempo);
                    var pitchBend = GetControlChange(p, "pitchBend", 0.0, partTick, tempo)
                                    .ToRangeDictionary(e => e.Key, e => e.Value / 8192.0 * pbs[e.Key], IntervalMode.OpenInterval);
                    var portamento = GetControlChange(p, "portamento", 64.0, partTick, tempo);

                    var notes = p.Notes
                                .Select(n =>
                    {
                        var tick = partTick + n.Pos;
                        var time = tempo[tick].TickToTime(tick);
                        var length = tempo[tick + n.Duration].TickToTime(tick + n.Duration) - time;
                        var pot = new Portamento((int)portamento[tempo[tick + n.Duration].TickToTime(tick + n.Duration)]);
                        return new Note(n.Lyric, time - partStartTime, length, n.NoteNumber, GetVibratoInfo(n, partTick, tempo), pot);
                    })
                                .ToRangeDictionary((n) => n.Position, IntervalMode.OpenInterval);

                    return new Part(partStartTime, tempo[partTick + p.Duration].TickToTime(partTick + p.Duration) - partStartTime, notes, pitchBend);
                })
                            .ToRangeDictionary((p) => p.TrackPosition, IntervalMode.OpenInterval);

                return new Track(t.Name, parts);
            }).ToArray());
        }