Beispiel #1
0
 void Awake()
 {
     if (current == null)
     {
         current = this;
     }
     _beatMapExists   = true;
     _audioClipExists = true;
     _audio           = GetComponent <AudioSource>();
     if (_audio.clip == null)
     {
         _audioClipExists = false;
         Debug.LogError("Maestro: No Audio Clip!");
     }
     else
     {
         if ("BeatMap_" + _audio.clip.name.Replace(".mp3", "") != beatmapFile.name)
         {
             Debug.LogWarning("Maestro: Audio Clip and Beatmap File name mismatch!");
         }
     }
     _beatIndex = 0;
     onBeat     = OnBeat;
     lateOnBeat = LateOnBeat;
     listeners  = new List <MusicBehaviour>();
     beatmap    = BeatMapSerializer.BeatMapReader.ReadBeatMap(beatmapFile);
 }
Beispiel #2
0
        /// <summary>
        /// Writes beatmap to xml file.
        /// </summary>
        /// <param name="beats">Raw data from FFT.</param>
        /// <param name="name">Xml file name.</param>
        public static void BeatMapToFile(BeatMap beats, string name)
        {
            //BeatMap map = new BeatMap(name, beats.songLength);

            //this is a test using a dummy object
            //map.AddBeat(1, 3.0f, 5.0f);
            BeatMapSerializer.BeatMapWriter.WriteBeatMap(beats);
        }
Beispiel #3
0
            public static BeatMap ReadBeatMap(TextAsset xmlFile)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(BeatMap));
                StringReader  xml        = new StringReader(xmlFile.text);
                BeatMap       newMap     = serializer.Deserialize(xml) as BeatMap;

                return(newMap);
            }
Beispiel #4
0
            public static BeatMap ReadBeatMap(string filePath)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(BeatMap));
                FileStream    stream     = new FileStream(filePath, FileMode.Open);
                BeatMap       newMap     = (BeatMap)serializer.Deserialize(stream);

                stream.Close();
                return(newMap);
            }
Beispiel #5
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 #6
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 #7
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 #8
0
            public static void WriteBeatMap(BeatMap map)
            {
                // Check if beatmap folder exists
                if (!Directory.Exists(BeatMapSerializer.filePath))
                {
                    Directory.CreateDirectory(BeatMapSerializer.filePath);
                }

                XmlSerializer serializer = new XmlSerializer(typeof(BeatMap));
                StreamWriter  writer     = new StreamWriter(BeatMapSerializer.filePath + "/BeatMap_" + map.fileName + ".xml", false, System.Text.Encoding.UTF8);

                serializer.Serialize(writer, map);
                writer.Close();
                Debug.Log("Wrote beatmap to file");
            }
Beispiel #9
0
        /// <summary>
        /// Writes beatmap to xml file.
        /// </summary>
        /// <param name="beats">Raw data from FFT.</param>
        /// <param name="name">Xml file name.</param>
        public static void BeatMapToFile(BeatMap beats, string name)
        {
            //BeatMap map = new BeatMap(name, beats.songLength);

            //this is a test using a dummy object
            //map.AddBeat(1, 3.0f, 5.0f);
            BeatMapSerializer.BeatMapWriter.WriteBeatMap(beats);
        }
Beispiel #10
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 #11
0
 void Awake()
 {
     if (current == null) {
         current = this;
     }
     _beatMapExists = true;
     _audioClipExists = true;
     _audio = GetComponent<AudioSource>();
     if (_audio.clip == null) {
         _audioClipExists = false;
         Debug.LogError("Maestro: No Audio Clip!");
     }
     else {
         if ("BeatMap_" + _audio.clip.name.Replace(".mp3", "") != beatmapFile.name) {
             Debug.LogWarning("Maestro: Audio Clip and Beatmap File name mismatch!");
         }
     }
     _beatIndex = 0;
     onBeat = OnBeat;
     lateOnBeat = LateOnBeat;
     listeners = new List<MusicBehaviour>();
     beatmap = BeatMapSerializer.BeatMapReader.ReadBeatMap(beatmapFile);
 }
Beispiel #12
0
            public static void WriteBeatMap(BeatMap map)
            {
                // Check if beatmap folder exists
                if (!Directory.Exists(BeatMapSerializer.filePath)) {
                    Directory.CreateDirectory(BeatMapSerializer.filePath);
                }

                XmlSerializer serializer = new XmlSerializer(typeof(BeatMap));
                StreamWriter writer = new StreamWriter(BeatMapSerializer.filePath + "/BeatMap_" + map.fileName + ".xml", false, System.Text.Encoding.UTF8);
                serializer.Serialize(writer, map);
                writer.Close();
                Debug.Log("Wrote beatmap to file");
            }
        //UPDATE LOOP FOR UNITY EDITOR
        void OnGUI()
        {
            int waveformWidth = (int)(position.width - _controlsWidth);

            _controlsPos = new Rect(0, 0, _controlsWidth, 200);
            _waveformPos = new Rect(_controlsWidth, 0,
                                    waveformWidth, 300);

            HandleWindowInstantiation();    //make sure the UI exists

            _waveformMarkupWindow.Setup(_waveformPos);


            //read in xml beatmap file if it exists for the supplied audio file
            if (_analysisControlWindow.musicToAnalyze != _prevAudioClip)              //only load if new

            //ANALYZER SONG IF ONE IS ASSIGNED IN THE EDITOR GUI
            {
                if (_analysisControlWindow.musicToAnalyze != null)
                {
                    _filePath = WaveformSerializer.filePath + "/Waveform_" + _analysisControlWindow.musicToAnalyze.name + ".xml"; //location of possibly saved Wavefrom

                    if (System.IO.File.Exists(_filePath))                                                                         //retrieve the Waveform if we computed one in the past
                    {
                        Waveform newWave = WaveformSerializer.ReadWaveformData(_filePath);
                        _waveformMarkupWindow.waveform = newWave.data;
                    }
                    else
                    {
                        _waveformMarkupWindow.waveform = null;
                    }

                    _filePath = BeatMapSerializer.filePath + "/BeatMap_" + _analysisControlWindow.musicToAnalyze.name + ".xml"; // location of possibly saved Beatmap

                    if (System.IO.File.Exists(_filePath))                                                                       //load Beatmap for current song if it could be found
                    {
                        BeatMap newMap = BeatMapSerializer.BeatMapReader.ReadBeatMap(_filePath);
                        _waveformMarkupWindow.beatmap = newMap;
                    }
                    else
                    {
                        _waveformMarkupWindow.beatmap = null;
                    }
                }

                //NO SONG WAS ASSIGNED
                else
                {
                    _waveformMarkupWindow.waveform = null;
                    _waveformMarkupWindow.beatmap  = null;
                }

                _prevAudioClip = _analysisControlWindow.musicToAnalyze;                //audio clip from previous frame
            }


            //DRAW SUBWINDOWS
            HandleDrawingSubwindow(_analysisControlWindow,
                                   _waveformMarkupWindow);

            /*
             * //waveformMarkupWindow.DrawWindowDebug();//shows borders of Subwinows
             *
             * if (waveformMarkupWindow.IsInSubwindow(Event.current.mousePosition)) {//check if we can click inside a subwindow
             *  //Debug.LogFormat("waveform has it");
             * }
             */

            //USER HAS TRIGGERED ANALYSIS VIA ANALYZER CONTROLLER SUBWINDOW
            if (_analysisControlWindow.triggerAnalysis == true)
            {
                _analysisControlWindow.triggerAnalysis = false;

                //ANALYSIS
                //feed Analyzer the user-defined audio file to get audio as frequency data
                double[] waveformData = _analyzer.ProcessAudio(_analysisControlWindow.musicToAnalyze,
                                                               _analysisControlWindow.numPartitions,
                                                               _analysisControlWindow.dataAbstractionOverlapPercent);
                //feed in frequency data to get a Beatmap
                BeatMap beats = _analyzer.AnalyzeData(waveformData,
                                                      _analysisControlWindow.musicToAnalyze,
                                                      _analysisControlWindow.threshold);

                //SERIALIZATOIN
                AnalyzerTools.WaveformToFile(waveformData, _analysisControlWindow.musicToAnalyze.name);
                AnalyzerTools.BeatMapToFile(beats, _analysisControlWindow.musicToAnalyze.name);

                //DRAWING
                _waveformMarkupWindow.waveform = waveformData;
                _waveformMarkupWindow.beatmap  = beats;
            }

            Repaint();    //force GUI to draw every update even if not clicked on
        }