Beispiel #1
0
        /// <summary>
        /// Analyzes the song data for beat information
        /// </summary>
        /// <returns>A beatmap of the song.</returns>
        /// <param name="data">Raw data.</param>
        /// <param name="clip">Audio clip to analyze.</param>
        /// <param name="thresholdModifier">Threshold value modifier</param>
        public BeatMap AnalyzeData(double[] data, AudioClip clip, float thresholdModifier)
        {
            _beatList = new BeatMap(clip.name, clip.length);
            int numParts      = (int)clip.length;
            int partitionSize = (data.Length + 1) / numParts;

            //We only care about the magnitude of our data, so we get the absolute values before doing analysis
            data = data.ToList().Select(i => (double)Mathf.Abs((float)i)).ToArray();

            for (int i = 0; i < data.Length - (int)(partitionSize); i += (int)(partitionSize))
            {
                //finds the average value of the sub-partition starting at index i and of size partitionSize
                double avg = data.Skip(i).Take(partitionSize).Average();
                //finds the highest energy sample in the current partition
                //int largest = i;
                //calculate the average energy variance in the partition
                double variance = 0;
                for (int j = 0; j < partitionSize; j++)
                {
                    variance += (data[i + j] - avg) * (data[i + j] - avg);
                }

                variance /= partitionSize;
                //calculate the base threshold using some magic numbers and the variance
                double thresh = (-0.0025714 * variance) + 1.5142857;
                thresh *= thresholdModifier;

                //if the any sample is threshold percent larger than the average, then we mark it as a beat.
                for (int j = 0; j < partitionSize; j++)
                {
                    if (data[i + j] > thresh * avg)
                    {
                        _beatList.AddBeat(((float)(i + j) / data.Length) * clip.length, 1f, data[i + j]);
                    }
                }
            }

            //eliminate double positives (the same beat occurring in two overlapping partitions, for example) by removing beats with extremely similar timestamps
            for (int i = 0; i < _beatList.beats.Count - 1; i++)
            {
                if ((_beatList.beats[i + 1].timeStamp - _beatList.beats[i].timeStamp) < .1)
                {
                    if (_beatList.beats[i + 1].energy > _beatList.beats[i].energy)
                    {
                        _beatList.beats.RemoveAt(i);
                    }
                    else
                    {
                        _beatList.beats.RemoveAt(i + 1);
                    }
                    i--;
                }
            }
            return(_beatList);
        }
Beispiel #2
0
        /// <summary>
        /// Writes a beatmap to xml file from BPM and song length.
        /// </summary>
        /// <param name="name">Xml file name.</param>
        /// <param name="bpm">Beats per minute.</param>
        /// <param name="numBeats">Number of beats.</param>
        public static void BeatMapFromBPM(string name, float bpm, int numBeats)
        {
            float   beatStep = 60f / bpm;
            float   length   = (float)numBeats * beatStep;
            BeatMap beats    = new BeatMap(name, length);

            for (float i = 0f; i < length; i += beatStep)
            {
                beats.AddBeat(i, 1f, 1);
            }
            BeatMapSerializer.BeatMapWriter.WriteBeatMap(beats);
            Debug.LogFormat("Coda: Created beatmap {0} with BPM of {1} and running time of {2} seconds ({3} beats long).", name, bpm, length, numBeats);
        }
Beispiel #3
0
        /// <summary>
        /// Analyzes the song data for beat information
        /// </summary>
        /// <returns>A beatmap of the song.</returns>
        /// <param name="data">Raw data.</param>
        /// <param name="clip">Audio clip to analyze.</param>
        /// <param name="thresholdModifier">Threshold value modifier</param>
        public BeatMap AnalyzeData(double[] data, AudioClip clip, float thresholdModifier)
        {
            _beatList = new BeatMap(clip.name, clip.length);
            int numParts = (int)clip.length;
            int partitionSize = (data.Length+1)/numParts;

            //We only care about the magnitude of our data, so we get the absolute values before doing analysis
            data = data.ToList().Select(i => (double)Mathf.Abs((float)i)).ToArray();

            for(int i = 0; i < data.Length-(int)(partitionSize); i += (int)(partitionSize)) {
                //finds the average value of the sub-partition starting at index i and of size partitionSize
                double avg = data.Skip(i).Take(partitionSize).Average();
                //finds the highest energy sample in the current partition
                //int largest = i;
                //calculate the average energy variance in the partition
                double variance = 0;
                for(int j = 0; j < partitionSize; j++)
                {
                    variance += (data[i + j] - avg) * (data[i + j] - avg);
                }

                variance /= partitionSize;
                //calculate the base threshold using some magic numbers and the variance
                double thresh = (-0.0025714 * variance) + 1.5142857;
                thresh *= thresholdModifier;

                //if the any sample is threshold percent larger than the average, then we mark it as a beat.
                for (int j = 0; j < partitionSize; j++) {
                    if (data[i+j] > thresh * avg) {
                        _beatList.AddBeat(((float)(i + j) / data.Length) * clip.length, 1f, data[i + j]);
                    }
                }
            }

            //eliminate double positives (the same beat occurring in two overlapping partitions, for example) by removing beats with extremely similar timestamps
            for(int i = 0; i < _beatList.beats.Count-1; i++) {
                if((_beatList.beats[i+1].timeStamp - _beatList.beats[i].timeStamp) < .1) {
                    if(_beatList.beats[i + 1].energy > _beatList.beats[i].energy) {
                        _beatList.beats.RemoveAt(i);
                    }
                    else {
                        _beatList.beats.RemoveAt(i + 1);
                    }
                    i--;
                }

            }
            return _beatList;
        }
Beispiel #4
0
 /// <summary>
 /// Writes a beatmap to xml file from BPM and song length.
 /// </summary>
 /// <param name="name">Xml file name.</param>
 /// <param name="bpm">Beats per minute.</param>
 /// <param name="numBeats">Number of beats.</param>
 public static void BeatMapFromBPM(string name, float bpm, int numBeats)
 {
     float beatStep = 60f / bpm;
     float length = (float)numBeats * beatStep;
     BeatMap beats = new BeatMap(name, length);
     for (float i = 0f; i < length; i += beatStep) {
         beats.AddBeat(i, 1f, 1);
     }
     BeatMapSerializer.BeatMapWriter.WriteBeatMap(beats);
     Debug.LogFormat("Coda: Created beatmap {0} with BPM of {1} and running time of {2} seconds ({3} beats long).", name, bpm, length, numBeats);
 }