0

I'm working on a mic listener with Python (3.7).

To work on the audio stream, I wrote a function that run on a thread and invoke itself at the end (tail recursion)

class Listener:
    # [...]

    def __init__(self, audio_conf: AudioConfiguration, listener_callback: Callable[[bytes], None] = None) -> None:
        self.__configuration = audio_conf
        if listener_callback:
            self.__listener_callback = listener_callback
        self.__stream = PyAudio().open(format=self.__configuration.FORMAT,  # p.get_format_from_width(WIDTH),
                                       channels=self.__configuration.CHANNELS,
                                       rate=self.__configuration.RATE,
                                       input=True,
                                       output=True,
                                       frames_per_buffer=self.__configuration.CHUNK)
        thread = Thread(target=self.__listen, args=())
        thread.start()

    # [...]
    def __listen(self) -> None:
        if self.__flag_deactivation:
            if self.__listener_callback:
                print(f"Call listener callback")
                p = Process(target=self.__listener_callback, args=(self.__active_buffer,))
                p.start()
                # p.join()
            self.reset_state()
        tmp_buffer: bytes = b""
        count: int = 0
        voice: int = 0
        for i in range(0, self.__configuration.FRAMES_LENGTH):
            tmp_buffer += self.__stream.read(self.__configuration.CHUNK_SIZE)  # read audio stream
            count += 1
            if self.__mic_tuning.is_voice():
                voice += 1
        self.__previous_buffer = tmp_buffer
        if self.__active:
            self.__active_buffer += tmp_buffer
        print(f"Listening {'active' if self.__active else 'background'} - Voice Threshold {voice / count}")
        self.__listen()

Obviously, Python complains about "Maximum recursion depth"...

Is there a way to :

  • get rid of maximum recursion depth (but not a good idea I think, it can hide some other problems...)

  • or rewrite that without tail recursion (but keep efficience)

I'm not working with Python from a long time, so I'll happy to learn some "pythonic" way to achieve that without hacking default behavior :)

Thanks !

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
Doubidou
  • 1,573
  • 3
  • 18
  • 35
  • [does-python-optimize-tail-recursion](https://stackoverflow.com/questions/13591970/does-python-optimize-tail-recursion): no :-) – Patrick Artner Jan 02 '19 at 08:29
  • 1
    not sure why you opted to tail-recurse.the code is no [mcve] so I am a bit stumped how we should help - probably your code is too big for SO, maybe you can condense it into a [mcve] that replicates the tail recursion but cuts down on used methods / functionality. You probably need some `while True:` _somewhere_ that continues to listen if a `__listen()` was triggered and ended ... maybe some wait() or joins() ... and shared data containers between threads that collect your sound ? – Patrick Artner Jan 02 '19 at 08:35
  • Got it with a `while True:` at the beginning of the function `__listen()`, you right :) The code is big, but the goal is simple : this function fill a buffer if a boolean is set to True, and stop filling if set to False. When it's turn to False, callback is called :) – Doubidou Jan 02 '19 at 08:48

0 Answers0