同时使用语音识别和可视化工具

时间:2016-10-31 14:19:20

标签: speech-recognition microphone pocketsphinx pocketsphinx-android

目前我正在使用pocketsphinx进行语音识别&一个可视化器,用于显示我在麦克风中说出的音频波形 但是,我一次只能运行一件事。因为麦克风将由可视化工具使用,语音识别中没有任何反应。请查看我的代码和帮我同时运行它们

主要活动

public class MainActivity extends AppCompatActivity implements RecognitionListener {

    //for visualizer permission android 6
    private boolean permissionToWriteAccepted = false;
    private String [] permissions = {"android.permission.RECORD_AUDIO", "android.permission.WRITE_EXTERNAL_STORAGE"};



    //Name searches allow to quickly reconfigure the decoder

    private static final String SENTENCE_SEARCH = "sentence";

    //used to handle permission request

    private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;

    private SpeechRecognizer recognizer;
    // private Snackbar snackbar;

    //for visualizer


    public static final String DIRECTORY_NAME_TEMP = "AudioTemp";
    public static final int REPEAT_INTERVAL = 40;
    // private TextView txtRecord;

    VisualizerView visualizerView;

    private MediaRecorder recorder = null;

    File audioDirTemp;
    private boolean isRecording = false;


    private Handler handler; // Handler for updating the visualizer
    // private boolean recording; // are we currently recording?

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        visualizerView = (VisualizerView) findViewById(R.id.visualizer);

        // Add the following code to your onCreate
        int requestCode = 200;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(permissions, requestCode);
        }


        // Check if user has given permission to record audio
        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
        if (permissionCheck == PackageManager.PERMISSION_DENIED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
            return;
        }


        //directory for the audio recorder
        audioDirTemp = new File(Environment.getExternalStorageDirectory(),
                DIRECTORY_NAME_TEMP);
        if (audioDirTemp.exists()) {
            deleteFilesInDir(audioDirTemp);
        } else {
            audioDirTemp.mkdirs();
        }

        // create the Handler for visualizer update
        handler = new Handler();


        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                runRecognizerSetup();



                if (!isRecording) {
                    // isRecording = true;

                    //  txtRecord.setText("Stop Recording");

                    recorder = new MediaRecorder();

                    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    recorder.setOutputFile(audioDirTemp + "/audio_file"
                            + ".mp3");

                    MediaRecorder.OnErrorListener errorListener = null;
                    recorder.setOnErrorListener(errorListener);
                    MediaRecorder.OnInfoListener infoListener = null;
                    recorder.setOnInfoListener(infoListener);

                    try {
                        recorder.prepare();
                        recorder.start();
                        isRecording = true; // we are currently recording
                    } catch (IllegalStateException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    handler.post(updateVisualizer);

                } else {

                    // txtRecord.setText("Start Recording");

                    releaseRecorder();
                }


                Snackbar.make(view, "Pleas speak clearly to the microphone", Snackbar.LENGTH_INDEFINITE)
                        .setAction("DISMISS", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {

                            }
                        }).show();


               // runRecognizerSetup();

            }
        });


        //first textbox

        ((TextView) findViewById(R.id.caption_text)).setText("Speak in Nepali");


        //run the recognizer

        //  runRecognizerSetup();


    }

    //for visualizer
    private void releaseRecorder() {
        if (recorder != null) {
            isRecording = false; // stop recording
            handler.removeCallbacks(updateVisualizer);
            visualizerView.clear();
            recorder.stop();
            recorder.reset();
            recorder.release();
            recorder = null;
        }
    }

    //for VIsualizer

    public static boolean deleteFilesInDir(File path) {

        if (path.exists()) {
            File[] files = path.listFiles();
            if (files == null) {
                return true;
            }
            for (int i = 0; i < files.length; i++) {

                if (files[i].isDirectory()) {

                } else {
                    files[i].delete();
                }
            }
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        switch (requestCode){
            case 200:
               // permissionToRecordAccepted  = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                permissionToWriteAccepted  = grantResults[1] == PackageManager.PERMISSION_GRANTED;
                break;
        }

        if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                runRecognizerSetup();
            } else {
                finish();
            }
        }
    }


    private void runRecognizerSetup() {
        //execute it as a async task as it is time consuming

        new AsyncTask<Void, Void, Exception>() {
            @Override
            protected Exception doInBackground(Void... params) {
                try {
                    Assets assets = new Assets(MainActivity.this);
                    File assetsDir = assets.syncAssets();
                    setupRecognizer(assetsDir);

                } catch (IOException e) {
                    return e;
                }
                return null;
            }

            @Override
            protected void onPostExecute(Exception e) {
                if (e != null) {
                    ((TextView) findViewById(R.id.caption_text))
                            .setText("Failed " + e);
                } else {
                    switchSearch(SENTENCE_SEARCH);
                }
            }
        }.execute();
    }

    private void switchSearch(String searchName) {
        recognizer.stop();
        searchName = SENTENCE_SEARCH;
        recognizer.startListening(searchName, 2000);

    }


    private void setupRecognizer(File assetsDir) throws IOException {

        //SET UP THE FILE to be recognized

        recognizer = SpeechRecognizerSetup.defaultSetup()
                .setAcousticModel(new File(assetsDir, "loadshedding.ci_cont"))
                .setDictionary(new File(assetsDir, "loadshedding.dict"))
                .getRecognizer();
        recognizer.addListener(this);

        //for grammar
//
//        File sentenceGrammar = new File(assetsDir,"loadshedding.gram");
//        recognizer.addGrammarSearch(SENTENCE_SEARCH,sentenceGrammar);

        //for continuous model

        File languageModel = new File(assetsDir, "loadshedding.lm.DMP");
        recognizer.addNgramSearch(SENTENCE_SEARCH, languageModel);


    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBeginningOfSpeech() {

    }

    @Override
    public void onEndOfSpeech() {
        if (!recognizer.getSearchName().equals(SENTENCE_SEARCH))
            switchSearch(SENTENCE_SEARCH);
        Toast.makeText(this, "onEndofSpeech", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onPartialResult(Hypothesis hypothesis) {
        if (hypothesis == null)
            return;

        String text = hypothesis.getHypstr();
        ((TextView) findViewById(R.id.result_text)).setText(text);
        Toast.makeText(this, "onPartialResult", Toast.LENGTH_SHORT).show();


    }

    @Override
    public void onResult(Hypothesis hypothesis) {
//
//        if (hypothesis ==null)
//            return;
//
//        String text = hypothesis.getHypstr();
//        ((TextView)findViewById(R.id.result_text)).setText(text);


//        ((TextView) findViewById(R.id.result_text)).setText("");
//        Toast.makeText(this,"onResult",Toast.LENGTH_SHORT).show();


    }

    @Override
    public void onError(Exception e) {
        ((TextView) findViewById(R.id.caption_text)).setText(e.getMessage());

    }

    @Override
    public void onTimeout() {
        switchSearch(SENTENCE_SEARCH);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (recognizer != null) {
            recognizer.cancel();
            recognizer.shutdown();
        }

        releaseRecorder();
    }

    // updates the visualizer every 50 milliseconds
    Runnable updateVisualizer = new Runnable() {
        @Override
        public void run() {
            if (isRecording) // if we are already recording
            {
                // get the current amplitude
                int x = recorder.getMaxAmplitude();
                visualizerView.addAmplitude(x); // update the VisualizeView
                visualizerView.invalidate(); // refresh the VisualizerView

                // update in 40 milliseconds
                handler.postDelayed(this, REPEAT_INTERVAL);
            }
        }
    };
}

这是可视化工具视图

public class VisualizerView extends View {
    private static final int LINE_WIDTH = 1; // width of visualizer lines
    private static final int LINE_SCALE = 75; // scales visualizer lines
    private List<Float> amplitudes; // amplitudes for line lengths
    private int width; // width of this View
    private int height; // height of this View
    private Paint linePaint; // specifies line drawing characteristics

    // constructor
    public VisualizerView(Context context, AttributeSet attrs) {
        super(context, attrs); // call superclass constructor
        linePaint = new Paint(); // create Paint for lines
        linePaint.setColor(Color.GREEN); // set color to green
        linePaint.setStrokeWidth(LINE_WIDTH); // set stroke width
    }

    // called when the dimensions of the View change
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        width = w; // new width of this View
        height = h; // new height of this View
        amplitudes = new ArrayList<Float>(width / LINE_WIDTH);
    }

    // clear all amplitudes to prepare for a new visualization
    public void clear() {
        amplitudes.clear();
    }

    // add the given amplitude to the amplitudes ArrayList
    public void addAmplitude(float amplitude) {
        amplitudes.add(amplitude); // add newest to the amplitudes ArrayList

        // if the power lines completely fill the VisualizerView
        if (amplitudes.size() * LINE_WIDTH >= width) {
            amplitudes.remove(0); // remove oldest power value
        }
    }

    // draw the visualizer with scaled lines representing the amplitudes
    @Override
    public void onDraw(Canvas canvas) {
        int middle = height / 2; // get the middle of the View
        float curX = 0; // start curX at zero

        // for each item in the amplitudes ArrayList
        for (float power : amplitudes) {
            float scaledHeight = power / LINE_SCALE; // scale the power
            curX += LINE_WIDTH; // increase X by LINE_WIDTH

            // draw a line representing this item in the amplitudes ArrayList
            canvas.drawLine(curX, middle + scaledHeight / 2, curX, middle
                    - scaledHeight / 2, linePaint);
        }
    }

}

这是布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/content_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main"
    tools:context="pannam.loadsheddingfinal.MainActivity">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:padding="16dp" >

        <TextView
            android:id="@+id/caption_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:typeface="sans" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"

            android:layout_weight="1"
            android:gravity="center" >

            <TextView
                android:id="@+id/result_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium" />
        </LinearLayout>
        <pannam.loadsheddingfinal.VisualizerView
            android:id="@+id/visualizer"
            android:layout_width="220dp"
            android:layout_height="75dp"
            android:layout_centerHorizontal="true"
            android:layout_margin="5dp"
             />
    </LinearLayout>
</RelativeLayout>

1 个答案:

答案 0 :(得分:0)

如果没有语音识别器类修改,您无法做到这两件事。您需要将SpeechRecognizer类复制到源并进行修改。例如,您可以使用每个部分结果发送有关幅度的消息:

decoder.processRaw(buffer, nread, false, false);
// This is a code to add together with new AmplitudeEvent
int max = 0;
for (int i = 0; i < nread; i++) {
     max = Math.max(max, Math.abs(buffer[i]));
}         
mainHandler.post(new AmplitudeEvent(max));

final Hypothesis hypothesis = decoder.hyp();
mainHandler.post(new ResultEvent(hypothesis, false));

...

private class AmplitudeEvent extends RecognitionEvent {
    private final int amplitude;

    Amplitude(int amplitude) {
        this.amplitude = amplitude;
    }

    @Override
    protected void execute(RecognitionListener listener) {
        listener.onAmplitude(amplitude);
    }
}