Beeping in Java
The objective of this article is to write a beep() method in Java. It will just play a tone in a specified frequency. Before we look into the details of the beep() method, let's have a look at the caller first. // main program to call the beep() method
public static void main(String[] args) throws Exception
{
int frequency=400; // hz
int duration =2000; // milliseconds
beep(frequency,duration);
}
Physics of Sound
Before we can define the beep() method, we must know the mathematical modeling of a sound wave. Mathematically, a "pure tone" can be represented by a sine wave. The following program will generate a sine wave. Just compile the program and go to the "Visualize" section below.
/******************************************************************************
* File : Sine.java
* Author : http://java.macteki.com/
* Description :
* Create sample data points of a Sine wave
* Tested with : JDK 1.6
******************************************************************************/
class Sine
{
static short[] makeSineSample()
{
double frequency = 400;
double sampleRate = 16000; // 16000 samples per second
int bytesPerSample = 2;
short[] audioData = new short[160]; // 160 sample points = 10 ms
int sampleLength = audioData.length;
double volume = 8192;
for(int i = 0; i < sampleLength; i++){
double time = i/sampleRate;
double angle = 2*Math.PI*frequency*time;
double sinValue = Math.sin(angle);
short amplitude = (short) (volume*sinValue);
audioData[i]=amplitude;
}
return audioData;
}
public static void main(String[] args) throws Exception
{
short[] buffer=makeSineSample();
for (int i=0;i<160;i++)
{
System.out.println(buffer[i]);
}
}
}
The above program will create 160 sample pixels of the sine wave with frequency 400hz. That is, the sine wave will complete 400 cycles in 1 second. If we generate 10 ms of data, there would be 4 cycles. Since the sampling rate is 16000 samples per second, 160 samples will contains 10 ms of data.
Visualize the Sample Data
First execute the program :
java Sine >out.txtLoad the output file into a excel file, then insert a graph with the sample data. You should see 4 cycles of sine wave as expected.
Java Sound API
The javax.sound.sampled package provides API to play a sound wave. All we have to do is to feed the sound wave sample data points to a SourceDataLine object. The following is a complete sample of playing a beep sound.
/******************************************************************************
* File : Beep.java
* Author : http://java.macteki.com/
* Description :
* Play a pure tone with specified frequency
* Tested with : JDK 1.6
******************************************************************************/
class Beep
{
static void beep(double frequency, int duration) throws Exception
{
int nChannel = 1; // number of channel : 1 or 2
// samples per second
float sampleRate = 16000; // valid:8000,11025,16000,22050,44100
int nBit = 16; // 8 bit or 16 bit sample
int bytesPerSample = nChannel*nBit/8;
double durationInSecond = duration/1000;
int bufferSize = (int) (nChannel*sampleRate*durationInSecond*bytesPerSample);
byte[] audioData = new byte[bufferSize];
// "type cast" to ShortBuffer
java.nio.ByteBuffer byteBuffer = java.nio.ByteBuffer.wrap(audioData);
java.nio.ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
int sampleLength = audioData.length/bytesPerSample;
// generate the sine wave
double volume = 8192; // 0-32767
double PI = Math.PI;
for(int i = 0; i < sampleLength; i++){
double time = i/sampleRate;
double freq = frequency;
double angle = 2*PI*freq*time;
double sinValue = Math.sin(angle);
short amplitude = (short) (volume*sinValue);
for (int c=0;c<nChannel;c++)
{
shortBuffer.put(amplitude);
}
}//end generating sound wave sample
boolean isSigned=true;
boolean isBigEndian=true;
// Define audio format
javax.sound.sampled.AudioFormat audioFormat =
new javax.sound.sampled.AudioFormat(sampleRate, nBit, nChannel, isSigned,isBigEndian);
javax.sound.sampled.DataLine.Info dataLineInfo =
new javax.sound.sampled.DataLine.Info(
javax.sound.sampled.SourceDataLine.class, audioFormat);
// get the SourceDataLine object
javax.sound.sampled.SourceDataLine sourceDataLine =
(javax.sound.sampled.SourceDataLine)
javax.sound.sampled.AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
// actually play the sound
sourceDataLine.write(audioData,0,audioData.length);
// "flush", wait until the sound is completed
sourceDataLine.drain();
}
public static void main(String[] args) throws Exception
{
int frequency=400; // hz
int duration =2000; // milliseconds
beep(frequency,duration);
}
}

Can you tell me why double volume = 8192; ? Why this value?
ReplyDeleteThe volume level 8192 is just an arbitrary choice between 0 and 32767.
DeleteThis comment has been removed by the author.
ReplyDeletewhy volume is a number from 0 to 32767
ReplyDeleteBecause it is a 16 bit sound sample (see line 19 of Beep.java).
DeleteFor a 16 bit sample, the amplitude is stored in a short integer (see line 43).
And for a 16 bit short integer, the range is from -32768 to +32767. That means your sine wave will have a maximum amplitude of 32767. And in Physics, amplitude is volume.
Hope this help.
thx you for these sound posts. i was looking for this for quite some time.
Deletewhy sample rates must be // valid:8000,11025,16000,22050,44100 ?
They are typical rates that most codec would support. Selecting a value from one of them is a safe choice.
DeleteGambling in the Casino 888: No deposit bonus casino - Air
ReplyDeleteGambling in the where can i find air jordan 18 retro red suede Casino 888: No deposit bonus casino. Gambling in the Casino 888: No deposit bonus replica air jordan 18 retro men red casino. show to buy air jordan 18 retro varsity red Gambling in the Casino 888: good air jordan 18 retro No deposit Wholesale jordan 13 retro Sale bonus casino. Gambling in the Casino 888: No