// Author: Zorah Fung // Modified: Tyler Mi // Generates random music using a music grammar import java.io.*; import java.util.*; import org.jfugue.pattern.Pattern; import org.jfugue.player.Player; import org.jfugue.rhythm.Rhythm; public class MusicGenerator { public static final boolean RHYTHM = true; public static final boolean MELODY = true; public static final boolean CHORD = true; public static final String FILE_NAME = "music.txt"; public static final int REPEAT = 4; public static void main(String[] args) throws FileNotFoundException { GrammarSolver grammar = new GrammarSolver(readLines(FILE_NAME)); Player player = new Player(); Rhythm rhythm = new Rhythm(); if (RHYTHM) { buildRhythm(grammar, rhythm); } Pattern p1 = rhythm.getPattern().setVoice(0).repeat(2); String melodyPattern = ""; if (MELODY) { melodyPattern = buildPatternString(grammar, "measure"); } Pattern p2 = new Pattern(melodyPattern).setInstrument("clarinet").setVoice(1); String chordPattern = ""; if (CHORD) { chordPattern = buildPatternString(grammar, "chordmeasure"); } Pattern p3 = new Pattern(chordPattern).setInstrument("electric_piano").setVoice(2); player.play(p1, p2, p3); } // Generates the given start symbol from the given grammar REPEAT times // and combines them all in a space-delimited String that is returned private static String buildPatternString(GrammarSolver grammar, String startSymbol) { String result = ""; String[] randomPatterns = grammar.generate(startSymbol, REPEAT); for (String pattern: randomPatterns) { result += pattern + " "; } result = result.replaceAll(" - ", ""); return result; } // Uses the given grammar to build up the rhythm to have multiple layers // that are chosen at random. private static void buildRhythm(GrammarSolver grammar, Rhythm rhythm) { String[] instruments = {"bassdrum", "snare", "crash", "claps"}; for (String instr : instruments) { String layer = ""; String[] randomPatterns = grammar.generate(instr, REPEAT); for (String pattern : randomPatterns) { layer += pattern; } rhythm.addLayer(layer); } } // Reads text from the file with the given name and returns as a List. // Strips empty lines and trims leading/trailing whitespace from each line. // pre: a file with the given name exists, throws FileNotFoundException otherwise public static List readLines(String fileName) throws FileNotFoundException { List lines = new ArrayList(); Scanner input = new Scanner(new File(fileName)); while (input.hasNextLine()) { String line = input.nextLine().trim(); if (line.length() > 0) { lines.add(line); } } return lines; } }