Skip to content

Using two independent streams causes an error with ASIO drivers. #600

@ldelebec

Description

@ldelebec

Grettings,

I am trying to write a script that reads two different output streams, the first being continuous while the second consists of short signals controlled by the user via the keyboard.

The script works well on the laptop sound card using MME, but I got a "unvailable output device" error when I try to run it on an external sound card (RME Fireface 802) using ASIO drivers (on Windows 10).

Here is a minimal example with a sine wave and a noise signal:

import sys

import numpy as np
import sounddevice as sd

start_index = 0


def main() -> None:
    # General parameters
    # asio_setting = sd.query_devices("asio")
    asio_setting = sd.query_devices(None, "output")
    sample_rate = int(asio_setting["default_samplerate"])
    device_index = asio_setting["index"]
    dtype = "float32"  # sounddevice uses float32 by default
    n_channels = 2

    # Noise duration
    noise_duration = 2
    n_samples_noise = round(noise_duration * sample_rate)
    noise = np.random.randn(n_samples_noise)
    noise *= 0.1

    output_buffer = np.zeros((n_samples_noise, n_channels), dtype=dtype)
    output_buffer[:, 1] = noise

    def callback(outdata, frames, time, status):
        # Check for any errors
        if status:
            print(status, file=sys.stderr)
        # Generate a sine wave signal
        global start_index
        t = (start_index + np.arange(frames)) / sample_rate
        outdata[:, 0] = 0.2 * np.sin(
            2 * np.pi * 440 * t
        )  # 440 Hz sine wave at 20% amplitude
        outdata[:, 1] = 0.0
        start_index += frames

    try:
        with sd.OutputStream(
            samplerate=sample_rate,
            channels=n_channels,
            callback=callback,
            device=device_index,
        ):
            sd.sleep(1_000)  # Wait 1 second
            # Loop over all the sentences and play them
            for _ in range(3):
                with sd.OutputStream(
                    samplerate=sample_rate, channels=n_channels, device=device_index
                ) as stream:
                    stream.write(output_buffer)

                # Once the noise is played, let user launch the next one
                print("#" * 80)
                print(
                    "Presser 'Entrée' pour continuer ou 'q' puis 'Entrée' pour quitter"
                )
                print("#" * 80)
                input_str = input()
                if input_str.lower() == "q":
                    sd.stop()
                    break

    except KeyboardInterrupt:
        sys.exit("\nInterrompu par l'utilisateur")
    except Exception as e:
        sys.exit(type(e).__name__ + ": " + str(e))

if __name__ == "__main__":
    main()

The error occurs when creating the second OutputStream.

Do I need to call both OutputStreams from the same thread ? How can I code it ?
Could asyncio be a solution ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions