Пример #1
0
        public static ProcessResultArray <Clip> Apply(ScaleOptions options, params Clip[] clips)
        {
            if (options.By != null)
            {
                clips = clips.Prepend(options.By).ToArray();
            }
            ClipUtilities.NormalizeClipLengths(clips);
            if (clips.Length < 2)
            {
                return(new ProcessResultArray <Clip>(clips));
            }
            var masterClip     = clips[0];
            var slaveClips     = clips.Skip(1).ToArray();
            var processedClips = slaveClips.Select(c => new Clip(c.Length, c.IsLooping)).ToArray();

            for (var i = 0; i < slaveClips.Length; i++)
            {
                var slaveClip = slaveClips[i];
                foreach (var note in slaveClip.Notes)
                {
                    var constrainedNote = new NoteEvent(note);
                    constrainedNote.Pitch = options.Strict ?
                                            ClipUtilities.FindNearestNotePitchInSet(note, masterClip.Notes) :
                                            ClipUtilities.FindNearestNotePitchInSetMusical(note, masterClip.Notes);
                    processedClips[i].Notes.Add(constrainedNote);
                }
            }
            return(new ProcessResultArray <Clip>(processedClips));
        }
Пример #2
0
        public static ProcessResultArray <Clip> Apply(SetRhythmOptions options, params Clip[] clips)
        {
            if (options.By != null)
            {
                clips = clips.Prepend(options.By).ToArray();
            }

            if (clips.Length < 2)
            {
                return(new ProcessResultArray <Clip>(clips, $"SetRhythm: Skipped command because it needs 2 clips, and {clips.Length} were passed in."));
            }
            ClipUtilities.NormalizeClipLengths(clips);

            var resultClips  = new Clip[clips.Length - 1];
            var byClip       = clips[0];
            var byIndex      = 0;
            var resultClipIx = 0;

            for (var i = 1; i < clips.Length; i++)
            {
                var clip       = clips[i];
                var resultClip = new Clip(0, clip.IsLooping);

                foreach (var note in clip.Notes)
                {
                    var byNote = byClip.Notes[byIndex % byClip.Count];

                    // special case: add silence between start of clip and first note, but only the first time, since subsequent silences are handled by DurationUntilNextNote
                    if (resultClip.Length == 0 && byIndex == 0)
                    {
                        resultClip.Length = byNote.Start;
                    }

                    resultClip.Add(new NoteEvent(note.Pitch, resultClip.Length, byNote.Duration, note.Velocity));
                    resultClip.Length += byClip.DurationUntilNextNote(byIndex % byClip.Count);
                    byIndex++;
                }

                // stacked/overlapping notes will lead to incorrect final length of clip, so check if this is the case
                var latestNoteEnd = resultClip.Notes.Max(x => x.End);
                if (latestNoteEnd > resultClip.Length)
                {
                    resultClip.Length = latestNoteEnd;
                }

                resultClip.Length           = Utilities.RoundUpToNearestSixteenth(resultClip.Length); // quantize clip length to nearest 1/16, or Live won't accept it
                resultClips[resultClipIx++] = resultClip;
            }

            return(new ProcessResultArray <Clip>(resultClips));
        }
Пример #3
0
    public void TestNormalizeClipLengths()
    {
        var clip1 = new Clip(1, true)
        {
            Notes = new SortedList <NoteEvent>()
            {
                new NoteEvent(60, 0, .25m, 100),
                new NoteEvent(60, .4m, .1m, 100),
            }
        };
        var clip2 = new Clip(4, true)
        {
            Notes = new SortedList <NoteEvent>()
            {
                new NoteEvent(62, 0, 1, 100),
                new NoteEvent(62, 1, 1, 100),
                new NoteEvent(62, 2, 1, 100),
                new NoteEvent(62, 3, 1, 100)
            }
        };
        var clip3 = new Clip(2, true)
        {
            Notes = new SortedList <NoteEvent>()
            {
                new NoteEvent(64, .5m, 1, 100),
                new NoteEvent(64, 1.5m, .5m, 100),
            }
        };

        ClipUtilities.NormalizeClipLengths(new[] { clip1, clip2, clip3 });
        Assert.AreEqual(clip1.Notes[0].Start, 0);
        Assert.AreEqual(clip1.Notes[1].Start, .4m);
        Assert.AreEqual(clip1.Notes[2].Start, 1);
        Assert.AreEqual(clip1.Notes[3].Start, 1.4m);
        Assert.AreEqual(clip1.Notes[4].Start, 2);
        Assert.AreEqual(clip1.Notes[5].Start, 2.4m);
        Assert.AreEqual(clip1.Notes[6].Start, 3);
        Assert.AreEqual(clip1.Notes[7].Start, 3.4m);
        Assert.AreEqual(clip1.Notes.Count, 8);
        Assert.AreEqual(clip2.Notes[0].Start, 0);
        Assert.AreEqual(clip2.Notes[1].Start, 1);
        Assert.AreEqual(clip2.Notes[2].Start, 2);
        Assert.AreEqual(clip2.Notes[3].Start, 3);
        Assert.AreEqual(clip2.Notes.Count, 4);
        Assert.AreEqual(clip3.Notes[0].Start, .5m);
        Assert.AreEqual(clip3.Notes[1].Start, 1.5m);
        Assert.AreEqual(clip3.Notes[2].Start, 2.5m);
        Assert.AreEqual(clip3.Notes[3].Start, 3.5m);
        Assert.AreEqual(clip3.Notes.Count, 4);
    }
Пример #4
0
    public static ProcessResult <Clip[]> Apply(ScaleOptions options, params Clip[] clips)
    {
        if (options.By != null)
        {
            clips = clips.Prepend(options.By).ToArray();
        }
        ClipUtilities.NormalizeClipLengths(clips);
        if (clips.Length < 2)
        {
            return(new ProcessResult <Clip[]>(clips));
        }
        var masterClip     = clips[0];
        var slaveClips     = clips.Skip(1).ToArray();
        var processedClips = slaveClips.Select(c => new Clip(c.Length, c.IsLooping)).ToArray();

        for (var i = 0; i < slaveClips.Length; i++)
        {
            var slaveClip = slaveClips[i];
            foreach (var note in slaveClip.Notes)
            {
                var masterNotes = SortedList <NoteEvent> .Empty;
                if (options.PositionAware)
                {
                    masterNotes = masterClip.Notes.Where(x => x.StartsInsideIntervalInclusive(note.Start, note.End) || x.CoversInterval(note.Start, note.End)).ToSortedList();
                }
                if (masterNotes.Count == 0)
                {
                    masterNotes = masterClip.Notes;
                }

                var constrainedNote   = note with {
                };
                constrainedNote.Pitch = options.Strict ?
                                        ClipUtilities.FindNearestNotePitchInSet(note, masterNotes) :
                                        ClipUtilities.FindNearestNotePitchInSetMusical(note, masterNotes);
                processedClips[i].Notes.Add(constrainedNote);
            }
        }
        return(new ProcessResult <Clip[]>(processedClips));
    }
Пример #5
0
        public static ProcessResultArray <Clip> Apply(RatchetOptions options, params Clip[] clips)
        {
            options.Strength = Math.Clamp(options.Strength, 0, 1);
            if (options.By != null)
            {
                clips = clips.Prepend(options.By).ToArray();
            }
            ClipUtilities.NormalizeClipLengths(clips);
            if (clips.Length < 2)
            {
                clips = new[] { clips[0], clips[0] };
            }
            Clip controlSequence = new Clip(clips[0]);

            Clip[] targetSequences = clips.Skip(1).Select(x => new Clip(x)).ToArray();
            Clip[] resultSequences = new Clip[targetSequences.Length];

            if (options.RatchetValues.Length > 0)
            {
                for (var i = 0; i < options.RatchetValues.Length; i++)
                {
                    if (options.RatchetValues[i] < 1)
                    {
                        options.RatchetValues[i] = 1;                               // todo: should be handled by optionparser and min max values in optioninfo
                    }
                }
                for (var i = 0; i < targetSequences.Length; i++)
                {
                    var targetSequence = targetSequences[i];
                    resultSequences[i] = DoManualRatchet(options.RatchetValues, targetSequence, options.Strength, options.VelocityToStrength, options.Shape,
                                                         options.Mode);
                }
            }
            else
            {
                var(controlMin, controlMax, targetRange) = options.Mode == RatchetMode.Pitch
                    ? GetControlValuesFromPitch(options, controlSequence)
                    : GetControlValuesFromVelocity(options, controlSequence);

                float controlRange = Math.Max(controlMax - controlMin, 1);

                // set pitch for each note in control sequence
                if (options.Mode == RatchetMode.Pitch)
                {
                    foreach (var note in controlSequence.Notes)
                    {
                        note.Pitch = (int)Math.Round((note.Pitch - controlMin) / controlRange * targetRange) + 1;
                    }
                }
                else
                {
                    foreach (var note in controlSequence.Notes)
                    {
                        note.Velocity = (int)Math.Round((Math.Clamp(note.Velocity, controlMin, controlMax) - controlMin) / controlRange * targetRange) + 1;
                    }
                }
                for (var i = 0; i < targetSequences.Length; i++)
                {
                    var targetSequence = targetSequences[i];
                    resultSequences[i] = DoRatchet(controlSequence, targetSequence, (float)options.Strength, options.VelocityToStrength, options.Shape,
                                                   options.Mode);
                }
            }


            return(new ProcessResultArray <Clip>(resultSequences));
        }