Change Audio Source for Speech Recognition - Android

268 views Asked by At

The problem is that we are using an HDMI capture device to renderer frame and audio. The device uses UAC protocol which is registered as an input audio device and selected as the default source of input for the speech engine. We want to change the input audio source for the speech engine to use the built-in bottom microphone or back CAMCORDER microphone.

There are limited resources available on the internet. Few related questions

  1. Android Speech Recognition Custom Audio Source
  2. Android speech recognizing and audio recording in the same time

We have tried the following code. The below solution is inspired by Github.com/KieronQuinn/AmbientMusicMod

This code muting the source for the speech engine, but not working!

val SAMPLE_RATE = 44100
        val CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO
        val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
//        val bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT)

        val audioRecord = AudioRecord.Builder()
            .setAudioSource(MediaRecorder.AudioSource.CAMCORDER)
            .setAudioFormat(AudioFormat.Builder()
                .setEncoding(AUDIO_FORMAT)
                .setSampleRate(SAMPLE_RATE)
                .setChannelMask(CHANNEL_CONFIG)
                .build())
//            .setBufferSizeInBytes(bufferSize)
            .build()

        val fileDescriptors = ParcelFileDescriptor.createReliablePipe()
        val clientRead = fileDescriptors[0]
        audioRecord.startRecording()

        Thread {

            try {
//                        datagramSocket.send(datagramPacket)
                val audioSink = fileDescriptors[1]
                ParcelFileDescriptor.AutoCloseOutputStream(audioSink).use { fos ->
                    val buffer = ByteArray(audioRecord.bufferSizeInFrames)
                    while (isListening) {
                        val bytesRead =
                            audioRecord.read(buffer, 0, buffer.size, AudioRecord.READ_BLOCKING)
                        if (bytesRead > 0) {

//                        datagramSocket.send(datagramPacket)

                            fos.write(buffer)

                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }


            audioRecord.stop()
            audioRecord.release()
        }.start()

        speechIntent.putExtra("android.speech.extra.AUDIO_SOURCE", clientRead)
        speechIntent.putExtra("android.speech.extra.AUDIO_SOURCE_ENCODING", AUDIO_FORMAT)
        speechIntent.putExtra("android.speech.extra.AUDIO_SOURCE_SAMPLING_RATE", SAMPLE_RATE)
        speechIntent.putExtra("android.speech.extra.AUDIO_SOURCE_CHANNEL_COUNT", CHANNEL_CONFIG)
        speechRecognizer.startListening(speechIntent)

Android 13 Google Speech Recognition v20230807 Google Groups Thread

Or

Any workaround to disable automatic routing to USB audio peripherals programmatically!?

1

There are 1 answers

0
Qamar On

Your app should have WRITE_SECURE_SETTINGS permission granted. Then call Settings.Secure.putInt(context.getContentResolver(), "usb_audio_automatic_routing_disabled", 1). – Irfan Latif

We can grant WRITE_SECURE_SETTINGS permission with the following ADB command.

adb shell pm grant app.package.name android.permission.WRITE_SECURE_SETTINGS

Read more here (USB-audio)

Side note

For now, this is the only workaround to our problem. I hope Google/AOSP will consider the case.