<< Chapter < Page | Chapter >> Page > |
..
Listing 10 . The class named AudioGraphSinusoidal. |
---|
/*File AudioGraphSinusoidal.java
Copyright 2014, R.G.BaldwinRevised 08/23/14
This class can be used to create an 8-second melody consisting of 32 pulsesat different frequencies.
******************************************************************************/import java.io.*;
import java.nio.*;import java.util.*;
public class AudioGraphSinusoidal extends AudioSignalGenerator02{public AudioGraphSinusoidal(AudioFormatParameters01 audioParams,String[] args,byte[] melody){super(audioParams,args,melody);
}//end constructor//-------------------------------------------------------------------------////This method returns a melody array that will play an 8-second melody
// consisting of 32 pulses at different frequencies. The frequencies of the// pulses are centered on middle-C (261.63 Hz).//The frequency deviation from middle-C versus time is based on a sinusoidal
// function with a frequency of 0.5 Hz. Each pulse represents one point on// a graph of the sinusoid. Pulses with frequencies at or above middle-C are
// delivered to the left speaker. Pulses with frequencies below middle-C are// delivered to the right speaker.
//The audio output can be thought of as an audio representation of a graph// of a sinusoid. Pulses with frequencies above middle-C represent points
// on the positive lobe of the sinusoid. Increasing pitch represents// increasing amplitude on the graph of the sinusoid. Pulses with
// frequencies below middle-C can be thought of as representing points on// the negative lobe of the sinusoid. In this case, decreasing pitch
// represents points on the sinusoid that are further from the horizontal// axis in the negative direction. Pulses with a frequency of middle-C can
// be thought of as representing points on the horizontal axis with a value// of zero.
//In order to eliminate pops and clicks caused by abrupt frequency changes// in the audio signal, the amplitude of each pulse is scaled by a
// triangular (rooftop) function that has a value that is zero at both ends// and 1.0 in the center with a linear progression from the center to the
// ends in both directions.//Four complete cycles of the 0.5 Hz sinusoid are represented by the 32
// pulses in the 8-second melody.byte[]getMelody(){
//Set channels to 2 for stereo overriding the default value of 1.audioParams.channels = 2;
System.out.println("audioParams.channels = " + audioParams.channels);//Each channel requires two 8-bit bytes per 16-bit sample.
int bytesPerSampPerChan = 2;//Override the default sampleRate of 16000.0F. Allowable sample rates// are 8000,11025,16000,22050, and 44100 samples per second.
audioParams.sampleRate = 8000.0F;// Specify the length of the melody in seconds.double lengthInSeconds = 8.0;//Set the center frequency. Audio pulses will be generated above and
// below this frequency to represent points on the graph of a// sinusoidal function.
double centerFreq = 261.63;//middle C//Create an output array of sufficient size to contain the melody at// "sampleRate" samples per second, "bytesPerSampPerChan" bytes per
// sample per channel and "channels" channels.melody = new byte[(int)(lengthInSeconds*audioParams.sampleRate*
bytesPerSampPerChan*audioParams.channels)];
System.out.println("melody.length = " + melody.length);//Declare variables used to control the output volume on the left and// right speaker channels. These values will be used to cause pulses
// representing negative values of the sinusoidal function to emit from// one speaker and pulses representing positive values to emit from
// the other speaker.double gain = 0.0;
double leftGain = 0.0;double rightGain = 0.0;
//Declare a variable that is used to control the frequency of each pulse.double freq = 0.0;
//Prepare a ByteBuffer for usebyteBuffer = ByteBuffer.wrap(melody);
//Compute the number of audio samples in the melody.int sampLength = (int)(lengthInSeconds*audioParams.sampleRate);
//Set the length of each pulse in seconds and in samples.double pulseLengthInSec = 0.25;//in seconds
int pulseLengthInSamples = (int)(pulseLengthInSec*audioParams.sampleRate);//Compute the audio sample values and deposit them in the output melody
// array.for(int cnt = 0; cnt<sampLength; cnt++){
//Compute the time in seconds for this sample.double time = cnt/audioParams.sampleRate;if(cnt%pulseLengthInSamples == 0){
//Time to create a new pulse at a different pitch. Compute the// frequency for the next pulse to represent a point on a sinusoidal
// function of time. This section of code could easily be modified// to create audio graphs of many different functions.//Evaluate and scale the function
double val = 0.35 * Math.sin(2*Math.PI*0.5*time);//Compute the frequency for the next pulse as a deviation from the// center frequency. For this scaled sinusoidal function, the Range
// is from 0.65*centerFreq to 1.35*centerFreq or from 170.05 Hz// to 353.2 Hz.
freq = (1+val)*centerFreq;}//end if
//Deposit audio data in the melody for each channel. Scale the amplitude// of each pulse with a triangular scale factor (rooftop shape) to
// minimize the undesirable pops and clicks that occur when there is an// abrupt change in the frequency from one pulse to the next. The
// following gain factor ranges from 0.0 at the ends to 1.0 in the// center of the pulse.
gain = (cnt%pulseLengthInSamples)/(double)pulseLengthInSamples;if(gain>0.5){
//Change to a negative slope.
gain = (pulseLengthInSamples -cnt%pulseLengthInSamples)/(double)pulseLengthInSamples;
}//end if//Set the final gain to a value that is compatible with 16-bit audio// data.
gain = 8000*gain;//Switch the left and right channels on and off depending on the location
// of the pulse frequency relative to the center frequency.if(freq>= centerFreq){
leftGain = gain;rightGain = 0;//switch off the right channel
}else{rightGain = gain;
leftGain = 0;//switch off the left channel}////Compute scaled pulse values and deposit them into the melody.
byteBuffer.putShort((short)(leftGain*Math.sin(2*Math.PI*freq*time)));byteBuffer.putShort((short)(rightGain*Math.sin(2*Math.PI*freq*time)));
}//end for loopreturn melody;}//end method getMelody
//-------------------------------------------------------------------------//}//end class AudioGraphSinusoidal |
-end-
Notification Switch
Would you like to follow the 'Accessible objected-oriented programming concepts for blind students using java' conversation and receive update notifications?