src/codeandchords/Melody.java
private void playMelodyThread( String key, float bpm, String scale, int rangeOctave, Instrument instrument ) throws InterruptedException
	{
		float[][]	curMelody	= melodyLib.get(scale.trim().toLowerCase());
		//		int			scaleLength	= curMelody.length;
		//		int[]		midiNotes	= new int[scaleLength];
		//		float[]		durations	= new float[scaleLength];
		Note[]		notes		= new Note[curMelody.length];
		float		defaultAmp	= 1;

		// Find position of notes in this key:
		int		keyPos		= -1;
		for(int i = 0; i < Melody.keys.length; i++)
		{
			if(Melody.keys[i].toUpperCase().contains(" " + key.trim().toUpperCase() + " "))
			{
				keyPos	= i;
				/*
					As of 6/15, octaves will start at C and so the following is N/A:
				//because midi numbers start at C, the last three notes in the octave (A, A#, B)
				//need to be dropped down an octave so that they make intuitive sense in the 
				//drop down box, which starts at A.  Without this, the notes at the top of the 
				//drop down list (A, A#, B) would be higher than the proceeding notes ( C - G# )
				if(keyPos >= 9) { keyPos = keyPos - 12; }
				 */
			}
		} // for - find key position
		if(keyPos == -1)
		{
			throw new IllegalArgumentException("Melody.playMelody: key " + key + " is not a valid key.");
		} // error checking

		this.setRangeList();

		// Calculate milli's per Note, given the tempo:
		float quarterNoteTime = (float) (Math.pow(bpm, -1) * 60 * 1000);

		int		scalePos;
		int		midiNote;
		float	duration;
		float	amplitude;
		boolean	isRest;

		// Calculate midi notes, given the key and range:
		for(int i = 0; i < curMelody.length; i++)
		{
			// If there is indeed a note at this part of the melody, add it to the midiNotes array:
			if(curMelody[i].length == 2)
			{
				scalePos	= (int) ((curMelody[i][0]) + keyPos);
				midiNote	= (12 * (rangeOctave + 1)) + scalePos;

				duration	= curMelody[i][1] * quarterNoteTime;
				amplitude	= defaultAmp;
				isRest		= false;
			} else if(curMelody[i].length == 1){
				// but if not, use -1 as a placeholder:
				midiNote	= -1;
				duration	= curMelody[i][0] * quarterNoteTime;
				amplitude	= 0;
				isRest		= true;
			} else {
				throw new IllegalArgumentException("Melody.playMelodyThread: curMelody[" + i + "] (" + curMelody[i] + 
						" is not a valid length; if indicating a rest, it must have length 1, and for all other notes, length 2.");
			}

			// create an array of Notes:
			notes[i]	= new Note(midiNote, duration, amplitude, isRest);

		} // for - calculate midi notes

		// This while loop is what keeps the melody repeating:
		
		int multiplyer = 700;
		
		while(this.melodyThreadRunning)
		{

			float	nextNoteStartTime	= parent.millis();
			
			if(this.input != null)
			{
				this.input.setAmplitudeArray(new float[] { this.instrument.getGain() * multiplyer });
			}

			// use the Note's duration to call instrument.play() at the appropriate time
			for( int i = 0 ; i < notes.length - 1 && this.melodyThreadRunning; i++)
			{
				instrument.playNote(notes[i]);

				if(this.input != null)
				{
					this.input.setFundamentalArray(new float[] { Pitch.mtof(notes[i].getMidiNum()) });
//					this.input.setAdjustedFundArray(new float[] { Pitch.mtof(notes[i].getMidiNum()) });
					this.input.setAmplitudeArray(new float[] { this.instrument.getGain() * multiplyer });
				}

				nextNoteStartTime	= parent.millis() + notes[i].getDuration();
				//				System.out.println("nextNoteStartTime = " + nextNoteStartTime);


				while(parent.millis() < nextNoteStartTime && this.isRunning())	
				{
					if(this.input != null)
					{
						this.input.setAmplitudeArray(new float[] { this.instrument.getGain() * multiplyer });
					}
					
					if(this.paused) { nextNoteStartTime = nextNoteStartTime + 12; }
					Thread.sleep(10);
				}

			} // for - play Notes
		} // while

	}
/**
	 * Uses the given scale and key to create an array of Notes,
	 * then loops through that array and plays them with the given Instrument.
	 * 
	 * @param key	String denoting the current key; do not include major or minor designation here
	 * @param bpm	tempo in beats per minute
	 * @param scale	either the String "major", "minor", or "chromatic"
	 * @param rangeOctave	int giving the range octave; must be between 3 and 6
	 * @param instrument	Instrument that will play the Melody
	 * @throws InterruptedException
	 */
Uses the given scale and key to create an array of Notes,
then loops through that array and plays them with the given Instrument.


Uses the given scale and key to create an array of Notes then loops through that array and plays them with the given Instrument .
private void playMelodyThread( String key, float bpm, String scale, int rangeOctave, Instrument instrument ) throws InterruptedException
	{
		float[][]	curMelody	= melodyLib.get(scale.trim().toLowerCase());
		Note[]		notes		= new Note[curMelody.length];
		float		defaultAmp	= 1;
		int		keyPos		= -1;
		for(int i = 0; i < Melody.keys.length; i++)
		{
			if(Melody.keys[i].toUpperCase().contains(" " + key.trim().toUpperCase() + " "))
			{
				keyPos	= i;
				/*
					As of 6/15, octaves will start at C and so the following is N/A:
				//because midi numbers start at C, the last three notes in the octave (A, A#, B)
				//need to be dropped down an octave so that they make intuitive sense in the 
				//drop down box, which starts at A.  Without this, the notes at the top of the 
				//drop down list (A, A#, B) would be higher than the proceeding notes ( C - G# )
				if(keyPos >= 9) { keyPos = keyPos - 12; }
				 */
			}
		} 
		if(keyPos == -1)
		{
			throw new IllegalArgumentException("Melody.playMelody: key " + key + " is not a valid key.");
		} 
		this.setRangeList();
		float quarterNoteTime = (float) (Math.pow(bpm, -1) * 60 * 1000);
		int		scalePos;
		int		midiNote;
		float	duration;
		float	amplitude;
		boolean	isRest;
		for(int i = 0; i < curMelody.length; i++)
		{
			if(curMelody[i].length == 2)
			{
				scalePos	= (int) ((curMelody[i][0]) + keyPos);
				midiNote	= (12 * (rangeOctave + 1)) + scalePos;
				duration	= curMelody[i][1] * quarterNoteTime;
				amplitude	= defaultAmp;
				isRest		= false;
			} else if(curMelody[i].length == 1){
				midiNote	= -1;
				duration	= curMelody[i][0] * quarterNoteTime;
				amplitude	= 0;
				isRest		= true;
			} else {
				throw new IllegalArgumentException("Melody.playMelodyThread: curMelody[" + i + "] (" + curMelody[i] + 
						" is not a valid length; if indicating a rest, it must have length 1, and for all other notes, length 2.");
			}
			notes[i]	= new Note(midiNote, duration, amplitude, isRest);
		} 
		int multiplyer = 700;
		while(this.melodyThreadRunning)
		{
			float	nextNoteStartTime	= parent.millis();
			if(this.input != null)
			{
				this.input.setAmplitudeArray(new float[] { this.instrument.getGain() * multiplyer });
			}
			for( int i = 0 ; i < notes.length - 1 && this.melodyThreadRunning; i++)
			{
				instrument.playNote(notes[i]);
				if(this.input != null)
				{
					this.input.setFundamentalArray(new float[] { Pitch.mtof(notes[i].getMidiNum()) });
					this.input.setAmplitudeArray(new float[] { this.instrument.getGain() * multiplyer });
				}
				nextNoteStartTime	= parent.millis() + notes[i].getDuration();
				while(parent.millis() < nextNoteStartTime && this.isRunning())	
				{
					if(this.input != null)
					{
						this.input.setAmplitudeArray(new float[] { this.instrument.getGain() * multiplyer });
					}
					if(this.paused) { nextNoteStartTime = nextNoteStartTime + 12; }
					Thread.sleep(10);
				}
			} 
		} 
	}
private void playMelodyThread ( String key , float bpm , String scale , int rangeOctave , Instrument instrument ) throws InterruptedException { float [ ] [ ] curMelody = melodyLib . get ( scale . trim ( ) . toLowerCase ( ) ) ; Note [ ] notes = new Note [ curMelody . length ] ; float defaultAmp = 1 ; int keyPos = - 1 ; for ( int i = 0 ; i < Melody . keys . length ; i ++ ) { if ( Melody . keys [ i ] . toUpperCase ( ) . contains ( " " + key . trim ( ) . toUpperCase ( ) + " " ) ) { keyPos = i ; /*
					As of 6/15, octaves will start at C and so the following is N/A:
				//because midi numbers start at C, the last three notes in the octave (A, A#, B)
				//need to be dropped down an octave so that they make intuitive sense in the 
				//drop down box, which starts at A.  Without this, the notes at the top of the 
				//drop down list (A, A#, B) would be higher than the proceeding notes ( C - G# )
				if(keyPos >= 9) { keyPos = keyPos - 12; }
				 */ } } if ( keyPos == - 1 ) { throw new IllegalArgumentException ( "Melody.playMelody: key " + key + " is not a valid key." ) ; } this . setRangeList ( ) ; float quarterNoteTime = ( float ) ( Math . pow ( bpm , - 1 ) * 60 * 1000 ) ; int scalePos ; int midiNote ; float duration ; float amplitude ; boolean isRest ; for ( int i = 0 ; i < curMelody . length ; i ++ ) { if ( curMelody [ i ] . length == 2 ) { scalePos = ( int ) ( ( curMelody [ i ] [ 0 ] ) + keyPos ) ; midiNote = ( 12 * ( rangeOctave + 1 ) ) + scalePos ; duration = curMelody [ i ] [ 1 ] * quarterNoteTime ; amplitude = defaultAmp ; isRest = false ; } else if ( curMelody [ i ] . length == 1 ) { midiNote = - 1 ; duration = curMelody [ i ] [ 0 ] * quarterNoteTime ; amplitude = 0 ; isRest = true ; } else { throw new IllegalArgumentException ( "Melody.playMelodyThread: curMelody[" + i + "] (" + curMelody [ i ] + " is not a valid length; if indicating a rest, it must have length 1, and for all other notes, length 2." ) ; } notes [ i ] = new Note ( midiNote , duration , amplitude , isRest ) ; } int multiplyer = 700 ; while ( this . melodyThreadRunning ) { float nextNoteStartTime = parent . millis ( ) ; if ( this . input != null ) { this . input . setAmplitudeArray ( new float [ ] { this . instrument . getGain ( ) * multiplyer } ) ; } for ( int i = 0 ; i < notes . length - 1 && this . melodyThreadRunning ; i ++ ) { instrument . playNote ( notes [ i ] ) ; if ( this . input != null ) { this . input . setFundamentalArray ( new float [ ] { Pitch . mtof ( notes [ i ] . getMidiNum ( ) ) } ) ; this . input . setAmplitudeArray ( new float [ ] { this . instrument . getGain ( ) * multiplyer } ) ; } nextNoteStartTime = parent . millis ( ) + notes [ i ] . getDuration ( ) ; while ( parent . millis ( ) < nextNoteStartTime && this . isRunning ( ) ) { if ( this . input != null ) { this . input . setAmplitudeArray ( new float [ ] { this . instrument . getGain ( ) * multiplyer } ) ; } if ( this . paused ) { nextNoteStartTime = nextNoteStartTime + 12 ; } Thread . sleep ( 10 ) ; } } } }
Uses the given scale and key to create an array of Notes,
 then loops through that array and plays them with the given Instrument.
Uses the given scale and key to create an array of Notes then loops through that array and plays them with the given Instrument .
//		int			scaleLength	= curMelody.length; //		int[]		midiNotes	= new int[scaleLength]; //		float[]		durations	= new float[scaleLength]; // Find position of notes in this key: // for - find key position // error checking // Calculate milli's per Note, given the tempo: // Calculate midi notes, given the key and range: // If there is indeed a note at this part of the melody, add it to the midiNotes array: // but if not, use -1 as a placeholder: // create an array of Notes: // for - calculate midi notes // This while loop is what keeps the melody repeating: // use the Note's duration to call instrument.play() at the appropriate time //					this.input.setAdjustedFundArray(new float[] { Pitch.mtof(notes[i].getMidiNum()) }); //				System.out.println("nextNoteStartTime = " + nextNoteStartTime); // for - play Notes // while