/// <summary> /// Recognize song in the database. /// </summary> /// <param name="songToRecognize">Preprocessed data of the song to be recognized.</param> /// <returns>Recognition result containting info about recognized song and process of recognizing. Song null and empty SongAccuracies on failure.</returns> public async Task <RecognitionResult> RecognizeSong(PreprocessedSongData songToRecognize) { string result; try { result = await PostAsync( baseUrl + "/recognition/recognizesong", JsonSerializer.Serialize(songToRecognize, serializerOptions), defaultHeaders); } catch (System.Net.Http.HttpRequestException e) { //result is null when there is no connection result = null; } if (result != null) { return(JsonSerializer.Deserialize <RecognitionResult>(result, serializerOptions)); } return(new RecognitionResult { Song = null, SongAccuracies = new List <System.Tuple <uint, double> >() }); }
/// <summary> /// Upload new song to the database. /// </summary> /// <param name="songToUpload">Preprocessed song data to be uploaded.</param> /// <returns>Uploaded song. Null on failure.</returns> public async Task <Song> UploadSong(PreprocessedSongData songToUpload) { string result; try { result = await PostAsync( baseUrl + "/recognition/addnewsong", JsonSerializer.Serialize(songToUpload, serializerOptions), defaultHeaders); } catch (System.Net.Http.HttpRequestException e) { //result is null when there is no connection result = null; } if (result != null) { return(JsonSerializer.Deserialize <Song>(result, serializerOptions)); } return(null); }
public ActionResult <Song> AddNewSong(PreprocessedSongData songToUpload) { Song newSong = new Song { Author = songToUpload.Author, Name = songToUpload.Name, Lyrics = songToUpload.Lyrics, BPM = songToUpload.BPM }; // Creaty empty SearchData data structure that will be saved into the database Dictionary <uint, List <ulong> > searchData = new Dictionary <uint, List <ulong> >(); // Save song metadata _context.Songs.Add(newSong); _context.SaveChanges(); // Get Id manually so we can use it at fingerprint creation int maxId = _context.Songs.Max(song => song.SongId); _logger.LogInformation("Addding TFPs to database"); // Conversion of maxId from int to uint is safe because SongId is always positive and smaller than max value of int _recognizer.AddFingerprintToDatabase(songToUpload.Fingerprint, Convert.ToUInt32(maxId), searchData); // Update data in database AddSearchDataToDB(searchData, newSong.BPM); _context.SaveChanges(); // Return added song return(CreatedAtAction(nameof(GetSong), new { id = newSong.Id }, newSong)); }
public async Task <ActionResult <RecognitionResult> > RecognizeSong(PreprocessedSongData songToUpload) { _logger.LogDebug("Getting correct searchdata"); Dictionary <uint, List <ulong> > searchData = GetSearchDataByBPM(songToUpload.BPM); // recognize song _logger.LogDebug("Recognizing song"); var recognitionResult = _recognizer.RecognizeSong(songToUpload.Fingerprint, searchData, songToUpload.TFPCount); // parse recognition result uint?songId = recognitionResult.Item1; List <Tuple <uint, double> > songAccuracies = recognitionResult.Item2; //find accuracy of recognition result song double maxAccuracy = GetSongAccuracy(songId, songAccuracies); // song was not found in chosen BPM sector if (songId == null) { _logger.LogDebug("Song not found by BPM"); // Iterate through all other BPM (from 60 to 180) and try to find // identify the song for (int potentialBPM = 60; potentialBPM < 180; potentialBPM += 5) { //dont search in BPM that was already searched through if (potentialBPM == songToUpload.BPM) { continue; } //get SearchData by bpm searchData = GetSearchDataByBPM(potentialBPM); var potentialRecognitionResult = _recognizer.RecognizeSong(songToUpload.Fingerprint, searchData, songToUpload.TFPCount); uint? potentialSongId = potentialRecognitionResult.Item1; double accuracy = GetSongAccuracy(potentialSongId, potentialRecognitionResult.Item2); // If result is not null and accuracy is higher than current max // remember the id and new max accuracy and accuracies of other songs if (potentialSongId != null && accuracy > maxAccuracy) { _logger.LogDebug($"New potential song id found: {potentialSongId} with proba: {accuracy} in BPM: {potentialBPM}"); songId = potentialSongId; //remember songId maxAccuracy = accuracy; //remember max accuracy songAccuracies = potentialRecognitionResult.Item2; //remember accuracies of other song in BPM batch } } } if (songId == null) { return(new RecognitionResult { Song = null, SongAccuracies = songAccuracies, }); } else { return(new RecognitionResult { // Conversion of songId from uint to int is safe, because ids are smaller than max value of int // also songId is checked to not be null Song = await _context.Songs.FindAsync((int)songId), SongAccuracies = songAccuracies, }); } }
/// <summary> /// C# side processing of uploaded or recorded audio data when recognizing song. /// </summary> /// <param name="sender"></param> /// <param name="e">Instance with audio data and process status information.</param> private async void OnSongToRecognizeEvent(object sender, string fileAsDataUrl, bool isDone) { //remove EventHandler in case this is the last iteration WasmSongEvent -= OnSongToRecognizeEvent; // Audio data is fully uploaded from javascript to C#, now recognize the song if (isDone) { // Update UI IsRecording = false; IsUploading = false; IsRecognizing = true; InformationText = "Looking for a match ..."; try { // Convert audio data from Base64 string to byteArray //string base64Data = Regex.Match(stringBuilder.ToString(), @"data:((audio)|(application))/(?<type>.+?),(?<data>.+)").Groups["data"].Value; byte[] binData = Convert.FromBase64String(stringBuilder.ToString()); //this is the data I want byte[] // Convert byte array to wav format uploadedSong = new WavFormat(binData); if (!IsSupported(uploadedSong)) { //release resources uploadedSong = null; return; } } // catch error that caused by faulty binData // ArgumentException at WavFormat(binData) // NullReferenceException at Regex.Match().Groups[]-Value catch (Exception ex) { this.Log().LogError(ex.Message); InformationText = "Error occured, please try again."; IsRecognizing = false; return; } //Debug print recorded audio properties this.Log().LogDebug("[DEBUG] Channels: " + uploadedSong.Channels); this.Log().LogDebug("[DEBUG] SampleRate: " + uploadedSong.SampleRate); this.Log().LogDebug("[DEBUG] NumOfData: " + uploadedSong.NumOfDataSamples); this.Log().LogDebug("[DEBUG] ActualNumOfData: " + uploadedSong.Data.Length); //Name, Author and Lyrics is not important for recognition call PreprocessedSongData songWavFormat = PreprocessSongData(uploadedSong); RecognitionResult result = await recognizerApi.RecognizeSong(songWavFormat); // Update UI await WriteRecognitionResults(result); IsRecognizing = false; } else { stringBuilder.Append(fileAsDataUrl); //repeat this event until e.isDone == true; WasmSongEvent += OnSongToRecognizeEvent; } }