/*****************************************************************************/ /* Framework for exercises of the lecture "IT applications in science" */ /* held at the BA-University of Cooperative Education, Stuttgart, Germany */ /* */ /* This source code is free for any kind of personal or educational use, */ /* which is absolutely non-profitable. */ /* */ /* This source code as all derivatives of it may not be used for any */ /* commercial purpose. This especially excludes any rights for claiming any */ /* kind of patents, warranty, applicability for a certain purpose, as */ /* finally for earning money on base of the before described inclusion range.*/ /* */ /* (c) 2003, Hans Weghorn, weghorn@ba-stuttgart.de */ /*---------------------------------------------------------------------------*/ /* History */ /* Date Author Description */ /* Oct. 19th, 2003 H. Weghorn Developed from scratch */ /* */ /* */ /* */ /*****************************************************************************/ // Importing required class libraries import java.awt.*; import java.awt.event.*; import java.lang.*; import javax.sound.sampled.*; // main application requires a GUI frame with threading properties public class ft_audio extends Frame implements Runnable { // general constants for audio settings final static float AUDIO_SAMPLING_RATE = 8000.0F; // Hz final static int AUDIO_SAMPLE_DEPTH = 8; // bits per sample final static int AUDIO_NO_OF_CHANNELS = 1; // 1 stands for mono final static int RECOGNITION_LENGTH = 8192; // buffer length for recog. ~ 1 sec // definition of frame size (audio signal frame as also display window) static int size_x = 512; int size_y = 256 + 2 + 100 +1; // arrays for audio processing byte[] audioInput = null; // audio data buffer consists of byte data (8 bits, mono) int[] plotCoorsX = null; // convenient ploting requires array with x-coordinates int[] plotAudioY = null; // and y coordinates in integer format int[] plotPSpecY = null; // same for power spectrum int[] patternPSpec = null; // for trained audio pattern private Graphics g = null; // further arrays for fourier analysis of input data to be defined here // ..?..?.. // // general settings entered through GUI boolean recognitionMode = false; // online or recognition mode boolean terminate = false; // end this nice application // required audio classes private static TargetDataLine m_targetLine; private static SourceDataLine m_sourceLine; //-------------------------------------------------------------------------- // Main method for the first excercise task (2nd task below): "Online FT" // - Implement the Fourier transform for the audio stream // - Calculate the power spectrum // - Display the power spectrum // Advice: Implement integer Fourier transform on base of sine tables; // consider the input number range is signed 8 bit, while for the power // spectrum 32 bit integers can be used. //-------------------------------------------------------------------------- public void run () { int length = -1; // actual processing frame size boolean mode = false; // actual processing mode int counter = 0; // for diagnostic purpose // prepare audio operation prepareRTgeneral (); // endless loop terminated by GUI input while ( !terminate ) { // check for mode or size change events -> if reqd apply modifications if ( length != size_x || mode != recognitionMode ) { if ( mode=recognitionMode ) { prepareRTrecognition (); } else { prepareRTonline (); length = size_x; counter = 0; } } // perform audio loop processing else { if ( mode ) { // recognition mode of audio signal processing // do nothing during recognition mode (everything under button control!!) try { Thread.sleep ( 100 ); } catch (InterruptedException ie) { ie = null; } } else { // online display mode for audio signal and FT int nBytesRead = m_targetLine.read ( audioInput, 0, length ); for ( int i=0; i= length ) counter =0; g.setColor ( Color.lightGray ); g.fillRect ( 0, 129, length, 256 ); g.translate ( 0, 130 ); g.setColor ( Color.magenta ); g.drawPolyline ( plotCoorsX, plotPSpecY, length ); g.translate ( 0, -130 ); } } } myFrame.dispose (); System.exit (0); } //-------------------------------------------------------------------------- // Two main methods for the second excercise task: Speech recognition // - Implement training method // - Implement evaluation of audio input // Hint: use faster FT developed for the 1st task //-------------------------------------------------------------------------- // method for learning audio signal patterns private void learnPattern ( boolean flag ) { disableGUI(); if ( flag ) { // in this case discard existing pattern if ( patternPSpec == null ) System.exit (2); // Internal error ?!?!? for ( int i=0; i= threshold ) { System.out.println ( "Bingo! This pattern was accepted!" ); cbResult.setState ( true ); } else { cbResult.setState ( false ); } enableGUI(); } //-------------------------------------------------------------------------- // End of section relevant for the exercise tasks //-------------------------------------------------------------------------- private void prepareRTgeneral () { m_targetLine.start(); m_sourceLine.start(); } private void prepareRTonline () { myFrame.remove ( pUI ); myFrame.setSize ( size_x, size_y ); audioInput = new byte[2*size_x]; plotCoorsX = new int[size_x]; plotAudioY = new int[size_x]; plotPSpecY = new int[size_x]; for ( int i=0; i>1; g.drawLine ( x, 0, x, y ); } } }; ((Canvas) myC).setSize ( 256, 130 ); dP.add ( (Canvas) myC, "Center" ); dP.pack (); dP.show (); } // top-level menu bar MenuBar menubar = new MenuBar (); // File menu Menu menuFunction = new Menu ( "Function" ); MenuItem miOnline = new MenuItem ( "Online FT" ); MenuItem miProcessing = new MenuItem ( "Recognition" ); MenuItem miExit = new MenuItem ( "Exit" ); // Size menu Menu menuSize = new Menu ( "Frame size" ); CheckboxMenuItem cbmi256 = new CheckboxMenuItem ( "256", false ); CheckboxMenuItem cbmi512 = new CheckboxMenuItem ( "512", true ); CheckboxMenuItem cbmi1k = new CheckboxMenuItem ( "1024", false ); Panel pUI = new Panel (); Button bLearn = new Button ( "Learn Pattern" ); Button bClear = new Button ( "Clear Pattern" ); Button bTest = new Button ( "Listen & Recognize" ); TextField tfThreshold = new TextField ( "0.5" ); TextField tfCorrelation = new TextField ( " " ); Checkbox cbResult = new Checkbox ( "recognized", false ); Frame myFrame = null; // contructor sets up intial appearance of GUI frame public ft_audio () { myFrame = this; // build up function menu menuFunction.add ( miOnline ); menuFunction.add ( miProcessing ); menuFunction.addSeparator (); menuFunction.add ( miExit ); miOnline.setShortcut ( new MenuShortcut('O') ); miProcessing.setShortcut ( new MenuShortcut('P') ); // build up frame size menu menuSize.add ( cbmi256 ); menuSize.add ( cbmi512 ); menuSize.add ( cbmi1k ); // assemble menu bar, set short cuts, and attach it to the frame menubar.add ( menuFunction ); //menubar.add ( menuSize ); menuFunction.setShortcut ( new MenuShortcut('F') ); setMenuBar ( menubar ); // window closing events from window manager (WM) this.addWindowListener ( new WindowAdapter () { public void windowClosing ( WindowEvent we ) { //myFrame.dispose (); System.exit (0); terminate = true; } } ); // exit menu activation miExit.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent ae ) { //myFrame.dispose(); System.exit (0); terminate = true; } }); // online menu activation miOnline.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent ae ) { recognitionMode = false; } }); // recognition menu activation miProcessing.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent ae ) { recognitionMode = true; } }); // size event activation cbmi256.addItemListener ( new ItemListener () { public void itemStateChanged ( ItemEvent ie ) { if ( cbmi256.getState() ) { cbmi512.setState ( false ); cbmi1k.setState ( false ); size_x = 256; } } }); cbmi512.addItemListener ( new ItemListener () { public void itemStateChanged ( ItemEvent ie ) { if ( cbmi512.getState() ) { cbmi256.setState ( false ); cbmi1k.setState ( false ); size_x = 512; } } }); cbmi1k.addItemListener ( new ItemListener () { public void itemStateChanged ( ItemEvent ie ) { if ( cbmi1k.getState() ) { cbmi256.setState ( false ); cbmi512.setState ( false ); size_x = 1024; } } }); // assemble panel for recognition mode pUI.setBackground ( new Color ( 176, 196, 222 ) ); pUI.setLayout ( new FlowLayout () ); pUI.add ( bLearn ); pUI.add ( bClear ); pUI.add ( tfThreshold ); pUI.add ( bTest ); pUI.add ( tfCorrelation ); tfCorrelation.setEditable ( false ); pUI.add ( cbResult ); cbResult.setEnabled(false); // fill control buttons with life bLearn.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent ae ) { learnPattern ( false ); } }); bClear.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent ae ) { learnPattern ( true ); } }); bTest.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent ae ) { double threshold; try { threshold = Double.parseDouble ( tfThreshold.getText() ); } catch ( NumberFormatException inf ) { threshold = 0.5; tfThreshold.setText ( "0.5" ); } compareAudioSignal ( threshold ); } }); this.setTitle ( "Audio tool" ); this.setSize ( size_x, size_y ); this.setResizable ( false ); this.show (); } // main entry for preparing audio actions, and launching GUI window public static void main ( String[] args ) { AudioFormat audioFormat = new AudioFormat ( AudioFormat.Encoding.PCM_SIGNED, AUDIO_SAMPLING_RATE, AUDIO_SAMPLE_DEPTH, AUDIO_NO_OF_CHANNELS, (AUDIO_NO_OF_CHANNELS*AUDIO_SAMPLE_DEPTH/8), AUDIO_SAMPLING_RATE, false ); try { DataLine.Info targetInfo = new DataLine.Info(TargetDataLine.class, audioFormat, size_x ); DataLine.Info sourceInfo = new DataLine.Info(SourceDataLine.class, audioFormat, size_x ); m_targetLine = (TargetDataLine) AudioSystem.getLine(targetInfo); m_sourceLine = (SourceDataLine) AudioSystem.getLine(sourceInfo); m_targetLine.open ( audioFormat, size_x ); m_sourceLine.open ( audioFormat, size_x ); } catch (LineUnavailableException e) { e.printStackTrace(); System.exit(1); } (new Thread ( new ft_audio () )).start(); } }