3

I'm trying to record sound from mic. Firstly as used PyAudio then sounddevice but both failed.

Here is code for PyAudio:

import pyaudio


def _recording_loop(samples_queue, running, stream, chunk_size):
    stream.start_stream()

    while running.is_set():
        samples_queue.put(stream.read(chunk_size))

    stream.stop_stream()


class Recoder:

    def __init__(self, frame_rate, period):
        self.proc = None
        self.running = Event()
        self.samples_queue = Queue()
        self.frame_rate = frame_rate
        self.chunk_size = (frame_rate*period) / 1000
        self.channels = 1

        self._pa = pyaudio.PyAudio()
        self._stream = None

    def start(self):
        if self.proc is None:
            self._stream = self._pa.open(format=pyaudio.paInt8,
                                         channels=self.channels,
                                         rate=self.frame_rate,
                                         input=True,
                                         frames_per_buffer=self.chunk_size)

            self.running.set()
            self.proc = Process(target=_recording_loop, args=[self.samples_queue, self.running, self._stream,
                                                              self.chunk_size])
            self.proc.start()

    def stop(self):
        if self.proc is not None:
            self.running.clear()
            self.proc.join()

        self._stream.close()
        self._pa.terminate()

    def empty(self):
        return self.samples_queue.empty()

    def read(self):
        res = []
        while not self.samples_queue.empty():
            res.append(self.samples_queue.get())
    return res

It gives me a warning: Python[21648:645093] 13:42:01.242 WARNING: 140: This application, or a library it uses, is using the deprecated Carbon Component Manager for hosting Audio Units. Support for this will be removed in a future release. Also, this makes the host incompatible with version 3 audio units. Please transition to the API's in AudioComponent.h. and nothing is ever recorded.

As I understand it's something with El Capitan and not solved yet. But maybe I'm wrong?

So I decided to switch library to sounddevice:

from multiprocessing import Process, Queue, Event
import sounddevice as sd


def _recording_loop(samples_queue, running, frame_rate, chunk_size):
    while running.is_set():
        samples_queue.put(sd.rec(chunk_size, samplerate=frame_rate, channels=1,
                                 dtype='int8', blocking=True))


class Recoder:

    def __init__(self, frame_rate, period):

        self.proc = None
        self.running = Event()
        self.samples_queue = Queue()
        self.frame_rate = frame_rate
        self.period = period

        self.chunk_size = (frame_rate * period) / 1000

    def start(self):
        if self.proc is None:
            self.running.set()
            self.proc = Process(target=_recording_loop, args=[self.samples_queue, self.running, self.frame_rate,
                                                              self.chunk_size])
            self.proc.start()

    def stop(self):
        if self.proc is not None:
            self.running.clear()
            self.proc.join()

    def empty(self):
        return self.samples_queue.empty()

    def read(self):
        res = []
        while not self.samples_queue.empty():
            res.append(self.samples_queue.get())

        return res

And it says:

||PaMacCore (AUHAL)|| Warning on line 530: err=''who?'', msg=Audio Hardware: Unknown Property
||PaMacCore (AUHAL)|| Warning on line 534: err=''who?'', msg=Audio Hardware: Unknown Property
||PaMacCore (AUHAL)|| Warning on line 445: err=''who?'', msg=Audio Hardware: Unknown Property

And again nothing is recorded. What I'm doing wrong?

Long Smith
  • 1,339
  • 3
  • 21
  • 40

2 Answers2

0

sounddevice.rec() is not meant to be used like that. You just call it with the number of frames you want to record and that's it (see the example from the docs):

import sounddevice as sd

fs = 44100
duration = 10  # seconds
myrecording = sd.rec(duration * fs, samplerate=fs, channels=2,
                     blocking=True)

That's it. You don't need half a page of code just to record some sound.

BTW, you can ignore the warning for now, see https://github.com/spatialaudio/python-sounddevice/issues/10.

Matthias
  • 4,524
  • 2
  • 31
  • 50
0

Yesterday I ran into similar problem. It seems that it's caused by using multiprocessing with sounddevice. When I do import sounddevice at the top of the module I get ||PaMacCore (AUHAL)|| Warning on line 530: err=''who?'', msg=Audio Hardware: Unknown Property and then the app just hangs while creating sounddevice.RawInputStream. When I import sounddevice in my run() method (I am creating a new class based on multiprocessing.Process) it works fine. For me it seems that sounddevice does something to initialise itself right after being imported and this must happen in the same process that will use it. Edit: instead of Multiprocessing use Threading.

mcjlnrtwcz
  • 272
  • 3
  • 10