Presentation is loading. Please wait.

Presentation is loading. Please wait.

CS1316: Representing Structure and Behavior

Similar presentations


Presentation on theme: "CS1316: Representing Structure and Behavior"— Presentation transcript:

1 CS1316: Representing Structure and Behavior
Structuring Sounds CS1316: Representing Structure and Behavior

2 Story Structuring sounds into songs (? Collections?)
Version 1: Representing linearity through elements order. Repeating and weaving with sounds Finding and replacing sounds in a list How do trace and debug what we’re doing with sounds and lists? Structuring sounds into songs Version 2: Creating trees of sounds. Traversing in a tree Pre-order and post-order

3 SoundElement: Creating a linked list of sounds
/** * Sounds for a linked list **/ public class SoundElement { * The sound this element is associated with Sound mySound; * The next element to process public SoundElement next;

4 Constructing an element
/** * Constructor sets next to null * and references the input sound. **/ public SoundElement(Sound aSound){ next = null; mySound = aSound; }

5 Linked List blah-blah-blah
/** * Methods to set and get next elements nextOne next element in list **/ public void setNext(SoundElement nextOne){ this.next = nextOne; } public SoundElement getNext(){ return this.next; We’ve seen this HOW MANY times?

6 Methods for Playing /** * Play the list of sound elements * after me
**/ public void playFromMeOn(){ this.collect().play(); } * Collect all the sounds from me on, * recursively. public Sound collect(){ if (this.getNext() == null) {return mySound;} else {return mySound.append(this.getNext().collect());}

7 Starting to explore > Sound s = new Sound("D:/cs1316/mediasources/shh-a-h.wav"); > Sound t = new Sound("D:/cs1316/mediasources/croak-h.wav"); > Sound u = new Sound("D:/cs1316/mediasources/clap-q.wav"); > SoundElement e1 = new SoundElement(s); > SoundElement e2 = new SoundElement(t); > SoundElement e3 = new SoundElement(u); > e1.playFromMeOn(); > e1 SoundElement with sound: Sound file: D:/cs1316/mediasources/shh-a-h.wav number of samples: (and next: null).

8 How did that happen? How were we able to get that string from typing in e1? By defining the method toString() on a class, we can define how it should appear. VERY useful in debugging!

9 toString() for SoundElement
/** * Provide a printable representation of me **/ public String toString(){ return "SoundElement with sound: "+mySound+" (and next: "+next+")."; }

10 Growing the list > e1.setNext(e2) > e1
SoundElement with sound: Sound file: D:/cs1316/mediasources/shh-a-h.wav number of samples: (and next: SoundElement with sound: Sound file: D:/cs1316/mediasources/croak-h.wav number of samples: 8808 (and next: null).). > e2.setNext(e3) SoundElement with sound: Sound file: D:/cs1316/mediasources/shh-a-h.wav number of samples: (and next: SoundElement with sound: Sound file: D:/cs1316/mediasources/croak-h.wav number of samples: 8808 (and next: SoundElement with sound: Sound file: D:/cs1316/mediasources/clap-q.wav number of samples: 4584 (and next: null).).). Where’s all that coming from?!? When we add in next to our toString(), it calls next’s toString()

11 e1.playFromMeOn() public void playFromMeOn(){ this.collect().play(); }
mySound: shh-a-h.wav next: mySound: croak-h.wav next: mySound: clap-q.wav next: null

12 public Sound collect(){ if (this.getNext() == null) {return mySound;}
mySound: shh-a-h.wav next: mySound: croak-h.wav next: mySound: clap-q.wav next:null this

13 else {return mySound.append(this.getNext().collect());}
mySound: shh-a-h.wav next: mySound: croak-h.wav next: mySound: clap-q.wav next:null We “freeze” this call to e1.collect() this

14 public Sound collect(){ if (this.getNext() == null) {return mySound;}
mySound: croak-h.wav next: mySound: clap-q.wav next:null Where’s e1? What e1? From e2’s view, there is no e1 this

15 else {return mySound.append(this.getNext().collect());}
mySound: croak-h.wav next: mySound: clap-q.wav next:null We “freeze” this call to e2.collect() this

16 public Sound collect(){ if (this.getNext() == null) {return mySound;}
mySound: clap-q.wav next:null We return clap-q.wav this

17 else {return mySound.append(this.getNext().collect());}
Back in e2.collect(), We return croak-h.wav appended with clap-q.wav mySound: croak-h.wav next: mySound: clap-q.wav next:null this

18 else {return mySound.append(this.getNext().collect());}
Back in e2.collect(), We return shh-a-h.wav appended with croak-h.wav appended with clap-q.wav mySound: shh-a-h.wav next: mySound: croak-h.wav next: mySound: clap-q.wav next:null this

19 e1.playFromMeOn() public void playFromMeOn(){ this.collect().play(); }
Now we play shh-a-h.wav appended with croak-h.wav appended with clap-q.wav mySound: shh-a-h.wav next: mySound: croak-h.wav next: mySound: clap-q.wav next: null

20 Testing Sound Lists public class SoundListTest { SoundElement root;
public SoundElement root(){ return root;} public void setUp(){ FileChooser.setMediaPath("D:/cs1316/MediaSources/"); Sound s = new Sound(FileChooser.getMediaPath( "scratch-h.wav")); root = new SoundElement(s); s = new Sound(FileChooser.getMediaPath( "gonga-2.wav")); SoundElement one = new SoundElement(s); root.repeatNext(one,10); s = new Sound(FileChooser.getMediaPath( "scritch-q.wav")); SoundElement two = new SoundElement(s); root.weave(two,3,3); s = new Sound(FileChooser.getMediaPath( "clap-q.wav")); SoundElement three = new SoundElement(s); root.weave(three,5,2); root.playFromMeOn(); } Testing Sound Lists

21 /** * Repeat the input phrase for the number of times specified. * It always appends to the current node, NOT insert. nextOne node to be copied in to list count number of times to copy it in. */ public void repeatNext(SoundElement nextOne,int count) { SoundElement current = this; // Start from here SoundElement copy; // Where we keep the current copy for (int i=1; i <= count; i++) { copy = nextOne.copyNode(); // Make a copy current.setNext(copy); // Set as next current = copy; // Now append to copy } Repeating Shockingly similar to what we saw before! We saw this before when we were doing Song nodes – shockingly similar code!

22 Copying by filename /** * copyNode returns a copy of this element
another element with the same sound */ public SoundElement copyNode(){ Sound copySound; if (this.mySound.getFileName() == null) {copySound = this.mySound.scale(1.0);} // Does nothing -- copies else {copySound = new Sound(this.mySound.getFileName());} // Copy from file SoundElement returnMe = new SoundElement(copySound); return returnMe; } How to copy a sound? If we have a filename, go get the file again. If not, just scale it by 1.0 (which copies as-is)

23 Weaving Again, shockingly similar to what we saw before! /**
* Weave the input sound count times every skipAmount elements nextOne SoundElement to be copied into the list count how many times to copy skipAmount how many nodes to skip per weave */ public void weave(SoundElement nextOne, int count, int skipAmount) { SoundElement current = this; // Start from here SoundElement copy; // Where we keep the one to be weaved in SoundElement oldNext; // Need this to insert properly int skipped; // Number skipped currently for (int i=1; i <= count; i++) copy = nextOne.copyNode(); // Make a copy //Skip skipAmount nodes skipped = 1; while ((current.getNext() != null) && (skipped < skipAmount)) current = current.getNext(); skipped++; }; if (current.getNext() == null) // Did we actually get to the end early? break; // Leave the loop oldNext = current.getNext(); // Save its next current.insertAfter(copy); // Insert the copy after this one current = oldNext; // Continue on with the rest } Weaving Again, shockingly similar to what we saw before!

24 What? You don’t like gongs?
So, what happens when you have umpteen copies of gong, but you don’t like gongs? Yes, we can remake the list, but what if you couldn’t?

25 Degong-ing the SoundListTest
public void degong(){ Sound gong = new Sound(FileChooser.getMediaPath( "gonga-2.wav")); Sound snap = new Sound(FileChooser.getMediaPath( "snap-tenth.wav")); root.replace(gong,snap); }

26 Replacing one sound by another in the list (recursively)
/** * Replace the one sound with the other sound * in all the elements from me on. * Decide two sounds are equal if come from same filename oldSound sound to be replaced newSOund sound to put in its place **/ public void replace(Sound oldSound, Sound newSound){ if (mySound.getFileName() != null) {if (mySound.getFileName().equals(oldSound.getFileName())) {mySound = newSound;}} if (next != null) {next.replace(oldSound,newSound);} }

27 Imagine: e1.replace(croak,clap)
mySound: shh-a-h.wav next: mySound: croak-h.wav next: mySound: clap-q.wav next: null

28 e1 e2 e3 mySound: shh-a-h.wav next: mySound: croak-h.wav next:
public void replace(Sound oldSound, Sound newSound){ if (mySound.getFileName() != null) {if (mySound.getFileName().equals(oldSound.getFileName())) {mySound = newSound;}} e1 e2 e3 mySound: shh-a-h.wav next: mySound: croak-h.wav next: mySound: clap-q.wav next: null this

29 if (next != null) {next.replace(oldSound,newSound);}
mySound: shh-a-h.wav next: mySound: croak-h.wav next: mySound: clap-q.wav next: null this

30 e2 e3 This is a match! mySound: croak-h.wav clap-q.wav next:
public void replace(Sound oldSound, Sound newSound){ if (mySound.getFileName() != null) {if (mySound.getFileName().equals(oldSound.getFileName())) {mySound = newSound;}} e2 e3 This is a match! mySound: croak-h.wav clap-q.wav next: mySound: clap-q.wav next: null this

31 if (next != null) {next.replace(oldSound,newSound);}
mySound: croak-h.wav clap-q.wav next: mySound: clap-q.wav next: null this

32 e3 mySound: clap-q.wav next: null this
public void replace(Sound oldSound, Sound newSound){ if (mySound.getFileName() != null) {if (mySound.getFileName().equals(oldSound.getFileName())) {mySound = newSound;}} e3 mySound: clap-q.wav next: null this

33 if (next != null) {next.replace(oldSound,newSound);}
And we’re done! We do return all the way back up again, but there’s nothing else to be done. mySound: clap-q.wav next: null this

34 Tracing what’s happening
Use “Debug Mode” from Debugger menu Type in variable names to trace. Set Breakpoints (Control-B) on the lines you want to stop in. Step over—skips to the next line Step in—skips in to that method call Resume—go to the next breakpoint Demo all of these things, please!

35

36 Version 2: When lists aren’t good enough
Do we think about music as a linear list of sounds? That is how we experience it. Or do we tend to cluster the sounds? Verse, chorus, verse? This motif, that motif, this motif? And what about this cool idea of embedding operations into the data structure?

37 Creating a tree of sounds
SoundBranch SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest children next

38 Creating and playing our tree of sounds
Welcome to DrJava. > SoundTreeExample tree = new SoundTreeExample(); tree.setUp(); > tree.play() > tree.playScaled(2.0); > tree.play(); We should actually do these. Note that once the scaleBranch stays changed in the second play()

39 SoundTreeExample public class SoundTreeExample {
ScaleBranch scaledBranch; // Needed between methods SoundBranch root; public SoundBranch root() {return root;}

40 Setting up the basic sounds
public void setUp() { FileChooser.setMediaPath("D:/cs1316/MediaSources/"); Sound clap = new Sound(FileChooser.getMediaPath("clap-q.wav")); Sound chirp = new Sound(FileChooser.getMediaPath("chirp-2.wav")); Sound rest = new Sound(FileChooser.getMediaPath("rest-1.wav")); Sound snap = new Sound(FileChooser.getMediaPath("snap-tenth.wav")); Sound clink = new Sound(FileChooser.getMediaPath("clink-tenth.wav")); Sound clave = new Sound(FileChooser.getMediaPath("clave-twentieth.wav")); Sound gong = new Sound(FileChooser.getMediaPath("gongb-2.wav"));

41 Build the root and first branch
root = new SoundBranch(); SoundNode sn; SoundBranch branch1 = new SoundBranch(); sn = new SoundNode(clap.append(rest).append(snap)); branch1.addChild(sn); sn = new SoundNode(rest.append(snap).append(rest));

42 A ScaleBranch and last Branch
scaledBranch = new ScaleBranch(1.0); sn = new SoundNode(clink.append(clave).append(gong)); scaledBranch.addChild(sn); sn = new SoundNode(rest.append(chirp).append(clap)); SoundBranch branch2 = new SoundBranch(); sn = new SoundNode(clap.append(snap).append(snap)); branch2.addChild(sn); sn = new SoundNode(rest.append(snap).append(clap));

43 Building the whole tree
root.addChild(branch1); root.addChild(scaledBranch); root.addChild(branch2); }

44 Playing the tree, and changing the scale
public void play(){ root.playFromMeOn(); } public void playScaled(double factor){ scaledBranch.setFactor(factor);

45 What a tree “looks like” (printed, e.g., toString())
> tree.root() SoundBranch (with child: SoundBranch (with child: SoundNode (with sound: Sound number of samples: and next: SoundNode (with sound: Sound number of samples: and next: null and next: ScaleBranch (1.0) SoundBranch (with child: SoundNode (with sound: Sound number of samples: and next: SoundNode (with sound: Sound number of samples: and next: null and next: SoundBranch (with child: SoundNode (with sound: Sound number of samples: 8452 and next: SoundNode (with sound: Sound number of samples: and next: null and next: No next))) and next: No next) Obviously, this doesn’t help us much, but the root() does

46 Going deeper: How’d we do that?
How we build a tree of sounds is very much like a tree of pictures. Set up a general node abstract class that all other nodes inherit from. Create a leaf node that will store our data of interest (sounds). Create a branch node that will store collections of leaves and references to other branches. Create (as we wish) branch nodes with operations that do things to the children of this branch.

47 Our SoundTree Class Structure
abstract CollectableNode Knows next Knows How to do basic list operations, and defines abstract sound operations (can collect() its sound(s)) The subclasses extend CollectableNode SoundBranch Knows children Knows How add children, and collect all the sounds from its children and next SoundNode Knows mySound Knows How collect itself and its next

48 Our SoundTree Class Structure (a little further)
abstract CollectableNode Knows next Knows How to do basic list operations, and collect() SoundBranch Knows children Knows How add children, and collect() SoundNode Knows mySound Knows How collect() ScaleBranch Knows a scaling factor Knows How to access scaling factor, and to collect from children then scale the resultant sound

49 CollectableNode /** * Stuff that all nodes and branches in the
* sound tree know. **/ abstract public class CollectableNode { * The next branch/node/whatever to process public CollectableNode next; * Constructor for CollectableNode just sets * next to null public CollectableNode(){ next = null; }

50 CollectableNode’s know about linked lists
/** * Methods to set and get next elements nextOne next element in list **/ public void setNext(CollectableNode nextOne){ this.next = nextOne; } public CollectableNode getNext(){ return this.next; The rest of it is there, too: add(), last(), insertAfter(), remove()… But you’ve seen that all before.

51 CollectableNodes know only a little about sound
/** * Play the list of sound elements * after me **/ public void playFromMeOn(){ this.collect().play(); } * Collect all the sounds from me on abstract public Sound collect(); * Collect all the sounds from me on, * but if there's processing, do it after. abstract public Sound collectAfter(); This is an important point to make for NEXT week, when we do generalized forms of lists and trees. We can really build these things without being specific to pictures and sounds. Comes later.

52 SoundNodes know sounds
/* * SoundNode is a class representing a drawn picture * node in a scene tree. **/ public class SoundNode extends CollectableNode { /** * The sound I'm associated with Sound mySound; * Make me with this sound sound the Sound I'm associated with public SoundNode(Sound sound){ super(); // Call superclass constructor mySound = sound; }

53 What happens if you print a SoundNode
/** * Method to return a string with informaiton * about this node */ public String toString() { return "SoundNode (with sound: "+mySound+" and next: "+next; }

54 How SoundNodes collect their sounds
/** * Collect all the sounds from me on, * recursively. **/ public Sound collect(){ if (this.getNext() == null) {return mySound;} else {return mySound.append(this.getNext().collect());} } “Hang on, how does that work?!?” Wait until we see the rest, then we’ll trace it.

55 SoundBranches know about children
public class SoundBranch extends CollectableNode { /* * A list of children to draw */ public CollectableNode children; * Construct a branch with children and * next as null **/ public SoundBranch(){ super(); // Call superclass constructor children = null; } Notice: Children could be SoundNodes or other branches—any kind of CollectableNode

56 SoundBranches know about children (contd.)
/** * Method to add nodes to children **/ public void addChild(CollectableNode child){ if (children != null) {children.add(child);} else {children = child;} }

57 How SoundBranches print
/** * Method to return a string with informaiton * about this branch */ public String toString() { String childString = "No children", nextString="No next"; if (children != null) {childString = children.toString();} if (next != null) {nextString = next.toString();} return "SoundBranch (with child: "+childString+" and next: "+ nextString+")"; }

58 Collecting sounds from SoundBranches
/** * Collect all the sound from our children, * then collect from next. pen Turtle to draw with **/ public Sound collect(){ Sound childSound; if (children != null) {childSound = children.collect();} else {childSound = new Sound(1);} // Collect from my next if (this.getNext() != null) {childSound=childSound.append(this.getNext().collect());} return childSound; } This collects from the children (or creates a default sound), then from the next’s, and returns them all together

59 ScaleBranches know about scaling (and a factor)
public class ScaleBranch extends SoundBranch { /** Amount to scale **/ double factor; /** * Construct a branch with this factor **/ public ScaleBranch(double nufactor){ super(); // Call superclass constructor this.factor = nufactor; } /** Accessors **/ public double getFactor() {return this.factor;} public void setFactor(double nufactor) {this.factor = nufactor;}

60 Scaling the children in a ScaleBranch
/** * Collect all the sound from our children, * then collect from next. Scale the children pen Turtle to draw with **/ public Sound collect(){ Sound childSound; if (children != null) {childSound = children.collect().scale(factor);} else {childSound = new Sound(1);} // Collect from my next if (this.getNext() != null) {Sound nextSound=this.getNext().collect(); childSound = childSound.append(nextSound);} return childSound; }

61 Printing a ScaleBranch
/** * Method to return a string with informaiton * about this branch */ public String toString() { return "ScaleBranch ("+factor+") "+super.toString(); }

62 Walking the data structure: At the root
> tree.root() SoundBranch (with child: SoundBranch (with child: SoundNode (with sound: Sound number of samples: and next: SoundNode (with sound: Sound number of samples: and next: null and next: ScaleBranch (1.0) SoundBranch (with child: SoundNode (with sound: Sound number of samples: and next: SoundNode (with sound: Sound number of samples: and next: null and next: SoundBranch (with child: SoundNode (with sound: Sound number of samples: 8452 and next: SoundNode (with sound: Sound number of samples: and next: null and next: No next))) and next: No next)

63 Down the children’s next path
> tree.root().children SoundBranch (with child: SoundNode (with sound: Sound number of samples: and next: SoundNode (with sound: Sound number of samples: and next: null and next: ScaleBranch (1.0) SoundBranch (with child: SoundNode (with sound: Sound number of samples: and next: SoundNode (with sound: Sound number of samples: and next: null and next: SoundBranch (with child: SoundNode (with sound: Sound number of samples: 8452 and next: SoundNode (with sound: Sound number of samples: and next: null and next: No next))) > tree.root().children.getNext() ScaleBranch (1.0) SoundBranch (with child: SoundNode (with sound: Sound number of samples: and next: SoundNode (with sound: Sound number of samples: and next: null and next: SoundBranch (with child: SoundNode (with sound: Sound number of samples: 8452 and next: SoundNode (with sound: Sound number of samples: and next: null and next: No next)) > tree.root().children.getNext().getNext() SoundBranch (with child: SoundNode (with sound: Sound number of samples: 8452 and next: SoundNode (with sound: Sound number of samples: and next: null and next: No next) > tree.root().children.getNext().getNext().getNext() null

64 Tracing a tree traversal
Welcome to DrJava. > SoundTreeExample tree = new SoundTreeExample(); tree.setUp(); > tree.root().collect().play() This code: Creates a tree object. Fills it up. Then gets the root, collects the sound from the whole tree (traverses the tree), then plays the collected sound.

65 Tracing the traversal: tree.root().collect().play
SoundBranch tree.root() SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest children next

66 SoundBranch this SoundBranch ScaleBranch SoundBranch Clap, rest, snap
public Sound collect(){ Sound childSound; if (children != null) {childSound = children.collect();} else {childSound = new Sound(1);} SoundBranch this SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest Yes, the root has children, so we ask the first of our children to collect()

67 The call to root().collect() is now paused…
public Sound collect(){ Sound childSound; if (children != null) {childSound = children.collect();} else {childSound = new Sound(1);} SoundBranch SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong this Rest, snap, clap Rest, chirp, clap Rest, snap, rest Yes, we’re in the same method, but now with a new this. It’s really a new call. The call to root().collect() is now paused…

68 Now, we’re in SoundNode’s collect()
public Sound collect(){ if (this.getNext() == null) {return mySound;} else {return mySound.append(this.getNext().collect());} } Now, we’re in SoundNode’s collect() SoundBranch SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap this Rest, chirp, clap Rest, snap, rest The call to root().children.collect() is now paused… We have a next, so we collect from there, too.

69 We’re in SoundNode’s collect(), with a new SoundNode
public Sound collect(){ if (this.getNext() == null) {return mySound;} else {return mySound.append(this.getNext().collect());} } We’re in SoundNode’s collect(), with a new SoundNode SoundBranch SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap this Rest, snap, rest The call to root().children.children.collect() is now paused… We have no next here, so we return “Rest,snap, rest”

70 We’re back in SoundNode’s collect()
public Sound collect(){ if (this.getNext() == null) {return mySound;} else {return mySound.append(this.getNext().collect());} } We’re back in SoundNode’s collect() SoundBranch SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap this Rest, chirp, clap Rest, snap, rest We now return “Clap, rest, snap” appended with “Rest, snap, rest”

71 We’re now in the second half of SoundBranch’s collect()
// Collect from my next if (this.getNext() != null) {Sound nextSound=this.getNext().collect(); childSound = childSound.append(nextSound);} return childSound; } We’re now in the second half of SoundBranch’s collect() SoundBranch SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong this Rest, snap, clap Rest, chirp, clap Rest, snap, rest We have a next, so we move on to call collect() on that.

72 Now we’re in ScaleBranch’s collect()
public Sound collect(){ Sound childSound; if (children != null) {childSound = children.collect().scale(factor);} else {childSound = new Sound(1);} Now we’re in ScaleBranch’s collect() SoundBranch this SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest Let’s skip the path down the children. childSound will become “Clink,clave,gong,rest,chirp,clap” scaled by the factor

73 Second half of ScaleBranch—we get the sounds from next
// Collect from my next if (this.getNext() != null) {Sound nextSound=this.getNext().collect(); childSound = childSound.append(nextSound);} return childSound; } Second half of ScaleBranch—we get the sounds from next SoundBranch this SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest

74 We’re in the first half of SoundBranch
public Sound collect(){ Sound childSound; if (children != null) {childSound = children.collect();} else {childSound = new Sound(1);} We’re in the first half of SoundBranch SoundBranch this SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest childSound will become “Clap, snap, snap, rest, snap, clap”

75 We’re in the second half of SoundBranch
// Collect from my next if (this.getNext() != null) {Sound nextSound=this.getNext().collect(); childSound = childSound.append(nextSound);} return childSound; } We’re in the second half of SoundBranch SoundBranch this SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest There is no next so we return “Clap, snap, snap, rest, snap, clap”

76 Back to second half of ScaleBranch
// Collect from my next if (this.getNext() != null) {Sound nextSound=this.getNext().collect(); childSound = childSound.append(nextSound);} return childSound; } Back to second half of ScaleBranch SoundBranch this SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest This returns “Clink,clave,gong,rest,chirp,clap” scaled by the factor, plus “Clap, snap, snap, rest, snap, clap” getNext().collect() returned “Clap, snap, snap, rest, snap, clap”

77 Back in the second half of SoundBranch’s collect()
// Collect from my next if (this.getNext() != null) {Sound nextSound=this.getNext().collect(); childSound = childSound.append(nextSound);} return childSound; } Back in the second half of SoundBranch’s collect() SoundBranch SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong this Rest, snap, clap Rest, chirp, clap Rest, snap, rest This returns “Clap,rest,snap,rest,snap,rest”, plus “Clink,clave,gong,rest,chirp,clap” scaled by the factor, plus “Clap, snap, snap, rest, snap, clap”

78 Now we’re back to the second half of this. There is no next
// Collect from my next if (this.getNext() != null) {Sound nextSound=this.getNext().collect(); childSound = childSound.append(nextSound);} return childSound; } Now we’re back to the second half of this. There is no next SoundBranch this SoundBranch ScaleBranch SoundBranch Clap, rest, snap Clap,snap,snap Clink,clave, gong Rest, snap, clap Rest, chirp, clap Rest, snap, rest FINAL RETURN: “Clap,rest,snap,rest,snap,rest”, plus “Clink,clave,gong,rest,chirp,clap” scaled by the factor, plus “Clap, snap, snap, rest, snap, clap”

79 That was one kind of tree traversal
There are other ways of thinking about traversing a tree! Go down the next before going to the children? Maybe do the scaling to the next instead of to the children? Processing first is called pre-order traversal. Processing last (doing the next) is called post-order traversal.

80 SoundBranch’s collectAfter()
/** * Collect all the sound from our children, * then collect from next. * If there's processing, do to Next, not to Children pen Turtle to draw with **/ public Sound collectAfter(){ Sound childSound; if (children != null) {childSound = children.collectAfter();} else {childSound = new Sound(1);} // Collect from my next if (this.getNext() != null) {childSound=childSound.append(this.getNext().collectAfter());} return childSound; }

81 ScaleBranch’s collectAfter()
/** * Collect all the sound from our children, * then collect from next. * Scale the next list, not the children pen Turtle to draw with **/ public Sound collectAfter(){ Sound childSound; if (children != null) {childSound = children.collect();} else {childSound = new Sound(1);} // Collect from my next if (this.getNext() != null) {Sound nextSound=this.getNext().collect(); childSound = childSound.append(nextSound.scale(factor));} return childSound; } Notice that we’re scaling what getNext().collect() returns, not what children.collect() returns Here’s where it’s really different

82 Trying this in SoundTreeList
public void playAfter(){ root.collectAfter().play(); } > tree.playAfter()

83 Where else could we go with this?
How about a kind of SoundBranch that knows how to repeat its children a certain number of time? How about a kind of SoundBranch that can mix its children with the next, with a certain percentage of each? Back with pictures: How about a kind of branch that can rotate its children? Or scale them, so you could zoom in or out, or grow/shrink the monster, across frames?

84 Arrays, and Lists, and Trees, oh my!
Where we’re going next: We’ve explored lists and trees in a good deal of depth now! You obviously saw lots of similarities between these implementations. “Couldn’t we do this once, instead of duplicating all this code?!?” YES! Let me show you… “Man, what I really want to do is user interfaces with Java—real applications! What does this all have to do with that?!?” A user interface is a tree. Let me show you…


Download ppt "CS1316: Representing Structure and Behavior"

Similar presentations


Ads by Google