Open pconrad opened 11 years ago
@rtwaltman and @dwang68
@pconrad commenting from @dwang68 account...
The missing line, I think is this:
pitch duration loudness pitch duration loudness pitch duration loudness pitch duration loudness pitch duration loudness pitch duration loudness etc...
So,for example: frere jacques might be:
c4 1 0.5
d4 1 0.5
e4 1 0.5
c4 1 0.5
c4 1 0.5
d4 1 0.5
e4 1 0.5
c4 1 0.5
e4 1 0.6
f4 1 0.6
g4 2 0.6
e4 1 0.7
f4 1 0.7
g4 2 0.7
g4 0.5 1
a4 0.5 1
g4 0.5 1
f4 0.5 1
e4 1 1
c4 1 1
g4 0.5 0.25
a4 0.5 0.25
g4 0.5 0.25
f4 0.5 0.25
e4 1 0.25
c4 1 0.25
c4 1 0.6
g3 1 0.6
c4 2 0.6
c4 1 0.4
g3 1 0.3
c4 2 0.2
@pconrad We are confused about the where to implement the master amplitude. I am wondering if the amplitude in the ADSREnvelopedContinuousSound defines the amplitude of the envelope at time t as it gets called in the class EnvelopedSound.java
for(; i<samples; i++){
amp=generateAmplitude(t,amp);
audioData[i]=(byte)((127)_generateWave(t)_amp);
t+=1.0/(double)this.sampleRate;
}
//And the sustain amplitude is multiplied by the amp of the note a.setSustainAmplitude(amp*sustainamp);
//But the amplitude of the ADSREnvelopedContinuousSound gets the amplitude of the note new ADSREnvelopedContinuousSound(freq, amp, a, 44100, d);
Can you explain the relations of those amplitude and where should we implement the master amplitude? Thanks a lot!
@dwang68 @bronhuston I'm thinking that we can just do a simple multiplier on the note volume, which we get while reading in from a .txt file. So if we just multiply it by some GUI-changeable variable called masterVolume, then each note should be adjusted to the 0->.95 scale.
To be specific, in createMelodyFromFile(), we split every line of our .txt: pitch duration loudness
and get the appropriate freq, duration, volume
Our 'loudness' or 'volume' string, which is splitline[2], gets parsed to a double and then set to a function variable volume, which gets passed to a Note constructor with: "m.add(new Note(freq,duration,volume));". So this adds the fully built notes from the line of text to our melody, which gets played later. So I'm thinking that our masterVolume should EITHER be in Note.java and when the instance variables get set by the constructor, we simply multiply the sent in volume by our masterVolume and then set it to the instance variable volume OR in Melody.java and the multiplication is done before the constructor call.
Then, the sustain amplitude will be multiplied by the new adjusted note volume on a scale of 0-.95 and everything already written should be working properly (at least I think). That way, we're not ever using a 1 amplitude note anywhere
@rtwaltman This sounds like a good plan so far.
Personally, I think that it makes the most sense to make the MasterVolume in the Note.java class because that is where the actual note is created.
The melody.java file primarily deals with creating the list of notes for a melody from some specified input(txt file). I think it makes the most sense to have the Melody.java file control how the list of notes is created from various input formats, while the Note.java file deals with actually creating each note and ensuring it has the correct amplitude, volume, etc.
It seems like this is how you are planning on handling it, so it sounds like you're definitely on the right track!
@bronhuston
I've implemented the volume label, text field, and slider for our masterVolume, but I'm to the point where I'm unsure of how to get the value of our masterVolume into every Note class that gets created. I was thinking of trying to make it a global sort of variable that could always be accessed and used, such as this:
public class Globals {
public static double masterVolume; //set this to our slider masterVolume
}
Then, whenever we make the note amplitude, we do something like
amplitude *= G.masterVolume;
, where G is an instance of Globals used just to get the variable.
I see two potential problems with this, however.
Looking at the code, I'm having a hard time tracing through and finding where and when the GUI builds the notes. I've been trying to decode the AudioFormat, SourceDataLine, and AudioSystem java classes to understand what's actually happening with the button listeners. As far as I can tell, AudioSystem builds a playable sound line, SourceDataLine, by using AudioFormat. And then that SourceDataLine is used to create an ADSREnvelopedContinuousSound instance, which calls the EnvelopedSound constructor inside of its constructor...and this is where I am lost. It appears Note is never even used for the melodyGUI. There's amplitudes being built inside of the EnvelopedSound, but as far as I can tell, Note is never used. Are these the amplitudes being built per note?
I'll definitely be bombarding Professor Conrad at office hours.
We basically have two things to implement:
The latter of which is abstracted away from using the Note class.
@rtwaltman In the case of the MelodyGui code, the Note class is sort of used indirectly. By this I mean that since the MelodyGUI uses the Melody class and the Melody class uses the note class, the MelodyGui class sort of uses the note class.
By changing how certain aspects of the Note class are handled, you change the contents of the Melody.
The melody class then handles the actual playing of the note through the creation of the ADSREnvelope etc.
In the Note class has values for the freq, duration and volume of each note, and the Melody class sets the amplitude to be equal to the the (notes volume)*(the inputed amp of the envelope) for each note.
@bronhuston I see. I was getting caught up on the details of the things that I don't understand and wasn't looking past them. Thanks for pushing me in the right direction!
Duration of notes requires more work.
~depends #18
Adjust all current code to support a new melody format.
Melody files should be in the format: