Using sound file as pyaudio input device - python

With PyAudio it is fairly simple to open an input stream comming from a physical sound input device.
I wonder if there is a way of open an existing sound file as a stream, which has the same properties as the sound-device-stream?
Instead of
self.p = pyaudio.PyAudio()
self.inStream = self.p.open(format=pyaudio.paInt16,
channels=1,
rate=self.RATE,
input=True,
frames_per_buffer=self.BUFFERSIZE)
I'd like to do
self.p = pyaudio.PyAudio()
self.inStream = self.p.open('testfile.wav',
input=True,
frames_per_buffer=self.BUFFERSIZE)
Regards,
Torsten

As far as I know you can't use PyAudio to open file directly, however it's possible to combine pyaudio and wave modules in case your app reroutes the processed sound to SoundFlower for example.
import pyaudio, wave
def open_stream(self):
self.p_audio = pyaudio.PyAudio()
self.file_source = wave.open('input.wav', 'rb')
s_width = self.file_source.getsampwidth()
format = self.p_audio.get_format_from_width(s_width)
channels = self.file_source.getnchannels()
rate = self.file_source.getframerate()
self.stream = self.p_audio.open(format=format,
channels=channels,
rate=rate,
frames_per_buffer=1024,
input=False,
output=True,
output_device_index=detect_build_in_output_device_idx(self.p_audio),
stream_callback=self.__recording_callback)
def __recording_callback(self, in_data, frame_count, time_info, status):
# read frames
in_data = self.file_source.readframes(frame_count)
# decode frames
left, right = audio_decode(in_data, self.file_source.getnchannels())
# process frames
left, right = self.core.process(left, right)
# encode back
processed_data = audio_encode((left, right))
return processed_data, pyaudio.paContinue

Related

how to submit an rtsp stream to pyaudio for further processing

I have a function that connects to my microphone and recognizes speech as a string with a phrase.
It looks like this:
import json, pyaudio
from Analysis import Voice_tag, nlp
from vosk import Model, KaldiRecognizer
class VoiseRecorder():
def __init__(self):
model = Model("model1")
self.rec = KaldiRecognizer(model, 128000)
p = pyaudio.PyAudio()
self.stream = p.open(format=pyaudio.paInt16,
channels=1,
rate = 128000,
input=True,
frames_per_buffer=64000)
self.stream.start_stream()
self.Voise
for text in self.CamVoise():
Voice_tag(text)
print(" ")
def Voise(self):
print('F on')
while True:
data = self.stream.read(32000, exception_on_overflow=False)
if (self.rec.AcceptWaveform(data)) and (len(data)>0):
out = json.loads(self.rec.Result())
if out['text']:
yield out['text']
VoiseRecord = VoiseRecorder()
Can I somehow transfer the sound from the rtsp stream to the processing using this method ?

How to get sound from PDM microphone on Google Coral Dev board ( mini )?

I just got my hands on the amazing Google Coral dev board, but I lack enough tutorials or software ecosystem around. I looked into the datasheet and found that there is a PDM microphone on the board. My question is, how can I record sound from it? Is there any native app for that and can I do it from python? Thanks
I was able to make it run via pyaudio
import pyaudio
import wave
# the file name output you want to record into
filename = "recorded.wav"
# set the chunk size of 1024 samples
chunk = 1024
# sample format
FORMAT = pyaudio.paInt16
# mono, change to 2 if you want stereo
channels = 1
# 44100 samples per second
sample_rate = 44100
record_seconds = 5
# initialize PyAudio object
p = pyaudio.PyAudio()
# open stream object as input & output
stream = p.open(format=FORMAT,
channels=channels,
rate=sample_rate,
input=True,
output=True,
frames_per_buffer=chunk)
frames = []
print("Recording...")
for i in range(int(44100 / chunk * record_seconds)):
data = stream.read(chunk)
frames.append(data)
print("Finished recording.")
# stop and close stream
stream.stop_stream()
stream.close()
# terminate pyaudio object
p.terminate()
# save audio file
# open the file in 'write bytes' mode
wf = wave.open(filename, "wb")
# set the channels
wf.setnchannels(channels)
# set the sample format
wf.setsampwidth(p.get_sample_size(FORMAT))
# set the sample rate
wf.setframerate(sample_rate)
# write the frames as bytes
wf.writeframes(b"".join(frames))
# close the file
wf.close()
or as #Manoj stated, one can use arecord native app

PyAudio: How to access stream.read() data in callback/non-blocking mode

Not knowledgeable in programming but in following along with the wire and wire callback examples on the documentation website I am struggling to figure out how to access the stream.read(CHUNK) data in callback mode to be processed by audioop.rms() from the audioop library.
Below are two slightly modified examples. The former is the wire method in blocking mode and processed by the rms function successfully. The latter is the wire method in non-blocking mode which I do not know how to go about accessing the same data.
"""
PyAudio Example: Make a wire between input and output (i.e., record a
few samples and play them back immediately).
"""
import pyaudio
import audioop # new
CHUNK = 1024
WIDTH = 2
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(WIDTH),
channels=CHANNELS,
rate=RATE,
input=True,
output=True,
frames_per_buffer=CHUNK)
print("* recording")
while True: # <-----------------------------------------
data = stream.read(CHUNK)
stream.write(data, CHUNK)
rms = audioop.rms(data, WIDTH) # new
print(rms) # computer audio power
print("* done")
stream.stop_stream()
stream.close()
p.terminate()
non-blocking
"""
PyAudio Example: Make a wire between input and output (i.e., record a
few samples and play them back immediately).
This is the callback (non-blocking) version.
"""
import pyaudio
import time
import audioop # new
WIDTH = 2
CHANNELS = 2
RATE = 44100
p = pyaudio.PyAudio()
def callback(in_data, frame_count, time_info, status):
return in_data, pyaudio.paContinue
stream = p.open(format=p.get_format_from_width(WIDTH),
channels=CHANNELS,
rate=RATE,
input=True,
output=True,
stream_callback=callback)
stream.start_stream()
while stream.is_active(): # <--------------------------------------------
time.sleep(0.1)
# data = stream.read(1024) # the docs say not to call this
data = stream.get_read_available() # not sure what to do
print(data) # new
rms = audioop.rms(data, WIDTH) # compute audio power
print(rms) # new
stream.stop_stream()
stream.close()
p.terminate()
I see this is from almost a year ago, but it may help others. You don't need (and in fact, as you discovered, can't use) stream.read() when using non-blocking mode and the callback function. You don't need to. The callback function will be automatically called in a different thread when the stream you opened has data to input or output from the default sources.
Since you want to do something with each chunk (compute the rms value), you need to do that inside the callback function as it processes each chunk. However, if you try to do too much, it can't process it all before the next chunk is ready, and you lose data. File writes and print statements are therefore not something you should do in the callback. (Think of it like an interrupt handler: only do what's essential). So in the working code below, I just compute the rms in the callback function, and make it a global variable so that you can access it from the main program for printing.
I didn't try to compute the audio time for each chunk you're passing to the callback, so by keeping the time.sleep() value at 0.1 it's possible that the code below is missing intermediate rms values.
"""
PyAudio Example: Make a wire between input and output (i.e., record a
few samples and play them back immediately).
This is the callback (non-blocking) version.
"""
import pyaudio
import time
import audioop # new
WIDTH = 2
CHANNELS = 2
RATE = 44100
p = pyaudio.PyAudio()
rms = None
def callback(in_data, frame_count, time_info, status):
# print(in_data) # takes too long in callback
global rms
rms = audioop.rms(in_data, WIDTH) # compute audio power
# print(rms) # new # takes too long in callback
return in_data, pyaudio.paContinue
stream = p.open(format=p.get_format_from_width(WIDTH),
channels=CHANNELS,
rate=RATE,
input=True,
output=True,
stream_callback=callback)
stream.start_stream()
while stream.is_active(): # <--------------------------------------------
print(rms) # may be losing some values if sleeping too long, didn't check
time.sleep(0.1)
stream.stop_stream()
stream.close()
p.terminate()

Python: How to get raw audio file using pyaudio for use in pocketsphinx?

I was trying to get audio data in raw format using pyaudio, to then use in pocketsphinx for my project. However, when I use the raw file generated the output by this program the output contains random noise.
I want the raw file to be usable in pocketsphinx.
import pyaudio
import wave
FORMAT = pyaudio.paInt32
CHANNELS = 1
RATE = 16000
CHUNK = 1024
RECORD_SECONDS = 2
audio = pyaudio.PyAudio()
# start Recording
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK)
print "recording..."
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print "finished recording"
# stop Recording
stream.stop_stream()
stream.close()
audio.terminate()
file = open("newfile.raw", "w")
file.write(b''.join(frames))
file.close()

How to reverse audio with pyaudio

I've been tinkering around with pyaudio for a while now, trying to reverse a simple wave file with no success.
In (my) theory I would only have to iterate from end to beginning through the file with every callback of pyaudio (1024 frames) fetch the audio data from the according index in the file, reverse the resulting string and play it.
Here is my code (only pyaudio callback and file handling, the rest is untouched from the example code):
import pyaudio
import wave
import time
import sys
if len(sys.argv) < 2:
print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
sys.exit(-1)
index = 40*1024
wf = wave.open(sys.argv[1], 'rb')
wf.setpos(index)
p = pyaudio.PyAudio()
def callback(in_data, frame_count, time_info, status):
global index
data = wf.readframes(frame_count)
data = data[::-1]
index-=1024
wf.setpos(index)
return (data, pyaudio.paContinue)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
stream_callback=callback)
stream.start_stream()
while stream.is_active():
time.sleep(0.1)
stream.stop_stream()
stream.close()
wf.close()
p.terminate()
I know this will crash when it reaches the file beginning, but it should play 40 × 1024 frames of reversed audio...
If the file you want reversed is small enough to fit in memory, your best bet would be loading it entirely and reversing the data, then streaming it:
import pyaudio
import wave
wavefile_name = 'wavefile.wav'
wf = wave.open(wavefile_name, 'rb')
p = pyaudio.PyAudio()
stream = p.open(format =
p.get_format_from_width(wf.getsampwidth()),
channels = wf.getnchannels(),
rate = wf.getframerate(),
output = True)
full_data = []
data = wf.readframes(1024)
while data:
full_data.append(data)
data = wf.readframes(1024)
data = ''.join(full_data)[::-1]
for i in range(0, len(data), 1024):
stream.write(data[i:i+1024])
However, if the file is too big to fit in memory, you'll need some way of reading the file backwards and feed into the sound system. That's an entirely different problem, because it involves some low level I/O programming to handle the backward reading.
Edit: after seeing your full code, I don't see any errors. The code runs properly in my computer, only to fail at the ending of the playback. However, you can do two things. First, you can go to the end of the wavefile to play the entire sound backwards, using this:
wf = wave.open(sys.argv[1], 'rb')
index = wf.getnframes() - 1024
wf.setpos(index)
Second, you have to modify the callback so it doesn't fail when the seek head goes beyond the beginning of the file:
def callback(in_data, frame_count, time_info, status):
global index
data = wf.readframes(frame_count)
data = data[::-1]
index-=1024
if index < 0:
return (data, pyaudio.paAbort)
else:
wf.setpos(max(index,0))
return (data, pyaudio.paContinue)
Other than that, it works pretty ok.

Categories

Resources