public ChordOccurrence AddChordOccurence(ChordOccurrence chordoc) { using (var sqlCnn = new SqlConnection(ConnectionString)) { sqlCnn.Open(); using (var sqlCmd = new SqlCommand(@$ "insert into ChordOccurrences(ChordId, SongSimplificationId, StartTick, EndTick) values (@ChordId, @SongSimplificationId, @StartTick, @EndTick) SELECT SCOPE_IDENTITY();", sqlCnn)) { var chordId = new SqlParameter() { ParameterName = "@ChordId", DbType = DbType.Int64, Value = chordoc.ChordId }; sqlCmd.Parameters.Add(chordId); var songSimplificationId = new SqlParameter() { ParameterName = "@SongSimplificationId", DbType = DbType.Int64, Value = chordoc.SongSimplificationId }; sqlCmd.Parameters.Add(songSimplificationId); var startTick = new SqlParameter() { ParameterName = "@StartTick", DbType = DbType.Int64, Value = chordoc.StartTick }; sqlCmd.Parameters.Add(startTick); var endTick = new SqlParameter() { ParameterName = "@EndTick", DbType = DbType.Int64, Value = chordoc.EndTick }; sqlCmd.Parameters.Add(endTick); chordoc.Id = Convert.ToInt64(sqlCmd.ExecuteScalar()); } } return(chordoc); }
/// <summary> /// Looks for unique chords and all their occurrences in a song simplification /// The key of the dictionary returned is the chord expressed as a sequence /// of pitches separated by commas (like "40,46,54"). The pitches are sorted /// </summary> /// <param name="simpl"></param> /// <returns></returns> public static Dictionary <string, List <ChordOccurrence> > GetChordsOfSimplification(SongSimplification simpl) { var durationOfHalfBeatInTicks = 48; var retObj = new Dictionary <string, List <ChordOccurrence> >(); // We create a dictionary where the keys are points it time // one for every half beat of the song and the values are the notes // played in that half beat // The assumption is that we don't have more than 2 chords in 1 beat // Since a note can last several beats, the same note and // the same chord can be in many entries // of the dictionary var beatNotes = new Dictionary <long, List <Note> >(); foreach (Note n in simpl.Notes) { if (n.IsPercussion) { continue; } var startBeat = n.StartSinceBeginningOfSongInTicks / durationOfHalfBeatInTicks; var endBeat = n.EndSinceBeginningOfSongInTicks / durationOfHalfBeatInTicks; for (var i = startBeat; i <= endBeat; i++) { if (!beatNotes.ContainsKey(i)) { beatNotes[i] = new List <Note>(); } beatNotes[i].Add(n); } } // Now we look at the notes played in each half beat. // We group the notes according to their start and stop times // The notes that start and stop simultatneously are // candidates for a chord foreach (var slice in beatNotes.Keys) { var sliceNotes = beatNotes[slice]; if (sliceNotes.Count < 2) { continue; } var possibleChords = new List <List <Note> >(); foreach (var n in sliceNotes) { var isNoteProcessed = false; foreach (var possibleChord in possibleChords) { if (IsNoteSimultaneousWithGroup(possibleChord, n)) { possibleChord.Add(n); isNoteProcessed = true; } } if (!isNoteProcessed) { var possibleChord = new List <Note>(); possibleChord.Add(n); possibleChords.Add(possibleChord); } } // We have now in possibleChords a list of groups of notes // We select the ones that have at least 2 notes if (possibleChords.Count > 0) { foreach (var possibleChord in possibleChords) { if (possibleChord.Count < 2 || !NotesGenerateHarmony(possibleChord)) { continue; } var thisChord = new Chord(possibleChord); if (!retObj.ContainsKey(thisChord.PitchesAsString)) { retObj[thisChord.PitchesAsString] = new List <ChordOccurrence>(); } var chordOccurrence = new ChordOccurrence { StartTick = possibleChord.FirstOrDefault().StartSinceBeginningOfSongInTicks, EndTick = possibleChord.FirstOrDefault().EndSinceBeginningOfSongInTicks, SongSimplificationId = simpl.Id }; if (!IsOccurrenceAlreadyInList(retObj[thisChord.PitchesAsString], chordOccurrence)) { retObj[thisChord.PitchesAsString].Add(chordOccurrence); } } } } return(retObj); }
private static bool IsOccurrenceAlreadyInList(List <ChordOccurrence> list, ChordOccurrence co) { return(list .Where(x => x.StartTick == co.StartTick && x.EndTick == co.EndTick) .Count() > 0); }