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>
Binary file lib/jtransforms-2.0.jar has changed
--- /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: 
+	 *
+	 */
+
+}