I'll be very detailed so there is no lack of information about what is happening
I have a class named Stream, that has the main function of reading data output from any selected audio device connected to the PC and return the data to another class (this part is not implemented in the code yet, but it's just for context). Here is the Stream class:
Stream.py
import pyaudio
import struct
from threading import Thread
from LEDController.BaseClass import BaseClass
from LEDController.Device import Device
class Stream(BaseClass):
def __init__(self, device: Device):
super().__init__(__name__)
self.__p = pyaudio.PyAudio()
self.stream = None
# Stream Settings
self.defaultFrames = 1024 * 8
self.format = pyaudio.paInt16
self.channels = device.channels
self.rate = device.defaultSampleRate
self.input = True
self.frames_per_buffer = self.defaultFrames
self.input_device_index = device.index
self.as_loopback = True
self.__open()
self.stop()
def __open(self):
try:
self.logger.info('Trying to Open Stream')
# Open Stream
self.stream = self.__p.open(
format=self.format,
channels=self.channels,
rate=self.rate,
input=self.input,
frames_per_buffer=self.defaultFrames,
input_device_index=self.input_device_index,
as_loopback=self.as_loopback,
# wasapi_fill_silence=True
)
except Exception as e:
self.logger.error(e)
else:
self.logger.info('Stream Opened')
def start(self):
try:
self.stream.start_stream()
self.read_thread = Thread(target=self.read)
self.read_thread.start()
self.logger.info("Stream Started")
return True
except Exception as e:
return self.logger.error(e)
def stop(self):
try:
self.stream.stop_stream()
self.logger.info("Stream Stopped")
return False
except Exception as e:
return self.logger.error(e)
def is_stopped(self):
return self.stream.is_stopped()
def read(self):
try:
while not self.is_stopped():
# Process Data
data = self.stream.read(self.defaultFrames) # This line doesn't return anything
data_int = struct.unpack(str(2 * self.defaultFrames) + 'h', data)
print(data_int)
# TODO return data
except Exception as e:
self.logger.error(e)
What it's doing:
At first, it receives a Device Object (code is not that important. However, I can edit and add it if needed). The Device object has a few pieces of information about the current selected device (such as device default sample rate, channels, etc, as you can see in Stream.__init__(). So the Stream class uses those pieces of information to open a PyAudio Stream with PyAudio.open(...) and right after that, it stops the stream until the user (there is a GUI) opens it.
The Problem
The Stream.read() method it's called by a Thread, so it keeps running, processing, and returning the data in real-time. However when I call Stream.start() and it starts the read method, the same keeps stuck in the following line:
data = self.stream.read(self.defaultFrames)
I've added a print statement in this method to see the data flowing. However, this statement only gets called after stopping the stream, and no error is shown.
Output
2020-06-03 09:15:21,718 — LEDController.Stream.Stream - 57 — INFO — Stream Started
2020-06-03 09:15:24,371 — LEDController.Stream.Stream - 65 — INFO — Stream Stopped
(output of the print statement, it's quite long so I'll not put it here)
As you can see, no data is printed while the stream is open. Looking at this output and after a few tests, I've figured out that self.stream.read(...) it's not returning any data, while the stream is opened and only returns when the stream stops. After that conclusion, I've started looking for solutions and doing more tests, but I couldn't find anything, and only for the recorded, this problem was not happening before (it started like yesterday) and I don't remember changing anything in my code.
Things that I've also tried, but haven't worked
- Removing the Thread and calling Stream.read() normally
- Reinstalling PyAudio
If you need any additional information, just tell me in the comments. I've tried to be as specific as possible and sorry if I didn't make my self clear enough. Just let me know and I'll update the question and fix the problem. Thanks in advance.