import java.util.Scanner;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class FrequencyPlayer {
private static Clip current;
private static final AudioFormat format = new AudioFormat( 50000, 16, 1, true, true );
private static final double pi2 = Math.PI*2;
public static void main( String[] args ) {
final JTextField frequency = new JTextField(10);
Runnable r = new Runnable() {
public void run() {
Object lock = new Object();
String old = "";
while ( true ) {
synchronized ( lock ) {
try {
String s = frequency.getText();
if ( !old.equals(s) ) {
old = s;
float fstart, fend, time;
fstart = fend = time = -1f;
Scanner scan = new Scanner(s);
if ( scan.hasNextFloat() ) {
fstart = scan.nextFloat();
if ( scan.hasNextFloat() ) {
fend = scan.nextFloat();
if ( scan.hasNextFloat() )
time = scan.nextFloat();
}
}
if ( fstart >= 0 ) {
if ( fend >= 0 ) {
if ( time >= 0 )
playRange(fstart,fend,time);
else
playRange(fstart,fend,5.f);
}
else
playFrequency(fstart);
}
}
}
catch ( Exception e ) {}
try {
lock.wait(50);
}
catch ( InterruptedException e ) {}
}
}
}
};
new Thread(r).start();
JFrame frame = new JFrame();
frame.add(frequency);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
public static void playFrequency( float freq ) {
byte[] data = generateAudioData(format,freq);
if ( current != null ) {
current.close();
}
try {
Clip c = AudioSystem.getClip();
c.open(format,data,0,data.length);
current = c;
c.loop(Clip.LOOP_CONTINUOUSLY);
System.out.println("Playing " + freq);
}
catch ( Exception e ) {
e.printStackTrace();
}
}
public static void playRange( float start, float end, float time ) {
byte[] data = generateAudioData(format,start,end,time);
if ( current != null ) {
current.close();
}
try {
Clip c = AudioSystem.getClip();
c.open(format,data,0,data.length);
current = c;
c.loop(Clip.LOOP_CONTINUOUSLY);
System.out.println("Playing " + start + " to " + end + " for " + time + "s");
}
catch ( Exception e ) {
e.printStackTrace();
}
}
public static byte[] generateAudioData( AudioFormat format, float frequency ) {
double waveLength = 1/frequency;
// We want at least 100 data points and we want to end at the end of a wave
int samples = (int)(format.getSampleRate())*2;
byte[] data = new byte[samples];
for ( int sample = 0; sample < data.length/2; sample++ ) {
int index = sample*2;
float time = sample/format.getSampleRate();
double position = Math.cos( pi2 * time / waveLength );
short amp = 0;
if ( format.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED) )
amp = (short)(0x7ffe*position);
else
amp = (short)(0x7ffe*position+0x7ffe);
data[index] = (byte)((amp>>8)&0xff);
data[index+1] = (byte)(amp&0xff);
}
return data;
}
public static byte[] generateAudioData( AudioFormat format, float fstart, float fend, float time ) {
float m = fend/fstart;
float m0 = (float)Math.pow(Math.E, Math.log(m)/time);
int samples = (int)((format.getSampleRate())*2*time);
byte[] data = new byte[samples];
float logm0 = (float)Math.log(m0);
float c = (float) (2*Math.PI*fstart/logm0);
for ( int sample = 0; sample < data.length/2; sample++ ) {
int index = sample*2;
float t = sample/format.getSampleRate();
double position = Math.sin( c * (Math.pow(Math.E, t*logm0) - 1) );
short amp = 0;
if ( format.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED) )
amp = (short)(0x7ffe*position);
else
amp = (short)(0x7ffe*position+0x7ffe);
data[index] = (byte)((amp>>8)&0xff);
data[index+1] = (byte)(amp&0xff);
}
return data;
}
}