from io import BytesIO
import numpy as np
import soundfile as sf
from stream2py.sources.audio import PyAudioSourceReader
# TODO: (wish) service this will builtins only
# DFLT_INPUT_DEVICE_INDEX = find_a_default_input_device_index()
DFLT_SR = 44100
DFLT_N_CHANNELS = 1
DFLT_SAMPLE_WIDTH = 2
DFLT_CHK_SIZE = 1024 * 4
DFLT_STREAM_BUF_SIZE_S = 60
read_kwargs_for_sample_width = {
2: dict(format='RAW', subtype='PCM_16', dtype='int16'),
3: dict(format='RAW', subtype='PCM_24', dtype='int32'),
4: dict(format='RAW', subtype='PCM_32', dtype='int32'),
}
[docs]def list_recording_device_index_names():
"""List (index, name) of available recording devices"""
return sorted((d['index'], d['name']) for d in PyAudioSourceReader.list_device_info() if d['maxInputChannels'] > 0)
# TODO: Merge with find_a_device_index
def find_a_default_input_device_index(verbose=True):
for index, name in list_recording_device_index_names():
if 'microphone' in name.lower():
if verbose:
print(f"Found {name}. Will use it as the default input device. It's index is {index}")
return index
for index, name in list_recording_device_index_names():
if 'mic' in name.lower():
if verbose:
print(f"Found {name}. Will use it as the default input device. It's index is {index}")
return index
def audio_pokes_version_of_bytes_to_waveform(b, sr=DFLT_SR, n_channels=DFLT_N_CHANNELS, sample_width=DFLT_SAMPLE_WIDTH):
return sf.read(BytesIO(b), samplerate=sr, channels=n_channels, **read_kwargs_for_sample_width[sample_width])[0]
def waveform_to_bytes(wf, sr=DFLT_SR, sample_width=DFLT_SAMPLE_WIDTH):
b = BytesIO()
subtype = read_kwargs_for_sample_width[sample_width]['subtype']
sf.write(b, wf, samplerate=sr, format='RAW', subtype=subtype)
b.seek(0)
return b.read()
# TODO: Test and merge with find_a_default_input_device_index
def find_a_device_index(filt='microphone', dflt=None):
if isinstance(filt, str):
match_str = filt
def filt(x):
return match_str in x.get('name', match_str).lower()
match = next(filter(filt, PyAudioSourceReader.list_device_info()), None)
return (match is not None and match['index']) or dflt
def ensure_source_input_device_index(input_device_index=None):
if input_device_index is None:
input_device_index = find_a_default_input_device_index()
if input_device_index is not None:
return input_device_index
else:
# TODO: Nicer way to print info (perhaps only relevant info, formated as table)
print("Need a valid input_device_index. Calling live_audio_chks.list_device_info() to information about the "
"devices I can detect:\n")
for item in PyAudioSourceReader.list_device_info():
print(item)
print("")
print("---> Look in the list above and choose an input_device_index (it's called index in the printout above) "
"that seems to be right for you!")
raise ValueError("Need a valid input_device_index")