public static HierarchicalRhythm CreateHierarchicalRhythm(RhythmStructure rhythm) { RhythmStructure rhythmCopy = new RhythmStructure(rhythm); int treeDepth = (int)Math.Log(rhythm.drums.Count, 2); HierarchicalRhythm hRhythm = new HierarchicalRhythm(rhythm.beatInterval, treeDepth); foreach (Drum drum in drumList) { /* Tree level 0 is the root, for drums that occur on every semiquaver of the rhythm, * and the bottom level is the notes that occur only once across the rhythm. */ for (int level = 0; level <= treeDepth; level++) { int intervalBetweenNotes = (int)Math.Pow(2, level); /* This index is the amount that the recurring note is "shifted" across the rhythm. * For example, if we're at minim level, then at i=3 we have notes occuring every minim, * starting on the semiquaver with index 3. */ for (int shift = 0; shift < intervalBetweenNotes; shift++) { /* If the particular drum we're looking at is found in the rhythm, * at the location we're dealing with, start scanning along. */ if (rhythmCopy.GetAtIndex(shift).Contains(drum)) { /* Finally, iterate across the entire rhythm according to the shift and interval. * TODO: This isn't very efficient, would be better to stop immediately if there's a mismatch. */ bool notesLineUp = true; for (int i = shift; i < rhythmCopy.drums.Count; i += intervalBetweenNotes) { if (!rhythmCopy.GetAtIndex(i).Contains(drum)) { notesLineUp = false; } } if (notesLineUp) { hRhythm.AddDrum(level, shift, drum); for (int i = shift; i < rhythmCopy.drums.Count; i += intervalBetweenNotes) { rhythmCopy.RemoveDrumAt(i, drum); } } } } } } return(hRhythm); }
static void Main(string[] args) { bool edit_only = false; bool find_hierarchy = true; if (!edit_only) { MidiReader reader = new MidiReader(); Console.WriteLine("Ready to record. Press any key to begin."); Console.ReadKey(); reader.Start(); Console.WriteLine("Recording started. Press any key to stop the recording."); Console.ReadKey(); reader.Stop(); Console.WriteLine("Recording finished. Processing..."); List <BeatEvent> beatEvents = TempoInferrer.NotesToEvents(reader.FetchEventList()); List <IntervalCluster> intervalClusters = TempoInferrer.EventsToClusters(beatEvents); intervalClusters = TempoInferrer.RateClusters(intervalClusters); BeatTracker finalBeat = BeatInferrer.FindBeat(intervalClusters, beatEvents); RhythmStructure rhythm = RhythmCreator.CreateRhythm(finalBeat, beatEvents); if (find_hierarchy) { rhythm = HierarchicalRhythmInferrer.FindRepeatingUnit(rhythm); } AsciiTabRenderer.RenderAsciiTab(rhythm); Console.WriteLine("ASCII Tab rendered to tab.txt."); if (find_hierarchy) { HierarchicalRhythm hRhythm = HierarchicalRhythmInferrer.CreateHierarchicalRhythm(rhythm); hRhythm.Print(); } } /* Read in (possibly edited) ASCII tab and convert to Sonic Pi */ SonicPiEmitter.EmitSonicPi(); Console.WriteLine("Sonic Pi code emitted to sonicpi.txt"); Console.ReadKey(); }