/// <summary> /// Parses the .arff file output from bextract. /// </summary> /// <param name="arffFile">Full path to .arff file to parse.</param> /// <returns>List of SongDataDTOs containing extracted features.</returns> public static List <SongDataDTO> parseArff(string arffFile) { List <SongDataDTO> result = new List <SongDataDTO>(); string arff = File.ReadAllText(arffFile); string[] tokens = arff.Split(new[] { "% filename " }, StringSplitOptions.None); //Go through each of the songs (skip the first token, that has the bextract attribute comments) for (int i = 1; i < tokens.Length; i++) { string songInfo = tokens[i]; SongDataDTO dto = parseSongInfo(songInfo); result.Add(dto); } return(result); }
/// <summary> /// Classify the given songs and output a JSON string with the results. /// </summary> /// <remarks> /// Results will be in the following format: /// /// { "ClassifierResults": /// [ { "song": /// { /// "title": "path\to\file\1.mp3", /// "energy": 0.40120655758066681, /// "positivity": 0.47041366490774172 /// } /// }, /// { "song": /// { /// "title": "path\to\file\2.mp3", /// "energy": 0.34171391252526506, /// "positivity": 0.28074189017885803 /// } /// }, /// ... /// ] /// } /// </remarks> /// /// /// <param name="songPaths">Paths to the songs to classify.</param> public string Classify(string[] songPaths) { if (posSvm == null || energySvm == null) { throw new Exception("SVMs have not yet been trained!"); } //Get features for all the songs List <SongDataDTO> songsWithFeatures = getFeatures(songPaths); //Classify each song List <ClassifierResult> classifierResults = new List <ClassifierResult>(); ConsoleManager.Show(); for (int i = 0; i < songsWithFeatures.Count; i++) { SongDataDTO songData = songsWithFeatures[i]; ClassifierResult result = new ClassifierResult(); Song song = new Song(); //song.title = songData.getFilename(); Turns the database into .wavs song.title = songPaths[i]; //Convert dto to double arrays (so svm can use them) double[] posFeatures = new double[bextractPosCols.Count()]; double[] energyFeatures = new double[bextractEnergyCols.Count()]; ConvertSongDataDtoToDoubleArrays(songData, ref posFeatures, ref energyFeatures); //Run classification song.positivity = posSvm.Score(posFeatures); song.energy = energySvm.Score(energyFeatures); result.song = song; //Fun Debugging info Console.WriteLine("Song: {0}\n Positivity: {1}\n Energy: {2} \n\n", song.title, song.positivity, song.energy); classifierResults.Add(result); } Console.WriteLine("Press Enter to continue"); Console.ReadLine(); ConsoleManager.Hide(); EmotionSpaceDTOList emotionSpaceDtoList = new EmotionSpaceDTOList(); emotionSpaceDtoList.ClassifierResults = classifierResults; return(JsonSerializer.serializeToJson(emotionSpaceDtoList)); }
public static List <SongDataDTO> parseArff(string arffFile) { List <SongDataDTO> result = new List <SongDataDTO>(); string arff = File.ReadAllText(arffFile); string[] tokens = arff.Split(new[] { "% filename " }, StringSplitOptions.None); //Go through each of the songs (skip the first token, that has the bextract attribute comments) for (int i = 1; i < tokens.Length; i++) { string token = tokens[i]; string[] lines = token.Split('\n'); string filename = lines[0].Trim(new[] { '\n', '\r' }); List <List <Double> > extractedFeatures = new List <List <Double> >(); //Line two is the sampling rate, which we do not use //Go through each of the lines of the bextract features for (int j = 2; j < lines.Length; j++) { string feature_line = lines[j]; string[] feature_strs = feature_line.Split(','); List <Double> features = new List <Double>(); //Convert each feature into a double, add to the double array //Skip the last one, it will be 'music' for (int k = 0; k < feature_strs.Length - 1; k++) { string feature_str = feature_strs[k]; Double feature = Double.Parse(feature_str); features.Add(feature); } extractedFeatures.Add(features); } SongDataDTO dto = new SongDataDTO(filename, extractedFeatures); result.Add(dto); } return(result); }
/// <summary> /// Extract the data from the SongDataDTO object and place into arrays of doubles. This is needed for training. /// </summary> /// <remarks> /// Only pulls out the bextract columns for positivity/energy. /// This function will allocate the arrays. /// </remarks> /// <param name="songData">SongDataDTO object containing the bextract data to use for training.</param> /// <param name="posFeatures">Reference to double array to store the features needed for training positivity.</param> /// <param name="energyFeatures">Reference to double array to store the features needed for training energy.</param> private void ConvertSongDataDtoToDoubleArrays(SongDataDTO songData, ref double[] posFeatures, ref double[] energyFeatures) { //Stick them in double arrays List <List <Double> > features = songData.getFeatures(); List <Double> featureList = features[0]; //Just pull the first row of features for now posFeatures = new double[bextractPosCols.Count() + 1]; energyFeatures = new double[bextractEnergyCols.Count() + 1]; //Pull out relevant bextract columns for (int i = 1; i < bextractPosCols.Count(); i++) { int col = bextractPosCols.ElementAt(i); posFeatures[i] = featureList[col]; } for (int i = 1; i < bextractEnergyCols.Count(); i++) { int col = bextractEnergyCols.ElementAt(i); energyFeatures[i] = featureList[col]; } }
/// <summary> /// Parses a song's section from the .arff file output of. /// </summary> /// <param name="songInfo">The song section of the .arff file. Between "% filename " tokens.</param> /// <returns>SongDataDTO containing extracted features</returns> private static SongDataDTO parseSongInfo(string songInfo) { string[] lines = songInfo.Split('\n'); //Line 1 is the filename string filename = lines[0].Trim(new[] { '\n', '\r' }); //Line two is the sampling rate, which we do not use //Following lines are extracted features for each sample of the song List <List <Double> > extractedFeatures = new List <List <Double> >(); for (int i = 2; i < lines.Length; i++) { string featureLine = lines[i]; List <Double> features = parseFeatureLine(featureLine); extractedFeatures.Add(features); } SongDataDTO dto = new SongDataDTO(filename, extractedFeatures); return(dto); }