Home | History | Annotate | Download | only in speechrecorder
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.speechrecorder;
     18 
     19 import android.app.Activity;
     20 import android.os.Bundle;
     21 import android.os.Handler;
     22 import android.speech.srec.Recognizer;
     23 import android.speech.srec.WaveHeader;
     24 import android.speech.srec.MicrophoneInputStream;
     25 import android.util.Config;
     26 import android.util.Log;
     27 import android.view.View;
     28 import android.view.View.OnClickListener;
     29 import android.widget.Button;
     30 import android.widget.RadioButton;
     31 import android.widget.TextView;
     32 import java.io.BufferedWriter;
     33 import java.io.ByteArrayOutputStream;
     34 import java.io.File;
     35 import java.io.FileFilter;
     36 import java.io.FileOutputStream;
     37 import java.io.FileWriter;
     38 import java.io.IOException;
     39 import java.io.InputStream;
     40 import java.io.OutputStream;
     41 
     42 public class SpeechRecorderActivity extends Activity {
     43     private static final String TAG = "SpeechRecorderActivity";
     44 
     45     private static final int DURATION_SEC = 7;
     46 
     47     private Handler mHandler;
     48 
     49     private TextView mCommand;
     50     private TextView mStatus;
     51     private Button mRecord;
     52     private Button mRedo;
     53     private RadioButton m8KHz;
     54     private RadioButton m11KHz;
     55     private RadioButton mCall;
     56     private RadioButton mDialNanp;
     57     private RadioButton mDialPairs;
     58 
     59     private InputStream mMicrophone;
     60     private ByteArrayOutputStream mBaos;
     61 
     62     private File mUtterance;
     63     private int mSampleRate;
     64     private Thread mThread;
     65     private boolean mStoppedListening;
     66 
     67     @Override
     68     protected void onCreate(Bundle icicle) {
     69         super.onCreate(icicle);
     70 
     71         mHandler = new Handler();
     72 
     73         setContentView(R.layout.recorder);
     74         mCommand = (TextView) findViewById(R.id.commandText);
     75         mStatus = (TextView) findViewById(R.id.statusText);
     76         mRecord = (Button) findViewById(R.id.recordButton);
     77         mRedo = (Button) findViewById(R.id.redoButton);
     78         m8KHz = (RadioButton)findViewById(R.id.codec8KHzRadioButton);
     79         m11KHz = (RadioButton)findViewById(R.id.codec11KHzRadioButton);
     80         mCall = (RadioButton)findViewById(R.id.callRadioButton);
     81         mDialNanp = (RadioButton)findViewById(R.id.dialNanpRadioButton);
     82         mDialPairs = (RadioButton)findViewById(R.id.dialPairsRadioButton);
     83 
     84         mCommand.setText("Please click 'Record' to begin");
     85         mRecord.setOnClickListener(new OnClickListener() {
     86             public void onClick(View v) {
     87                 if (Config.LOGD) {
     88                     Log.d(TAG, "mRecord.OnClickListener.onClick");
     89                 }
     90 
     91                 setupRecording();
     92             }
     93         });
     94 
     95         mRedo.setEnabled(false);
     96         mRedo.setOnClickListener(new OnClickListener() {
     97             public void onClick(View v) {
     98                 if (Config.LOGD) {
     99                     Log.d(TAG, "mRedo.onClickListener.onClick");
    100                 }
    101 
    102                 mUtterance.delete();
    103 
    104                 setupRecording();
    105             }
    106         });
    107 
    108         m8KHz.setText("PCM/16bit/8KHz");
    109         m11KHz.setText("PCM/16bit/11KHz");
    110         m11KHz.setChecked(true);
    111         mCall.setChecked(true);
    112     }
    113 
    114     private void setupRecording() {
    115         Log.d(TAG, "setupRecording");
    116         // disable buttons
    117         mRedo.setEnabled(false);
    118         mRecord.setEnabled(false);
    119         m8KHz.setFocusable(false);
    120         m11KHz.setFocusable(false);
    121         mCall.setFocusable(false);
    122         mDialNanp.setFocusable(false);
    123         mDialPairs.setFocusable(false);
    124 
    125         // find the first utterance not covered
    126         String[] utterances = mCall.isChecked() ? mCallUtterances :
    127             mDialNanp.isChecked() ? mDialNanpUtterances :
    128             mDialPairs.isChecked() ? mDialPairsUtterances :
    129                 null;
    130         mUtterance = null;
    131         int index = -1;
    132         for (int i = 0; i < utterances.length; i++) {
    133             File u = new File(getDir("recordings", MODE_PRIVATE),
    134                     utterances[i].toLowerCase().replace(' ', '_') + ".wav");
    135             if (!u.exists()) {
    136                 mUtterance = u;
    137                 index = i;
    138                 break;
    139             }
    140         }
    141 
    142         // check if done
    143         if (mUtterance == null) {
    144             mCommand.setText("Finished: Thank You!");
    145             return;
    146         }
    147         Log.d(TAG, "going to record " + mUtterance.toString());
    148 
    149         // fix up UI
    150         mCommand.setText("Say: \"" + utterances[index] + "\"");
    151         final String status = "item " + (index + 1) + "/" + utterances.length;
    152 
    153         // start the microphone
    154         mSampleRate = m8KHz.isChecked()? 8000 :
    155                 m11KHz.isChecked() ? 11025 :
    156                 11025;
    157         mBaos = new ByteArrayOutputStream(mSampleRate * 2 * 20);
    158         try {
    159             mMicrophone = new MicrophoneInputStream(mSampleRate, mSampleRate * 15);
    160 
    161 //            mMicrophone = logInputStream(mUtterance.toString(), mMicrophone, mSampleRate);
    162         } catch (IOException e) {
    163 
    164         }
    165 
    166         // post a number of delayed events to update the UI and to stop recording
    167         // after a few seconds.
    168         for (int i = 0; i <= DURATION_SEC; i++) {
    169             final int remain = DURATION_SEC - i;
    170             mHandler.postDelayed(new Runnable() {
    171                 public void run() {
    172                     if (remain > 0) {
    173                         mStatus.setText(status + "  Recording... " + remain);
    174                     }
    175                     else {
    176                         mStatus.setText(status);
    177                         stopRecording();
    178                     }
    179                 }
    180             }, i * 1000);
    181         }
    182 
    183         // now start a thread to store the audio.
    184         mStoppedListening = false;
    185         mThread = new Thread() {
    186             public void run() {
    187                 Log.d(TAG, "run audio capture thread");
    188                 byte buffer[] = new byte[512];
    189                 while (!mStoppedListening) {
    190                     try {
    191                         int rtn = 0;
    192                         rtn = mMicrophone.read(buffer, 0, 512);
    193                         if (rtn > 0) mBaos.write(buffer, 0, rtn);
    194                     } catch (IOException e) {
    195                     }
    196                 }
    197             }
    198         };
    199         mThread.start();
    200 
    201         // to avoid the button click
    202         try {
    203             Thread.sleep(100);
    204         } catch (InterruptedException ie) {
    205         }
    206 
    207     }
    208 
    209     private void stopRecording() {
    210         Log.d(TAG, "stopRecording");
    211         mStoppedListening = true;
    212         try {
    213             mThread.join();
    214         } catch (InterruptedException e) {
    215 
    216         }
    217         try {
    218             OutputStream out = new FileOutputStream(mUtterance.toString());
    219             try {
    220                 byte[] pcm = mBaos.toByteArray();
    221                 Log.d(TAG, "byteArray length " + pcm.length);
    222                 WaveHeader hdr = new WaveHeader(WaveHeader.FORMAT_PCM,
    223                         (short)1, mSampleRate, (short)16, pcm.length);
    224                 hdr.write(out);
    225                 out.write(pcm);
    226             } finally {
    227                 out.close();
    228                 mMicrophone.close();
    229                 mBaos.close();
    230             }
    231         } catch (IOException e) {
    232 
    233 
    234         } finally {
    235         }
    236 
    237         // stop the recording
    238         mRecord.setEnabled(true);
    239 
    240         mRedo.setEnabled(true);
    241 
    242         mCommand.setText("Got it!");
    243     }
    244 
    245 
    246     private final static String[] mCallUtterances = new String[] {
    247         "Call Adam Varro",
    248         "Call Alex Lloyd",
    249         "Call Amod Karve",
    250         "Call Ana Maria Lopez",
    251         "Call Ben Sigelman",
    252         "Call Chris Vennard",
    253         "Call Dana Pogoda",
    254         "Call Daryl Pregibon",
    255         "Call Davi Robison",
    256         "Call David Barrett Kahn",
    257         "Call David Hyman",
    258         "Call Douglas Gordin",
    259         "Call Gregor Rothfuss",
    260         "Call James Sheridan",
    261         "Call Jason Charo",
    262         "Call Jeff Reynar",
    263         "Call Joel Ward",
    264         "Call John Milton",
    265         "Call Lajos Nagy",
    266         "Call Lori Sobel",
    267         "Call Martin Jansche",
    268         "Call Meghan McGarry",
    269         "Call Meghan Shakar",
    270         "Call Nilka Thomas",
    271         "Call Pedro Colijn",
    272         "Call Pramod Adiddam",
    273         "Call Rajeev Sivaram",
    274         "Call Rich Armstrong",
    275         "Call Robin Watson",
    276         "Call Sam Morales",
    277     };
    278 
    279     private final static String[] mDialPairsUtterances = new String[] {
    280         // all possible pairs
    281         "Dial 000 000 0000",
    282 
    283         "Dial 101 010 1010",
    284         "Dial 111 111 1111",
    285 
    286         "Dial 202 020 2020",
    287         "Dial 212 121 2121",
    288         "Dial 222 222 2222",
    289 
    290         "Dial 303 030 3030",
    291         "Dial 313 131 3131",
    292         "Dial 323 232 3232",
    293         "Dial 333 333 3333",
    294 
    295         "Dial 404 040 4040",
    296         "Dial 414 141 4141",
    297         "Dial 424 242 4242",
    298         "Dial 434 343 4343",
    299         "Dial 444 444 4444",
    300 
    301         "Dial 505 050 5050",
    302         "Dial 515 151 5151",
    303         "Dial 525 252 5252",
    304         "Dial 535 353 5353",
    305         "Dial 545 454 5454",
    306         "Dial 555 555 5555",
    307 
    308         "Dial 606 060 6060",
    309         "Dial 616 161 6161",
    310         "Dial 626 262 6262",
    311         "Dial 636 363 6363",
    312         "Dial 646 464 6464",
    313         "Dial 656 565 6565",
    314         "Dial 666 666 6666",
    315 
    316         "Dial 707 070 7070",
    317         "Dial 717 171 7171",
    318         "Dial 727 272 7272",
    319         "Dial 737 373 7373",
    320         "Dial 747 474 7474",
    321         "Dial 757 575 7575",
    322         "Dial 767 676 7676",
    323         "Dial 777 777 7777",
    324 
    325         "Dial 808 080 8080",
    326         "Dial 818 181 8181",
    327         "Dial 828 282 8282",
    328         "Dial 838 383 8383",
    329         "Dial 848 484 8484",
    330         "Dial 858 585 8585",
    331         "Dial 868 686 8686",
    332         "Dial 878 787 8787",
    333         "Dial 888 888 8888",
    334 
    335         "Dial 909 090 9090",
    336         "Dial 919 191 9191",
    337         "Dial 929 292 9292",
    338         "Dial 939 393 9393",
    339         "Dial 949 494 9494",
    340         "Dial 959 595 9595",
    341         "Dial 969 696 9696",
    342         "Dial 979 797 9797",
    343         "Dial 989 898 9898",
    344         "Dial 999 999 9999",
    345 
    346     };
    347 
    348 
    349     private final static String[] mDialNanpUtterances = new String[] {
    350         "Dial 211",
    351         "Dial 411",
    352         "Dial 511",
    353         "Dial 811",
    354         "Dial 911",
    355         // random numbers
    356         "Dial 653 5763",
    357         "Dial 263 9072",
    358         "Dial 202 9781",
    359         "Dial 379 8229",
    360         "Dial 874 9139",
    361         "Dial 236 0163",
    362         "Dial 656 7455",
    363         "Dial 474 5254",
    364         "Dial 348 8687",
    365         "Dial 629 8602",
    366 
    367         //"Dial 272 717 8405",
    368         //"Dial 949 516 0162",
    369         //"Dial 795 117 7190",
    370         //"Dial 493 656 3767",
    371         //"Dial 588 093 9218",
    372         "Dial 511 658 3690",
    373         "Dial 440 301 8489",
    374         "Dial 695 713 6744",
    375         "Dial 581 475 8712",
    376         "Dial 981 388 3579",
    377 
    378         "Dial 840 683 3346",
    379         "Dial 303 467 7988",
    380         "Dial 649 504 5290",
    381         "Dial 184 577 4229",
    382         "Dial 212 286 3982",
    383         "Dial 646 258 0115",
    384         "Dial 427 482 6852",
    385         "Dial 231 809 9260",
    386         "Dial 681 930 4301",
    387         "Dial 246 650 8339",
    388     };
    389 }
    390