Exemplo n.º 1
0
        public static QNT_Duration DurationFromBeatSnap(uint beatSnap)
        {
            QNT_Duration duration = Constants.QuarterNoteDuration;

            //Since we use PPQN, anything a quarter note or smaller is a division of the time
            if (beatSnap >= 4)
            {
                duration.tick = (UInt64)(duration.tick / (beatSnap / 4.0f));
            }
            //Otherwise, it is a multiplication
            else
            {
                duration.tick = (UInt64)((4.0f / beatSnap) * duration.tick);
            }

            return(duration);
        }
Exemplo n.º 2
0
        void ClickTrackPCMReaderCallback(float[] data)
        {
            CopyContext ctx;

            ctx.bufferData     = data;
            ctx.bufferChannels = 2;
            ctx.bufferFreq     = sampleRate;
            ctx.playbackSpeed  = 1.0f;
            ctx.outputValue    = 0.0f;
            ctx.volume         = volume;

            for (int dataIndex = 0; dataIndex < data.Length / 2; dataIndex++)
            {
                ctx.index = dataIndex;

                QNT_Timestamp currentTick           = timeline.ShiftTick(new QNT_Timestamp(0), (float)((dataIndex) / (float)sampleRate));
                TempoChange   currentTempo          = timeline.GetTempoForTime(currentTick);
                QNT_Duration  timeSignatureDuration = new QNT_Duration(Constants.PulsesPerWholeNote / currentTempo.timeSignature.Denominator);
                GenerateClickTrackSamples(ctx, currentTick, currentTempo, timeSignatureDuration);
            }
        }
Exemplo n.º 3
0
        void GenerateClickTrackSamples(CopyContext ctx, QNT_Timestamp currentTick, TempoChange currentTempo, QNT_Duration timeSignatureDuration)
        {
            QNT_Timestamp tempoStart       = currentTempo.time;
            QNT_Timestamp nextBeat         = timeline.GetClosestBeatSnapped(currentTick, currentTempo.timeSignature.Denominator);
            UInt64        currentBeatInBar = ((currentTick.tick - tempoStart.tick) / timeSignatureDuration.tick) % currentTempo.timeSignature.Numerator;

            if (currentBeatInBar != 1)
            {
                TryAddClickEvent(currentTick, nextBeat, hihat_hit);
            }
            else
            {
                TryAddClickEvent(currentTick, nextBeat, hihat_hit3);
            }

            TryAddClickEvent(currentTick, nextBeat + Constants.SixteenthNoteDuration, hihat_hit2);
            TryAddClickEvent(currentTick, nextBeat + Constants.EighthNoteDuration, hihat_open);

            for (int i = clickTrackEvents.Count - 1; i >= 0; i--)
            {
                ClickTrackEvent ev = clickTrackEvents[i];
                ev.clip.currentSample = ev.currentSample;
                ev.clip.CopySampleIntoBuffer(ctx);
                ev.currentSample = ev.clip.currentSample;

                if (ev.clip.scaledCurrentSample > ev.clip.samples.Length)
                {
                    clickTrackEvents.RemoveAt(i);
                }
                else
                {
                    clickTrackEvents[i] = ev;
                }
            }
        }
Exemplo n.º 4
0
        void OnAudioFilterRead(float[] bufferData, int bufferChannels)
        {
            CopyContext ctx;

            ctx.bufferData     = bufferData;
            ctx.bufferChannels = bufferChannels;
            ctx.bufferFreq     = sampleRate;
            ctx.playbackSpeed  = speed;
            ctx.outputValue    = 0.0f;

            if (clearHitsounds)
            {
                hitsoundEvents.Clear();
                hitSoundEnd    = new QNT_Timestamp(0);
                clearHitsounds = false;
            }

            if (clearClicksounds)
            {
                clickTrackEvents.Clear();
                clearClicksounds = false;
            }

            if (newPreviewHitsoundEvents != null)
            {
                List <HitsoundEvent> newPreview = newPreviewHitsoundEvents;
                newPreviewHitsoundEvents = null;

                previewHitsoundEvents.Clear();
                previewHitsoundEvents = newPreview;
            }

            if (playPreview)
            {
                int dataIndex = 0;

                while (dataIndex < bufferData.Length / bufferChannels && (preview.currentSample < currentPreviewSongSampleEnd) && (preview.scaledCurrentSample) < song.samples.Length)
                {
                    ctx.index         = dataIndex;
                    ctx.volume        = volume;
                    ctx.playbackSpeed = speed;
                    preview.CopySampleIntoBuffer(ctx);

                    PlayHitsounds(ctx, previewHitsoundEvents);

                    ++dataIndex;
                }

                if (preview.currentSample >= currentPreviewSongSampleEnd || (preview.scaledCurrentSample) >= song.samples.Length)
                {
                    playPreview = false;
                }
            }

            if (paused || (song.scaledCurrentSample) > song.samples.Length)
            {
                hitsoundEvents.Clear();

                //Continue to flush the hitsounds
                if (!playPreview && previewHitsoundEvents.Count > 0)
                {
                    int dataIndex = 0;

                    while (dataIndex < bufferData.Length / bufferChannels)
                    {
                        ctx.index  = dataIndex;
                        ctx.volume = hitSoundVolume;
                        PlayHitsounds(ctx, previewHitsoundEvents);
                        ++dataIndex;
                    }
                }

                return;
            }

            if (song != null)
            {
                QNT_Timestamp timeStart = timeline.ShiftTick(new QNT_Timestamp(0), (float)song.currentTime);
                QNT_Timestamp timeEnd   = timeline.ShiftTick(new QNT_Timestamp(0), (float)(song.currentTime + (bufferData.Length / bufferChannels) / (float)song.frequency * (song.frequency / (float)sampleRate)));

                if (timeEnd > hitSoundEnd)
                {
                    hitSoundEnd = timeStart + Constants.QuarterNoteDuration;
                    AddHitsoundEvents(hitsoundEvents, timeStart, hitSoundEnd);
                }
            }

            for (int dataIndex = 0; dataIndex < bufferData.Length / bufferChannels; dataIndex++)
            {
                ctx.volume        = volume;
                ctx.index         = dataIndex;
                ctx.playbackSpeed = speed;
                song.CopySampleIntoBuffer(ctx);

                if (songExtra != null)
                {
                    songExtra.CopySampleIntoBuffer(ctx);
                }

                //Play hitsounds (reverse iterate so we can remove)
                ctx.volume = hitSoundVolume;
                PlayHitsounds(ctx, hitsoundEvents);

                ctx.playbackSpeed = speed;
                if (leftSustain != null)
                {
                    ctx.volume = leftSustainVolume;
                    leftSustain.CopySampleIntoBuffer(ctx);
                }

                if (rightSustain != null)
                {
                    ctx.volume = rightSustainVolume;
                    rightSustain.CopySampleIntoBuffer(ctx);
                }

                QNT_Timestamp currentTick           = timeline.ShiftTick(new QNT_Timestamp(0), (float)GetTimeFromCurrentSample());
                TempoChange   currentTempo          = timeline.GetTempoForTime(currentTick);
                QNT_Duration  timeSignatureDuration = new QNT_Duration(Constants.PulsesPerWholeNote / currentTempo.timeSignature.Denominator);

                if (playMetronome)
                {
                    if (GetTimeFromCurrentSample() > nextMetronomeTick)
                    {
                        metronomeSamplesLeft = (int)(sampleRate * metronomeTickLength);
                        nextMetronomeTick    = 0;
                    }

                    if (nextMetronomeTick == 0)
                    {
                        QNT_Timestamp nextBeat = timeline.GetClosestBeatSnapped(timeline.ShiftTick(new QNT_Timestamp(0), (float)GetTimeFromCurrentSample()) + timeSignatureDuration, currentTempo.timeSignature.Denominator);
                        nextMetronomeTick = timeline.TimestampToSeconds(nextBeat);
                    }
                }

                //Metronome
                if (metronomeSamplesLeft > 0)
                {
                    const uint MetronomeTickFreq    = 817;
                    const uint BigMetronomeTickFreq = 1024;

                    QNT_Timestamp tempoStart = currentTempo.time;

                    uint tickFreq = 0;

                    UInt64 currentBeatInBar = ((currentTick.tick - tempoStart.tick) / timeSignatureDuration.tick) % currentTempo.timeSignature.Numerator;

                    if (currentBeatInBar == 0)
                    {
                        tickFreq = BigMetronomeTickFreq;
                    }
                    else
                    {
                        tickFreq = MetronomeTickFreq;
                    }

                    for (int c = 0; c < bufferChannels; ++c)
                    {
                        int   totalMetroSamples = (int)(sampleRate * metronomeTickLength);
                        float metro             = Mathf.Sin(Mathf.PI * 2 * tickFreq * ((totalMetroSamples - metronomeSamplesLeft) / (float)totalMetroSamples) * metronomeTickLength) * 0.33f;
                        bufferData[dataIndex * bufferChannels + c] = Mathf.Clamp(bufferData[dataIndex * bufferChannels + c] + metro, -1.0f, 1.0f);
                    }
                    metronomeSamplesLeft -= 1;
                }


                if (playClickTrack && currentTick < clickTrackEndTime)
                {
                    ctx.volume        = volume;
                    ctx.index         = dataIndex;
                    ctx.playbackSpeed = 1.0f;
                    GenerateClickTrackSamples(ctx, currentTick, currentTempo, timeSignatureDuration);
                }
            }
        }
Exemplo n.º 5
0
        public static QNT_Timestamp GetSnappedValue(QNT_Timestamp time, uint beatSnap)
        {
            QNT_Duration snapValue = Constants.DurationFromBeatSnap(beatSnap);

            return((time / snapValue) * snapValue);
        }
Exemplo n.º 6
0
 public int CompareTo(QNT_Duration other)
 {
     return(tick.CompareTo(other.tick));
 }
Exemplo n.º 7
0
        public static QNT_Duration GetSnappedValue(QNT_Duration duration, uint beatSnap)
        {
            QNT_Duration snapValue = Constants.DurationFromBeatSnap(beatSnap);

            return((duration / snapValue.tick) * snapValue.tick);
        }