void TryAddClickEvent(QNT_Timestamp current, QNT_Timestamp beat, ClipData clip)
        {
            if (current == beat)
            {
                bool addedSound = false;
                foreach (ClickTrackEvent ev in clickTrackEvents)
                {
                    if (ev.time == current)
                    {
                        addedSound = true;
                        break;
                    }
                }

                if (!addedSound)
                {
                    ClickTrackEvent ev;
                    ev.clip          = clip;
                    ev.currentSample = 0;
                    ev.time          = current;
                    clickTrackEvents.Add(ev);
                }
            }
        }
        IEnumerator LoadHitsounds()
        {
            while (KickClip.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (SnareClip.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (PercussionClip.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (ChainStartClip.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (ChainNoteClip.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (MeleeClip.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (MineClip.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }

            while (HiHat_Hit.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (HiHat_Hit2.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (HiHat_Open.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }
            while (HiHat_Hit3.loadState != AudioDataLoadState.Loaded)
            {
                yield return(null);
            }

            kick       = FromAudioClip(KickClip);
            snare      = FromAudioClip(SnareClip);
            percussion = FromAudioClip(PercussionClip);
            chainStart = FromAudioClip(ChainStartClip);
            chainNote  = FromAudioClip(ChainNoteClip);
            melee      = FromAudioClip(MeleeClip);
            mine       = FromAudioClip(MineClip);

            hihat_hit  = FromAudioClip(HiHat_Hit);
            hihat_hit2 = FromAudioClip(HiHat_Hit2);
            hihat_hit3 = FromAudioClip(HiHat_Hit3);
            hihat_open = FromAudioClip(HiHat_Open);
        }
Exemple #3
0
        public static List <float> Detect(ClipData src, Timeline timeline, QNT_Timestamp start, QNT_Timestamp end)
        {
            for (int i = 0; i < bpmMatchDatas.Length; i++)
            {
                bpmMatchDatas[i].match = 0f;
            }

            if (start == end)
            {
                return(new List <float>());
            }

            if (end < start)
            {
                QNT_Timestamp temp = start;
                start = end;
                end   = temp;
            }

            float startTime = timeline.TimestampToSeconds(start);
            float endTime   = timeline.TimestampToSeconds(end);

            int  channels   = src.channels;
            int  frequency  = src.frequency;
            uint numSamples = (uint)(frequency * (endTime - startTime) * channels);

            int splitFrameSize = BASE_SPLIT_SAMPLE_SIZE;

            var volumeArr  = new float[Mathf.CeilToInt((float)src.samples.Length / (float)splitFrameSize)];
            int powerIndex = 0;

            // Sample data analysis start
            for (int sampleIndex = 0; sampleIndex < src.samples.Length; sampleIndex += splitFrameSize)
            {
                float sum = 0f;
                for (int frameIndex = sampleIndex; frameIndex < sampleIndex + splitFrameSize; frameIndex++)
                {
                    if (src.samples.Length <= frameIndex)
                    {
                        break;
                    }
                    // Use the absolute value, because left and right value is -1 to 1
                    float absValue = Mathf.Abs(src.samples[frameIndex]);
                    if (absValue > 1f)
                    {
                        continue;
                    }

                    // Calculate the amplitude square sum
                    sum += (absValue * absValue);
                }

                // Set volume value
                volumeArr[powerIndex] = Mathf.Sqrt(sum / splitFrameSize);
                powerIndex++;
            }

            // Representing a volume value from 0 to 1
            float maxVolume = volumeArr.Max();

            for (int i = 0; i < volumeArr.Length; i++)
            {
                volumeArr[i] = volumeArr[i] / maxVolume;
            }

            // Create volume diff list
            var diffList = new List <float>();

            for (int i = 1; i < volumeArr.Length; i++)
            {
                diffList.Add(Mathf.Max(volumeArr[i] - volumeArr[i - 1], 0f));
            }

            // Calculate the degree of coincidence in each BPM
            int   index          = 0;
            float splitFrequency = (float)frequency / (float)splitFrameSize;

            for (int bpm = MIN_BPM; bpm <= MAX_BPM; bpm++)
            {
                float sinMatch = 0f;
                float cosMatch = 0f;
                float bps      = (float)bpm / 60f;

                if (diffList.Count > 0)
                {
                    for (int i = 0; i < diffList.Count; i++)
                    {
                        sinMatch += (diffList[i] * Mathf.Cos(i * 2f * Mathf.PI * bps / splitFrequency));
                        cosMatch += (diffList[i] * Mathf.Sin(i * 2f * Mathf.PI * bps / splitFrequency));
                    }

                    sinMatch *= (1f / (float)diffList.Count);
                    cosMatch *= (1f / (float)diffList.Count);
                }

                float match = Mathf.Sqrt((sinMatch * sinMatch) + (cosMatch * cosMatch));

                bpmMatchDatas[index].bpm   = bpm;
                bpmMatchDatas[index].match = match;
                index++;
            }

            // Returns a high degree of coincidence BPM
            int          matchIndex = Array.FindIndex(bpmMatchDatas, x => x.match == bpmMatchDatas.Max(y => y.match));
            var          sort       = bpmMatchDatas.OrderBy(x => x.match).Reverse().ToList();
            List <float> results    = new List <float>();

            for (int i = 0; i < 10; ++i)
            {
                results.Add(sort[i].bpm);
            }

            return(results);
        }