10 KiB
The very first object-oriented language I learned when I was 19 in my computer science & engineering program at school. I had my professor Jeff Meunier teaching us through making projects which, looking back, was the best way that he could have taught us Java to be honest. It was and still is an incredibly verbose language but at the end we made a cool project with a music beat to it. I struggled with it before but I wonder how well I would do at it now.
This was the main part of the code that I was really stoked that I figured out. Looking back i don't really know why...
public Chord(Sound[] sounds)
{ super(sounds.length);
int _subIndex = 0; f
or(int n=_subIndex ; n<sounds.length; n++)
{ SoundPlayer sp = new SoundPlayer();
this.subscribe(sp); } }
Recommended reading in the Murach book:
312, 318-321,
Steps for the old java synthesizer assignment
-
Create new project, named CSE1102-HW06-Rhythminator1
-
Create new
Main
class, with normal main method -
Create a new package called
message
.
Make a IPublisher
and ISubscriber
class/interface
- In IPublisher interface copy&paste:
public interface IPublisher
{
public void subscribe(ISubscriber subscriber);
public void unsubscribe(ISubscriber subscriber);
}
- In ISubscriber interface copy&paste:
public interface ISubscriber
{
public void notify(Message msg);
}
- Create
Broadcaster
class in the message package implementing:
public class Broadcaster implements IPublisher, ISubscriber
There will be redlines and therefore right click to automatically correct
Create a constructor:
public Broadcaster(int max_subscribers){
int [ ] array = _iSubscriberholder;
array = null;
}
Make private member variable outside of constructor at the top:
private int[ ] _iSubscriberholder
- Creating the subscribe method in the Broadcaster class
private int x = 0;
@Override
public void subscribe(ISubscriber subscriber){
[x++] = subscriber;}
-
Create the same unsubscribe method as in lab, except without body if java doesn’t already do it for you
-
copy&paste the publish method essentially and change method name to notify
-
Make comment blocks for each public method in the Broadcaster class
example:
/**
* Broadcasts a message to multiple subscribers.
*/
public class Broadcaster implements IPublisher, ISubscriber
This is the comment block for the constructor:
/**
* Creates an instance of a Broadcaster that can hold up to some number of
* subscribers.
* @param numSubscribers The maximum number of subscribers that this11
* Broadcaster can hold.
*/
public Broadcaster(int numSubscribers)
- Create a class called TestSubscriber in the message package. Copy&paste:
package message;
public class TestSubscriber implements ISubscriber
{
private String _name;
public TestSubscriber(String name)
{
_name = name;
}
@Override
public void notify(Message msg)
{
System.out.println("TestSubscriber notified, name = " + _name);
}
public static void main(String[] args)
{
Broadcaster b = new Broadcaster(4);
b.subscribe(new TestSubscriber("first"));
b.subscribe(new TestSubscriber("second"));
b.subscribe(new TestSubscriber("third"));
b.subscribe(new TestSubscriber("fourth"));
b.notify(null); // we'll use a null message for now
}
}
If you run it, it SHOULD look like this in the output:
TestSubscriber notified, name = first
TestSubscriber notified, name = second
TestSubscriber notified, name = third
TestSubscriber notified, name = fourth
- change to this for testing purposes:
Broadcaster b = new Broadcaster(4);
b.subscribe(new TestSubscriber("first"));
b.subscribe(new TestSubscriber("second"));
b.notify(null); // we'll use a null message for now
error!
to fix: don’t call notify method on null array location
-
Copy&Paste
Broadcaster
class and rename asSequencer
-
Change the
notify
method so that it looks like this:
int y = 0;
method:
public void notify(){
if(array = null){???}
create private member variable first:
furthermore fix the sequncermuch like above so that it works if any/all of array location are null
this should be the output if it works:
TestSubscriber notified, name = first
TestSubscriber notified, name = second
TestSubscriber notified, name = first
TestSubscriber notified, name = second
-
make comments for each public method
-
create a new package called model
-
Make a new class called
Clock
in model package , download class file from website and paste code into the class -
add javadoc comments like before
-
Create a
TestClock
class in the model package with main method:
code should look like this:
public static void main(String[] args)
{
Clock c = new Clock();
TestSubscriber ts = new TestSubscriber("clock tick");
c.subscribe(ts);
c.start(8);
}
output should be this (8 times, once every half second):
TestSubscriber notified, name = clock tick
replace the TestSubscriber in the main method with a Sequencer, but then put a few TestSubscriber instances in the sequencer. Have the sequencer subscribe to the clock. Run it!
output should be this:
TestSubscriber notified, name = first
TestSubscriber notified, name = second
TestSubscriber notified, name = third
TestSubscriber notified, name = fourth
TestSubscriber notified, name = first
TestSubscriber notified, name = second
TestSubscriber notified, name = third
TestSubscriber notified, name = fourth
-
Download sounds.zip file from website, make a new folder inside the project called sounds. Unzip zip file and drag and drop the sound bytes into the folder
-
Download Sound.java file and place it inside the model package
-
Create a class called
Sound
and paste this (you should hear sound after running and you can choose which sounds to put in ):
public class TestSound
{
public static void main(String[] args)
{
Sound.scanSoundDir();
Sound s1 = new Sound("DrumRhythm1");
s1.play();
}
}
-
Create a class called
SoundPlayer
-
make it implements the ISubscriber interface
-
let Eclipse create the notify method in the class
-
create a constructor with String parameter:
public Sound _name;
public SoundPlayer(String x){
_name = new Sound (x);
}
- create another constructor with Sound parameter:
pubic SoundPlayer(Sound y){
y = _name;
-
inside the notify method, play the sound?
-
Create
TestSoundPlayer
class in model package, and copy&paste this:
public static void main(String[] args)
{
Sound.scanSoundDir();
SoundPlayer drum = new SoundPlayer("KickDrum6");
SoundPlayer fizz = new SoundPlayer("Fizz");
Sequencer seq = new Sequencer(8);
seq.subscribe(drum); // step 1
seq.subscribe(drum); // step 219
seq.subscribe(fizz); // step 3
seq.subscribe(drum); // step 4
seq.subscribe(drum); // step 5
seq.subscribe(drum); // step 6
seq.subscribe(fizz); // step 7
seq.subscribe(null); // step 8 is a rest
Clock c = new Clock();
c.setDelay(250);
c.subscribe(seq);
c.start(16);
}
-
create comments for this class (SoundPlayer)
-
Create Chord class that extends Broadcaster class
-
create a constructor like this:
public Chord(Sound[ ] x){
super(sounds.length);}
Inside the Chord constructor, below that statement, do this: create a new SoundPlayer for
each of the sounds in the parameter array. Have that SoundPlayer subscribe to this
instance. lolwut?
It works like this:
for(some loop)
{
SoundPlayer sp = new SoundPlayer(___);
this.subscribe(sp);
}
- Test it in the main method now
Here's the main method:
f
You should hear all three sounds played at the same time
-
comment everything in the chord class
-
create a
SoundBank
class in the model package -
Give this class a constructor that has a Sound array parameter and stores that array in a member var iable.
Sound [ ] _soundbanks;
SoundBank(Sound[ ] y){
y = _soundbanks;}
-
?????????????????? HOW DO YOU WRITE THIS METHOD?
-
TestSoundBank
public static void main(String[] args)
{
Sound.scanSoundDir();
Sound s1 = new Sound("Glockenspiel1");
Sound s2 = new Sound("Snare1");
Sound s3 = new Sound("BassDrum1");
SoundBank sb = new SoundBank(new Sound[]{s1, s2, s3});
Chord c = sb.chord(new boolean[]{true, true, true});
c.notify(null);
}
Also make sure that this works:
Chord c = sb.chord(new int[]{0, 1, 2});
- Test this in the main class:
public static void main(String[] args)
{
Sound.scanSoundDir();
Sound s1 = new Sound("Tom1");
Sound s2 = new Sound("Fizz");
Sound s3 = new Sound("NintendoCore1");
Sound s4 = new Sound("NintendoCore2");
Sound s5 = new Sound("Snare4");
Sound s6 = new Sound("KickDrum5");
SoundBank sb = new SoundBank(new Sound[]{s1, s2, s3, s4, s5, s6});
Sequencer seq = new Sequencer(16);
seq.subscribe(sb.chord(new int[]{2, 5})); // 1
seq.subscribe(sb.chord(new int[]{5})); // 2
seq.subscribe(sb.chord(new int[]{4})); // 3
seq.subscribe(sb.chord(new int[]{1})); // 4
seq.subscribe(sb.chord(new int[]{2, 4})); // 5
seq.subscribe(sb.chord(new int[]{0})); // 6
seq.subscribe(sb.chord(new int[]{4})); // 7
seq.subscribe(sb.chord(new int[]{0, 5})); // 8
seq.subscribe(sb.chord(new int[]{3, 5})); // 9
seq.subscribe(sb.chord(new int[]{4})); // 10
seq.subscribe(sb.chord(new int[]{1})); // 11
seq.subscribe(sb.chord(new int[]{4})); // 12
seq.subscribe(sb.chord(new int[]{0, 3, 4})); // 134
seq.subscribe(sb.chord(new int[]{0})); // 14
seq.subscribe(sb.chord(new int[]{4})); // 15
seq.subscribe(sb.chord(new int[]{0, 1})); // 16
Clock c = new Clock();
c.setDelay(250);
c.subscribe(seq);
c.start(32);
}
It should work, sequence of 16 beats that repeats twice
- delete classes
Delete these classes:
• message package: TestSubscriber
• model package: TestChord, TestClock, TestSound, TestSoundBank, TestSoundPlayer