spatialaudio / python-sounddevice

:sound: Play and Record Sound with Python :snake:
https://python-sounddevice.readthedocs.io/
MIT License
980 stars 145 forks source link

Dropping audio/Advice on implementing a PAUSE/RESUME #500

Closed andrewfr closed 4 months ago

andrewfr commented 7 months ago

Hi Folks:

I don't know if this is the right place to ask for advice? I am still new to audio.

I am trying to pause and resume a RawOutputStream. I am using a callback. The problem is I lose about a little bit of audio. I guess I am dropping a frame (not even a second of sound. I need to figure out how to calculate this).

my sample rate is 24000 and block_size is 8192

More information. My threads communicate through queues.

audio_generation -> output_audio -> callback

in output_audio (a while loop)

while True:
        message = io_context.audio_queue.get()
        match message.type:
                 case MessageType.PAUSE:
                        io_context.output_stream.stop()
                        io_context.audio_internal_queue.put_nowait(message)
                        continue

                 case MessageType.RESUME:
                        if not io_context.output_stream.active:
                            io_context.output_stream.start()

My callback is similar to the sd examples

def callback(outdata, frames, time, status):
        assert frames == block_size
        if status.output_underflow:
            print("Output underflow: increase blocksize?", file=sys.stderr)
            raise sd.CallbackAbort
        assert not status
        try:
            message = io_context.audio_internal_queue.get()

            if message.type == MessageType.PAUSE:
                return

        except queue.Empty as e:
            print("Buffer is empty: increase buffersize?", file=sys.stderr)
            raise sd.CallbackAbort from e

        data = message.data

        if len(data) <= len(outdata):
            outdata[: len(data)] = data
            outdata[len(data) :] = b"\x00" * (len(outdata) - len(data))

I know the pause does not work because it arrives too late. I thought about manipulating the callback queue to have it raise a sd.CallbackStop in the callback but that is tricky. What is the recommended way to pause and resume an audio stream?

Thanks in advance, Andrew

mgeier commented 7 months ago

I am trying to pause and resume a RawOutputStream. [...] The problem is I lose about a little bit of audio.

I'm not sure what you are expecting to happen, but stopping and re-starting a stream will not be gapless.

If you want the sound to stop, don't stop the stream, but write zeros to the stream. When you want the sound to continue, start writing the signal values again.

andrewfr commented 7 months ago

Thanks for the reply. I am new to audio and sound-device so I don't know what to expect. However, I did two things:

  1. I number the frames. I found which frame was dropped. I save it when stopping. I re-inserted the frame in the proper position in the callback queue before re-starting. That seemed to have worked but it doesn't sound quite right. However, I don't like manipulating the queue's internals.

  2. writing zeroes to the stream. That worked. However, isn't that inefficient? Since you mentioned it, I guess this is the preferred approach.

Thank you, Andrew

mgeier commented 7 months ago

I don't really understand what you are trying to do, so I was just guessing.

If you provide a minimal reproducible example and explain what you expect to happen that doesn't, I may be able to give you more meaningful advice.

andrewfr commented 6 months ago

Hi Matthais:

I am sorry for being so late in replying. I am building a voice assistant (more specifically a Dialogflow custom integration). Consequently I have to handle much of the low-level IO. So far, sounddevice is doing a fantastic job. I am not an audio person. I have much to learn. And I still have a lot to do. Within the week, I'll try to post a small example of how I pause output.

Cheers, Andrew


From: Matthias Geier @.> Sent: 03 December 2023 06:08 To: spatialaudio/python-sounddevice @.> Cc: Andrew Francis @.>; Author @.> Subject: Re: [spatialaudio/python-sounddevice] Dropping audio/Advice on implementing a PAUSE/RESUME (Issue #500)

I don't really understand what you are trying to do, so I was just guessing.

If you provide a minimal reproducible example and explain what you expect to happen that doesn't, I may be able to give you more meaningful advice.

— Reply to this email directly, view it on GitHubhttps://github.com/spatialaudio/python-sounddevice/issues/500#issuecomment-1837445957, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ABOMO6U7R4PK4ACXXLITVS3YHRMR7AVCNFSM6AAAAAA67WCPTWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMZXGQ2DKOJVG4. You are receiving this because you authored the thread.

mgeier commented 4 months ago

I'm closing this for now, please create a new issue once you have a MRE.

andrewfr commented 4 months ago

Hi Matthias:

Sorry about that. Let me get on this.

Cheers, Andrew


From: Matthias Geier @.> Sent: 02 February 2024 15:15 To: spatialaudio/python-sounddevice @.> Cc: Andrew Francis @.>; Author @.> Subject: Re: [spatialaudio/python-sounddevice] Dropping audio/Advice on implementing a PAUSE/RESUME (Issue #500)

Closed #500https://github.com/spatialaudio/python-sounddevice/issues/500 as not planned.

— Reply to this email directly, view it on GitHubhttps://github.com/spatialaudio/python-sounddevice/issues/500#event-11688896194, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ABOMO6S2TBALN6VW3VFKBQLYRVCMTAVCNFSM6AAAAAA67WCPTWVHI2DSMVQWIX3LMV45UABCJFZXG5LFIV3GK3TUJZXXI2LGNFRWC5DJN5XDWMJRGY4DQOBZGYYTSNA. You are receiving this because you authored the thread.