-2

Given I have searched for days, and couldn't find anything, I came here for help.

Is there any way to find the audio device list PocketSphinx is using to input the correct one, instead of having to guess by performance in python?

Manu1800
  • 145
  • 7
  • you can't say which one is correct if you don't test it. – furas Jun 18 '21 at 13:52
  • yes, but is there any way that I can print the audio devices, or at least know which one is the right one? – Manu1800 Jun 18 '21 at 16:52
  • I don't know if it has this function but PocketSphinx is used by [SpeechRecognition](https://github.com/Uberi/speech_recognition) which has `speech_recognition.Microphone.list_microphone_names()` – furas Jun 18 '21 at 18:39
  • in `SpeechRecognition ` source code I found [list_microphone_names](https://github.com/Uberi/speech_recognition/blob/master/speech_recognition/__init__.py#L115) and it uses module `PyAudio` to get this list. There is also function [list_working_microphones](https://github.com/Uberi/speech_recognition/blob/master/speech_recognition/__init__.py#L133). You could copy this code to your project. – furas Jun 18 '21 at 18:47

1 Answers1

0

I don't know if it has this function but PocketSphinx is used by SpeechRecognition which has list_microphone_names() and even list_working_microphones()

It uses module pyaudio to get this list. And module audioop to test it.

If you copy this code

(I added import audioop inside list_working_microphones)

class Microphone():
    
    @staticmethod
    def get_pyaudio():
        """
        Imports the pyaudio module and checks its version. Throws exceptions if pyaudio can't be found or a wrong version is installed
        """
        try:
            import pyaudio
        except ImportError:
            raise AttributeError("Could not find PyAudio; check installation")
        from distutils.version import LooseVersion
        if LooseVersion(pyaudio.__version__) < LooseVersion("0.2.11"):
            raise AttributeError("PyAudio 0.2.11 or later is required (found version {})".format(pyaudio.__version__))
        return pyaudio

    @staticmethod
    def list_microphone_names():
        """
        Returns a list of the names of all available microphones. For microphones where the name can't be retrieved, the list entry contains ``None`` instead.
        The index of each microphone's name in the returned list is the same as its device index when creating a ``Microphone`` instance - if you want to use the microphone at index 3 in the returned list, use ``Microphone(device_index=3)``.
        """
        audio = Microphone.get_pyaudio().PyAudio()
        try:
            result = []
            for i in range(audio.get_device_count()):
                device_info = audio.get_device_info_by_index(i)
                result.append(device_info.get("name"))
        finally:
            audio.terminate()
        return result

    @staticmethod
    def list_working_microphones():
        """
        Returns a dictionary mapping device indices to microphone names, for microphones that are currently hearing sounds. When using this function, ensure that your microphone is unmuted and make some noise at it to ensure it will be detected as working.
        Each key in the returned dictionary can be passed to the ``Microphone`` constructor to use that microphone. For example, if the return value is ``{3: "HDA Intel PCH: ALC3232 Analog (hw:1,0)"}``, you can do ``Microphone(device_index=3)`` to use that microphone.
        """

        import audioop   # <-- added 

        pyaudio_module = Microphone.get_pyaudio()
        audio = pyaudio_module.PyAudio()
        try:
            result = {}
            for device_index in range(audio.get_device_count()):
                device_info = audio.get_device_info_by_index(device_index)
                device_name = device_info.get("name")
                assert isinstance(device_info.get("defaultSampleRate"), (float, int)) and device_info["defaultSampleRate"] > 0, "Invalid device info returned from PyAudio: {}".format(device_info)
                try:
                    # read audio
                    pyaudio_stream = audio.open(
                        input_device_index=device_index, channels=1, format=pyaudio_module.paInt16,
                        rate=int(device_info["defaultSampleRate"]), input=True
                    )
                    try:
                        buffer = pyaudio_stream.read(1024)
                        if not pyaudio_stream.is_stopped(): pyaudio_stream.stop_stream()
                    finally:
                        pyaudio_stream.close()
                except Exception:
                    continue

                # compute RMS of debiased audio
                energy = -audioop.rms(buffer, 2)
                energy_bytes = chr(energy & 0xFF) + chr((energy >> 8) & 0xFF) if bytes is str else bytes([energy & 0xFF, (energy >> 8) & 0xFF])  # Python 2 compatibility
                debiased_energy = audioop.rms(audioop.add(buffer, energy_bytes * (len(buffer) // 2), 2), 2)

                if debiased_energy > 30:  # probably actually audio
                    result[device_index] = device_name
        finally:
            audio.terminate()
        return result

Then you can use it

 Microphone.list_microphone_names()

Result on my Linux Mint

['HDA Intel MID: ALC272X Analog (hw:0,0)',
 'HDA Intel MID: ALC272X Digital (hw:0,1)',
 'HDA Intel MID: ALC272X Alt Analog (hw:0,2)',
 'HDA ATI HDMI: 0 (hw:1,3)',
 'sysdefault',
 'front',
 'surround40',
 'surround51',
 'surround71',
 'iec958',
 'spdif',
 'samplerate',
 'speexrate',
 'pulse',
 'upmix',
 'vdownmix',
 'dmix',
 'default']

If in list_microphone_names you replace device_info.get("name") with device_info then you can get more information but I don't know if they useful for you

[{'defaultHighInputLatency': 0.034829931972789115,
  'defaultHighOutputLatency': 0.034829931972789115,
  'defaultLowInputLatency': 0.008707482993197279,
  'defaultLowOutputLatency': 0.008707482993197279,
  'defaultSampleRate': 44100.0,
  'hostApi': 0,
  'index': 0,
  'maxInputChannels': 2,
  'maxOutputChannels': 2,
  'name': 'HDA Intel MID: ALC272X Analog (hw:0,0)',
  'structVersion': 2},
 {'defaultHighInputLatency': -1.0,
  'defaultHighOutputLatency': 0.034829931972789115,
  'defaultLowInputLatency': -1.0,
  'defaultLowOutputLatency': 0.008707482993197279,
  'defaultSampleRate': 44100.0,
  'hostApi': 0,
  'index': 1,
  'maxInputChannels': 0,
  'maxOutputChannels': 2,
  'name': 'HDA Intel MID: ALC272X Digital (hw:0,1)',
  'structVersion': 2},

  # ...etc...

Of course you could reduce this code and use directly pyaudio


I tested also list_working_microphones() but in some moment it crashed on some C/C++ module and I don't know how it works.

furas
  • 134,197
  • 12
  • 106
  • 148