Files
secondo/Javagui/viewer/hoese/ToneGenerator.java
2026-01-23 17:03:45 +08:00

196 lines
5.5 KiB
Java

//This file is part of SECONDO.
//Copyright (C) 2013, University in Hagen, Department of Computer Science,
//Database Systems for New Applications.
//SECONDO is free software; you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation; either version 2 of the License, or
//(at your option) any later version.
//SECONDO is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//You should have received a copy of the GNU General Public License
//along with SECONDO; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package viewer.hoese;
import javax.sound.sampled.Clip;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import java.io.File;
public class ToneGenerator {
private byte[] data; // the sinus data
private Clip clip; // the clip playing the audio
private boolean loop; // run audio in a loop
private int length; // length of playing if not loop
private AudioFormat af; //
private int currentFreq;
private File soundFile;
public ToneGenerator(){
// create audio format
af = new AudioFormat(44100, 16, 1, true, false); // sample rate, sample size, Channels, signed, bigendian
// create sinus wave
data = getSinusTone(440, af);
currentFreq = 440;
loop = true;
length = 1000;
soundFile = null;
try{
clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
clip.open(af, data,0 , data.length);
} catch(javax.sound.sampled.LineUnavailableException e){
clip = null;
}
}
public boolean getLoop(){ return loop; }
public int getLength(){ return length; }
public int getFrequency(){ return currentFreq; }
public File getSoundFile(){ return soundFile; }
public void setLoop(boolean on){
loop = on;
}
public boolean setLength(int length){
if(length>=0){
this.length = length;
return true;
}
return false;
}
public boolean setFrequency(int hz){
if(currentFreq == hz && soundFile==null){
return true;
}
if(hz<20 || hz > 20000){
return false;
}
if(clip==null){
return false;
}
soundFile=null;
currentFreq = hz;
data = getSinusTone(hz, af);
if(clip.isRunning()){
clip.stop();
}
clip.close();
try{
clip.open(af,data,0,data.length);
} catch(javax.sound.sampled.LineUnavailableException e){
return false;
}
return true;
}
boolean setSoundFile(File file){
if(clip==null){
return false;
}
if(file==null){
return false;
}
AudioInputStream in;
try{
in = AudioSystem.getAudioInputStream(file);
} catch(javax.sound.sampled.UnsupportedAudioFileException e){
return false;
} catch(java.io.IOException e2){
return false;
}
if(clip.isRunning()){
clip.stop();
}
clip.close();
soundFile = file;
try{
clip.open(in);
} catch(javax.sound.sampled.LineUnavailableException e){
return false;
} catch(java.io.IOException e2){
return false;
}
return true;
}
private byte[] getSinusTone(double frequency, AudioFormat af) {
byte sample_size = (byte) (af.getSampleSizeInBits() / 8);
byte[] data = new byte[(int) af.getSampleRate() * sample_size];
double step_width = (2 * Math.PI) / af.getSampleRate();
double x = 0;
for (int i = 0; i < data.length; i += sample_size) {
int sample_max_value = (int) Math.pow(2, af.getSampleSizeInBits()) / 2 - 1;
int value = (int) (sample_max_value * Math.sin(frequency * x));
for (int j = 0; j < sample_size; j++) {
byte sample_byte = (byte) ((value >> (8 * j)) & 0xff);
data[i + j] = sample_byte;
}
x += step_width;
}
return data;
}
public void play(){ // todo: play in a thread
if(clip!=null){
if(clip.isRunning()){
return;
}
if(!loop){
new Thread(new PlayThread(clip,length)).start();
} else {
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
}
}
public void stop(){
if(clip!=null){
clip.stop();
}
}
private class PlayThread implements Runnable{
PlayThread(Clip clip, int length){
this.clip=clip;
this.length=length;
}
public void run(){
clip.loop(Clip.LOOP_CONTINUOUSLY);
try{
Thread.sleep(length);
} catch(Exception e){
}
clip.stop();
}
private Clip clip;
private int length;
}
}