Mercurial > hg > Members > kent > SpectrumViewer
changeset 0:5c6db5d47717 default tip
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 09 Dec 2008 15:04:03 +0900 |
parents | |
children | |
files | build.xml lib/jtransforms-2.0.jar src/AudioListener.java src/Plotter.java src/SpectrumViewer.java |
diffstat | 5 files changed, 340 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build.xml Tue Dec 09 15:04:03 2008 +0900 @@ -0,0 +1,52 @@ +<project name="MyProject" default="dist" basedir="."> + <description> + show speech signal and spectrum. + </description> + + <!-- set global properties for this build --> + <property name="src" location="src"/> + <property name="build" location="build"/> + <property name="lib" location="lib"/> + + <!-- set classpath refference --> + <path id="project.classpath"> + <pathelement path="build"/> + <pathelement location="${lib}/jtransforms-2.0.jar"/> + </path> + + <!-- initialization --> + <target name="init"> + <!-- Create the time stamp --> + <tstamp/> + <!-- Create the build directory structure used by compile --> + <mkdir dir="${build}"/> + </target> + + <!-- build --> + <target name="compile" depends="init" description="compile the source " > + <!-- Compile the java code from ${src} into ${build} --> + <javac srcdir="${src}" destdir="${build}"> + <classpath refid="project.classpath"/> + </javac> + </target> + + <!-- execution --> + <target name="run" depends="compile" description="test run" > + <java dir="${build}" fork="true" classname="SpectrumViewer"> + <classpath refid="project.classpath"/> + </java> + </target> + + <!-- miscs --> + <target name="demo" description="sample program for java.sound" > + <mkdir dir="sun-demo"/> + <get dest="sun-demo/JavaSoundDemo.zip" src="http://java.sun.com/products/java-media/sound/samples/JavaSoundDemo.zip"/> + </target> + + <!-- cleanup --> + <target name="clean" + description="clean up" > + <!-- Delete the ${build} and ${dist} directory trees --> + <delete dir="${build}"/> + </target> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/AudioListener.java Tue Dec 09 15:04:03 2008 +0900 @@ -0,0 +1,126 @@ + +import javax.sound.sampled.*; +import java.lang.Runnable; +import java.lang.Math; +import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D; + +public class AudioListener implements Runnable { + private int frameLength; + private Plotter plotter; + private Plotter sprPlotter; + private AudioFormat format; + private boolean runnable=true; + private Thread thread; + private FloatFFT_1D fft; + private double[] window; + + public AudioListener(AudioFormat af, Plotter plotter, Plotter sprPlotter, int fps, boolean windowOn) { + assert af.getSampleRate()%fps==0; + this.frameLength = (int)af.getSampleRate()/fps; + this.plotter = plotter; + this.sprPlotter = sprPlotter; + this.format = af; + this.fft = new FloatFFT_1D(frameLength); + this.window = new double[frameLength]; + for (int i=0; i<frameLength; i++) { + if (windowOn) + window[i] = Math.exp( -Math.pow((((double)i-frameLength/2.0)/(frameLength/2.0)*5),2) /4.0); + else + window[i] = 1; + //window[i] = ( -Math.pow((((double)i-frameLength/2.0)/(frameLength/2.0)*5),2) /4.0); + } + } + + public void start() { + thread = new Thread(this); + thread.start(); + } + + public void run() { + int count=0; + TargetDataLine line; + //format = formatControls.getFormat(); + + /* こいつが3つものthreadを生成している? */ + DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); + if (!AudioSystem.isLineSupported(info)) { + System.out.println("Line matching " + info + " not supported."); + return; + } + + // get and open the source data line for playback. + try { + line = (TargetDataLine) AudioSystem.getLine(info); + System.out.println("You can access the line"); + line.open(format, frameLength*5); + } catch (Exception ex) { + System.err.println("Unable to open the line: " + ex); + return; + } + + /* main loop. */ + line.start(); + byte[] data = new byte[frameLength]; + byte[] spectrum = new byte[frameLength/2]; + while (runnable) { + int numByte; + numByte = line.read(data, 0, data.length); + if (numByte==-1) { + System.err.println("error"); + break; + } + + computeSpectrum(data, spectrum); + plotter.setData(data); + plotter.repaint(); + sprPlotter.setData(spectrum); + sprPlotter.repaint(); + count++; + } + + line.stop(); + line.flush(); + line.close(); + System.out.println("count: "+count); + + } + + public void stop() { + runnable=false; + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("thread end"); + } + + public void computeSpectrum(byte[] input, byte[] output) { + float[] data = new float[2*frameLength]; + + /* windowing */ + /* + * w(t) = exp(-x^2/o^2) + * w(t) = exp( -(x-5)^2 / 2^2 ) 0<x<10 + */ + + for (int i=0; i<frameLength; i++) { + data[2*i] = (float)input[i] * (float)window[i]; + /* windowing */ + data[2*i+1] = 0; + } + + /* Fast Fourier Transform */ + fft.complexForward(data); + + for (int i=0; i<frameLength/2; i++) { + //double tmp = java.lang.Math.hypot(data[2*i],data[2*i+1]); + double tmp = data[2*i]*data[2*i]+data[2*i+1]*data[2*i+1]; + //output[i] = (byte)java.lang.Math.log10(tmp); + output[i] = (byte)(tmp/(float)frameLength); + } + } + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Plotter.java Tue Dec 09 15:04:03 2008 +0900 @@ -0,0 +1,49 @@ + +import java.awt.*; + +public class Plotter extends Canvas { + private int maxValue, minValue; + private Canvas canvas; + private byte[] data; + + + public Plotter(int minValue, int maxValue) { + this.minValue=minValue; + this.maxValue=maxValue; + } + + public void paint(Graphics g) { + g.drawRoundRect(0,0, getWidth(), getHeight(), 5, 5); + if (data==null || data.length==0) return; + + int size = data.length; + int height = getHeight(); + float xstep = (float)this.getWidth()/(float)size; + float p = (float)height/((float)maxValue-(float)minValue); + + // first value + float value=(float)height - (data[0]-minValue)*p; + + for (int i=1; i<size; i++) { + float prevValue; + prevValue = value; + value = (float)height - (data[i]-minValue)*p; + assert value<=height; + assert value>0; + + g.drawLine( (int)((i-1)*xstep), (int)prevValue, (int)((i)*xstep), (int)value); + } + } + /* + * Heigh - (value-minV)/(maxV-minV)*Height + * = (Height+/ + */ + + public void setData(byte[] data) { + this.data = data; + } +} + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/SpectrumViewer.java Tue Dec 09 15:04:03 2008 +0900 @@ -0,0 +1,113 @@ +import java.awt.*; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.awt.event.WindowListener; +import java.awt.event.WindowEvent; +import javax.sound.sampled.*; + +public class SpectrumViewer extends Frame { + private Plotter plotter; + private Plotter sprPlotter; + private Container controler; + private AudioListener audioListener; + private Button startButton; + private Button stopButton; + + public static void main(String[] args) throws Exception{ + SpectrumViewer mw = new SpectrumViewer(); + mw.setVisible(true); + } + + public SpectrumViewer() { + super("mainwindow"); + setSize(400, 600); + //setLayout(new BorderLayout()); + setLayout(new BorderLayout()); + + /* startButton */ + startButton = new Button("Start"); + startButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + SpectrumViewer.this.startAudioListener(); + } + }); + /* stopButton */ + stopButton = new Button("Stop"); + stopButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + SpectrumViewer.this.stopAudioListener(); + } + }); + //stopButton.setVisible(false); + + /* control panel */ + controler = new Container(); + controler.setLayout(new BorderLayout()); + controler.add(startButton, BorderLayout.EAST); + controler.add(stopButton, BorderLayout.WEST); + + plotter = new Plotter(-128, 127); + sprPlotter = new Plotter(0, 127); + Container tmp = new Container(); + tmp.setLayout(new GridLayout(2,1)); + tmp.add(plotter); + tmp.add(sprPlotter); + + /* Frame set */ + //add(plotter, BorderLayout.SOUTH); + //add(sprPlotter, BorderLayout.CENTER); + //add(controler, BorderLayout.NORTH); + //add(plotter); + //add(sprPlotter); + add(tmp, BorderLayout.CENTER); + add(controler, BorderLayout.NORTH); + addWindowListener(new WindowListener() { + public void windowActivated(WindowEvent e){ } + public void windowClosed(WindowEvent e){ } + public void windowDeactivated(WindowEvent e){ } + public void windowDeiconified(WindowEvent e){ } + public void windowIconified(WindowEvent e){ } + public void windowOpened(WindowEvent e){ } + public void windowClosing(WindowEvent e){ + System.out.println("exit"); + System.exit(0); + } + }); + } + + public void startAudioListener() { + AudioFormat format; + //format = new AudioFormat(8000, 8, 1, true, true); + format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, + 16000, 8, 1, 1, 16000, true); + audioListener = new AudioListener(format, plotter, sprPlotter, 50,true); + audioListener.start(); + System.out.println("start button was clicked"); + System.out.println("frame rate: "+format.getFrameRate()); + System.out.println("frame size: "+format.getFrameSize()); + //System.out.println("property: "+format.getProperty()); + System.out.println("sample rate: "+format.getSampleRate()); + System.out.println("sample bits: "+format.getSampleSizeInBits()); + System.out.println("big endian: "+format.isBigEndian()); + //controler.remove(startButton); + //controler.add(stopButton); + } + public void stopAudioListener() { + audioListener.stop(); + audioListener=null; + System.out.println("stop button was clicked"); + //stopButton.setVisible(false); + //controler.remove(stopButton); + //controler.add(startButton); + } + /* + * AudioFormat( encoding, sampleRate, sampleSizeInBits, + * channels, frameSize, frameRate, bigEndian) + * sampleRate: 1秒間の1チャネル毎のサンプリング周波数 8000, 44100 + * sampleSizeInBits: 1サンプルのbit数 8, 16 + * channels: the number of channels 1(mono) or 2(stereo) + * frameSize: + * + */ + +}