qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v7] audio/pwaudio.c: Add Pipewire audio backend for QEMU


From: Volker Rümelin
Subject: Re: [PATCH v7] audio/pwaudio.c: Add Pipewire audio backend for QEMU
Date: Sun, 12 Mar 2023 09:01:07 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.8.0

+/* output data processing function to read stuffs from the buffer */
+static void
+playback_on_process(void *data)
+{
+    PWVoice *v = (PWVoice *) data;
+    void *p;
+    struct pw_buffer *b;
+    struct spa_buffer *buf;
+    uint32_t n_frames, req, index, n_bytes;
+    int32_t avail;
+
+    if (!v->stream) {
+        return;
+    }
+
+    /* obtain a buffer to read from */
+    b = pw_stream_dequeue_buffer(v->stream);
+    if (b == NULL) {
+        error_report("out of buffers: %s", strerror(errno));
+        return;
+    }
+
+    buf = b->buffer;
+    p = buf->datas[0].data;
+    if (p == NULL) {
+        return;
+    }
+    req = b->requested * v->frame_size;
+    if (req == 0) {
+        req = 4096 * v->frame_size;
+    }
+    n_frames = SPA_MIN(req, buf->datas[0].maxsize);
+    n_bytes = n_frames * v->frame_size;
+
+    /* get no of available bytes to read data from buffer */
+
+    avail = spa_ringbuffer_get_read_index(&v->ring, &index);
+
+    if (!v->enabled) {
+        avail = 0;
+    }
+
+    if (avail == 0) {
+        memset(p, 0, n_bytes);

memset() doesn't work for unsigned samples. For unsigned samples, a stream of zeros is silence with a DC offset. When Pipewire mixes this stream with another, the result is a clipped audio stream. To hear this, start QEMU with qemu-system-x86_64 -machine pcspk-audiodev=audio0 -device ich9-intel-hda -device hda-duplex,audiodev=audio0 -audiodev pipewire,id=audio0,out.mixing-engine=off ... and start playback with the hda device.

With best regards,
Volker

+    } else {
+        if (avail < (int32_t) n_bytes) {
+            n_bytes = avail;
+        }
+
+        spa_ringbuffer_read_data(&v->ring,
+                                    v->buffer, RINGBUFFER_SIZE,
+                                    index & RINGBUFFER_MASK, p, n_bytes);
+
+        index += n_bytes;
+        spa_ringbuffer_read_update(&v->ring, index);
+    }
+
+    buf->datas[0].chunk->offset = 0;
+    buf->datas[0].chunk->stride = v->frame_size;
+    buf->datas[0].chunk->size = n_bytes;
+
+    /* queue the buffer for playback */
+    pw_stream_queue_buffer(v->stream, b);
+}
+




reply via email to

[Prev in Thread] Current Thread [Next in Thread]