This week's lab will ask you to create several methods that look something like methods discussed in your textbook. However, in several cases I will ask you to make some significant changes. Please feel free to use your book as a guide, but make sure to pay attention to what I am actually asking you to produce.
To do this lab you will need to have a copy of the following files.
The first three sounds are "pure" tones of differing frequencies.
The fourth sound is played on a musical instrument rather than generated digitally.
The fifth sound is our author reading the preamble but trimmed to exactly 19 seconds so that we can avoid some errors with some of the things I will ask you to do.
Open tone1.wav . Play the sound and explore with the sound explorer (make sure you use "zoom in")
[Q1] Describe the shape of the wave?
[Q2] Find the sample number of the first peak (not the value, but the sample index)
[Q3] Find the sample number of the second peak.
[Q4] Using this information, calculate the frequency of this tone (hint, this is just the "orig440.wav" file we have been working with in this unit. Show me your work, but if you aren't getting 440 as an answer you don't understand how to solve the problem.
Open tone2.wav Play the sound and use the sound explorer
[Q5] Find the sample number of the first peak
[Q6] Find the sample number of the second peak.
[Q7] Using this information, calculate the frequency of this tone
Open tone3.wav Play the sound and use the sound explorer
[Q8] Find the sample number of the first peak
[Q9] Find the sample number of the second peak.
[Q10] Using this information, calculate the frequency of this tone
Finally, open instrument2.wav Play the sound and use the sound explorer
[Q11] What does the sound sound like?
[Q12] Describe the shape of the wave? Please make sure you zoom in to see the full wave, but make sure that you scan to the right and don't just answer this based on the first couple of samples)
[Q13] Calculating the frequency of this wave is a little more complicated than that used with the previous tones. However, it IS possible. Describe what you could do to find the frequency of this wave.
[Q14] Do it. What is the frequency of this tone?
Music can be made in several ways.
The first is a simple progression of notes (something you will be doing in PA06). Mary had a little lamb is E - D - C - D - E - E- E. To create this "music" you would need to string together several sound files into a sequence - much like you make a comic strip or art collage by putting several pictures together in the right sequence.
The second is through the creation of "chords" - playing two notes simultaneously. In order to do this you need to find a way to layer two different sounds over the top of each other. It turns out that this is fairly simple to do when using sound "addition"
Write a method called mergeSounds(). This method should take in two different sounds (assumed to be the same length) and should return a third sound which is the "blending" of these two sounds through sound addition. In other words, if sample#1 of sound#1 has a value of 100, and sample #1 of sound#2 has a value of 200, then sample#1 of the output sound should have a value of 300.
[SIG1] When you think you have it correct, ask a TA to check it
When you are done, merge sounds tone1 and tone2
[Q15] Play the resulting sound. What does it sound like?
[Q16] Look at the sound wave using the sound explorer. What does it look like (look carefully)
Try this again with tone1 and tone3.
[Q17] Play the resulting sound. What does it sound like?
[Q18] Look at the sound wave using the sound explorer. What does it look like (This one will be a little more obvious, but still look carefully)
Finally, try this again with tone1 and instrument2
[Q17] Play the resulting sound. What does it sound like?
[Q18] Look at the sound wave using the sound explorer (make sure you scroll into the middle a ways to account for the "start up" on instrument2). What does it look like?
Create a COPY of your mergeSounds() method and call it mergeAverageSounds(). In this new version instead of setting the output to the SUM of the two sounds it sets it to the AVERAGE of the two sounds (in my example, the average of 100 and 200 is 150).
[Q19] Merge tone1 and tone2. How are the results of mergeAverageSounds() different from the previous version of mergeSounds()? (and they are different)
Suppose that you wanted to create an echo effect. An echo is created when you hear a sound source along with a delayed reflection of that sound source (for example, your "hello" bouncing off of a canyon wall several 100 feet away).
In many ways, this is similar to what you did in Activity B - that is, you are layering two sounds (the source and the reflection) over the top of each other to create a third sound.
However, it is DIFFERENT from Activity B in that you start with only one sound that you use twice (the original and it's reflection). Furthermore, there is some concept of "delay" between when you FIRST hear a sound and when you hear it's reflection. Finally, the reflection is normally "fainter" (more faint??) than the original
In this activity, let's create such an echo effect.
I would like you to use an approach which is different from that used in Recipe 63 in your book. I do this not because what's in your book is wrong (it works just fine!) but because I want to take advantage of the mergeSounds() method we just wrote in Activity B
Step #1
Write a method called buildReflection(). This method should take two parameters - the sound to be reflected/echoed, and a delay factor. This factor should be an integer which indicates how many samples are skipped before the sound is "reflected" back.
buildReflection() should return a sound which is a delayed version of the original with each (delayed) sample set to some smaller percentage of the original sample.
For example, suppose the delay is 1000. This would mean that the reflection would start with the first 1000 samples being empty (set to zero). Sample 1001 in the reflection would be based on sample 1 of the original sound, but "softer" Sample 1002 in the reflection would be based on sample 2 of the original sound.
To make a sample softer, let's just multiply by 50% (0.5).
Thus, if sample 1 of the original is 100, sample 1001 of the reflection would be 50. If sample 2 of the original is 180, sample 1002 of the reflection would be 90, etc.
Finally, with this approach you have to decide what to do about the LAST 1000 samples of the original sound. For simplicity, I would just ignore them. Thus, a two second original sound would still be two seconds with this reflection technique.
Step #2
Write a method called echo(). This method should also take two parameters - the sound to be reflected/echoed, and a delay factor.This method should use this information to call buildReflection() that you built in Step#1. After you have invoked buildReflection() you now have two sound files - the original that was passed in and the softer/delayed version build by buildReflection().
Next you can use mergeSounds() from Activity B to blend these two sounds into a third sound.
Testing this out
Once you have this done try testing it with
s = makeSound("tone1.wav")
echo(s , 1000)
Can you hear the echo? Probably not. Try it again with
echo(s, 5000)
Can you hear the echo? Again, probably not. The problem is that the tones have such a high frequency that echo doesn't do much. Instead, test this with the NEW version of the preamble that I made available today.
s2 = makeSound("preamble19.wav")
echo(s2 , 1000)
[Q20] What do you hear?
[Q21] Repeat this with a delay factor of 4000. What do you hear?
[SIG2] When you are comfortable that your code works, show it to a TA.
Yesterday in lecture we talked about how you could use the final method - changeFreq() - to take the 440 tone and generate a tone with any frequency we wanted. However, in playing with this we noticed that we got one of those tones that "buzzed" We can talk in lecture on Wednesday about why this is. In the mean time, let's look at writing a method that will generate one of these "pure" tones completely from scratch.
Using Recipe 70 on page 191 as a guide, write your own version of the sineWave() method. The only significant change that I want between what is in the book and what you should produce is that I want YOUR version to take three parameters
[SIG3] When you have my version of sineWave() working, show this to your TA.
While it should be relatively easy to simply copy/edit the code from your textbook, it is sort of important that you get in the habit of looking at code and really seeing what it does and how it works. Reflect on the code that you just wrote and answer the following questions. It may be helpful to consider these questions by assuming that someone invoked the method with
sineWave(440,2000,2)
[Q22] What is the value of the interval variable? What does this represent?
[Q23] What is the value of the samplesPerCycle variable? What does this represent?
[Q24] What is the value of the maxCycle variable? What does this represent? Why do you think that we need it?
[Q25] For each of the given values of pos calculate the value of rawSample and sampleVal:
| pos | rawSample | sampleVal |
| 6 | ||
| 12 | ||
| 25 | ||
| 44 |
[Q26] What does rawSample represent?
[Q26] What does sampleVal represent?
Test this by creating a "chord" by issuing the following commands:
s440 = sineWave(440,2000,2) s880 = sineWave(880,4000,2) s1320 = sineWave(1320,8000,2) openSoundTool(s440)
[Q27] What does the wave look and sound like at this point?
Next try -
merge = mergeSounds(s440,s880) openSoundTool(merge)
[Q28] What does the wave look and sound like after adding in s880?
Finally try
mergeBigger = mergeSounds(merge,1320) explore(mergeBigger) # see question 24
[Q29] What does the wave look and sound like after adding both s880 and s1320?
mergeBigger = mergeSounds(merge,1320) openSoundTool(mergeBigger) # see question 24
At this point you have completed all the required portions of the lab.
Depending on the time you should probably stick around and either work on the Bonus Problem (see below) or start on PA06.
[Bonus Problem]
Using Recipe 64 as a guide but using the TECHNIQUES used in Activity C, create a method called echoes that takes three parameters