Some functions that you may need are provided in the file Cons.java, and you will need some of your functions from the last assignment. Question 1 may be done in Java or in Lisp; the rest should be done in Java.
This function does the same thing as the earlier version of solve; in this version, use patterns to rewrite the given expression. The base cases are the same as before, and you can copy your code for those cases.
(solve '(= f (* m a)) 'f) => (= f (* m a))
(solve '(= (* m a) f) 'f) => (= f (* m a))
An initial list of patterns is provided; add patterns to complete the set.
The class should be created using new Memoizer(Functor f) where f is a functor that wraps the function associated with the memoizer.
Use a HashMap within the Memoizer to associate function values with argument values. You can Google "java hashmap" to get documentation of a HashMap.
Memoizer should have a method Object call(Object x) to perform the wrapped function call. The call method should operate as follows:
The synthesizer driver program is implemented as a discrete-event simulator, based on a PriorityQueue. You can Google "java priorityqueue" to get documentation of a PriorityQueue.
A discrete-event simulator processes a sequence of events which are scheduled at particular clock times. The PriorityQueue is used to hold the pending events, with the priority being the time at which an event is scheduled to occur. In operation, the simulator removes the highest-priority (smallest time value) event from the queue, sets the current time to the time of the event, and executes it; the event will typically perform some action, and it may schedule other events for the future. The simulation stops if the queue becomes empty.
We will assume that time values are integers. Events that occur at the same integer time are considered to be simultaneous, regardless of their order, since the computer is much faster than the music output. A time duration of 1 represents a 1/16 note duration.
An Event has a scheduled .time() and an .action(); this class is provided. An action is a list, consisting of a command followed by parameters; usually there is only one parameter, the length of time the command lasts. An event is added to the queue by the call addevent(PriorityQueue pq, Cons action, int time) .
Execution of a command may emit an I/O command to the synthesizer. Write a function execute(PriorityQueue pq, Cons act, int time) that executes an action by emitting appropriate commands.
The function emit(instrument, time, duration) sends a command to an instrument; the arguments are all int. The instrument values are as follows:
Commands are as follows, with d representing the duration of the action; usually a duration should be a power of 2, except for rest.
(seq (boom 4) (bell 4)) (seq (repeat 2 (kaboom 4)) (repeat 3 (cymbal 2))) (repeat 2 (seq (piano 0 C5 4) (piano 0 D5 4) (piano 0 E5 4)))
It will be helpful to write the totaltime() function (below) first.
The jFugue system, http://jfugue.org, allows sounds to be produced from Java. An interface has been written to allow the output of your program to produce sounds through jFugue. Your program will not be any different whether you use jFugue or not; using jFugue may make debugging easier because you can hear whether the music sounds right. If you would like to use jFugue, download it from the class directory or the jFugue site and install it in the same directory that you use for your program. Probably the easiest way to install jFugue is to download the .jar file and unpack it in the same directory with your program using
jar xf jfugue-4.0.3.jarUse the file Cons.jfugue.java and rename it to be Cons.java .