PIPES is a toolkit for creating applications that instantiate the pipeline architecture. There are four kinds of filters: transformers, testers, producers, and consumers.
In version 1.0 of PIPES filters are passive. When notified, a filter reads a single message from its input pipe, process the message, then writes the processed message to its output pipe.
The filter sub-classes (Producer, Transformer, Tester, and Consumer) are abstract. Users must extend them and provide implementations of the corresponding processing methods: produce, transform, test, and consume.
A pipe has the capacity to hold a single message. A static flag in the Pipe class determines if the pipeline should be demand-driven or data-driven.
Producers and consumers have run() methods. A run() method contains a perpetual loop that drives the pipeline until the producer runs out of data. The consumer's run method drives a demand-driven pipeline, while the producer's start method drives a data-driven pipeline.
A message is an object with three fields:
boolean quit; // tells a
demand-driven consumer that the producer has no more data
boolean fail; // indicates that a message
failed a test and should be ignored
T content; // the content of the
message, where T is a type parameter
It's important that filters not depend on each other so they can be reused in other pipelines. To make this true, use the Publisher-Subscriber design pattern.
Implement PIPES 1.0
PIPES 2.0 is similar to version 1.0 but instead the filter sub-classes are concrete. Their processing methods are fields containing lambdas. (Lambdas are function-objects introduced in Java 8.0. They are discussed here: Lambdas.) User's simply create the desired filters using factory methods that set the processor fields with the specified lambdas, then connect them with pipes.
Implement PIPES 2.0
PIPES 3.0 uses active filters. Each filter has a run method that perpetually reads messages from its input pipe, processes them, then writes the processed message to its output pipe. Instead of a single message, a pipe has a message queue. A filter must wait for data if its input pipe is empty. Pipes must be monitors with synchronized read and write operations. (See Multi Threading for some older lecture notes on synchronization. A more modern implementation might use Actors.) In this version the Publisher-Subscriber design pattern isn't needed. Filter sub-classes can be abstract as they were in version 1.0 or they can be concrete classes that use lambdas to process messages as they were in version 2.0.
Implement PIPES 3.0.
G-Band is a digital music studio that processes streams of musical notes. Each note has frequency, amplitude, and duration. (These can be floating point numbers.) GB provides the following configurable filters:
· Amplifiers: Increases or decreases the volume of each note
· Players: Play the notes through the computer's sound system.
· Noise Filters: Remove noise notes from the stream. A noise note can be a note that doesn't make sense: too loud, too quiet, too short, inaudible frequency, or a note that's suspiciously different from its predecessor (this might be static or a pop).
· Duration Filters: Remove notes that are too long or too short.
· EQ Filters: changes the amplitude of notes in a given frequency band.
· Limiters (aka Compressors): Decrease the amplitude of notes above a given amplitude threshold.
· Digital Composer: Generates a random sequence of <= 100 notes.
Use PIPES x.0 to implement and test G-Band. If you are using versions 1.0 or 2.0 test your implementations using the demand-driven and the data-driven settings.
Hint: Using the package javax.sound.midi.*, create a channel as follows:
Synthesizer synth = MidiSystem.getSynthesizer();
synth.open();
Channel channel = synth.getChannels()[0];
On my system all of the channels seem to be the same: piano.
Here's how to play a sound:
channel.noteOn( frequency, amplitude );
Thread.sleep( duration);
channel.noteOff(n.getFrequency());
Draw a class diagram showing how you would design PIPES 1.0. In a separate package show how PIPES would be customized by a user to create the G-Band application.
Assume a G-Band pipeline consists of a digital composer connected to a filter, connected to an equalizer, connected to a player. Draw two sequence diagrams showing how a note passes through this pipeline in the demand-driven mode and in the data-driven mode.
Implement the Airline Performance Analyzer using PIPES x.0.
The Sum of Squares Pipeline shows how the PIPES framework can be used.