aboutsummaryrefslogtreecommitdiff
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/alsaaudio.c2
-rw-r--r--audio/audio-hmp-cmds.c2
-rw-r--r--audio/audio.c33
-rw-r--r--audio/audio_int.h1
-rw-r--r--audio/audio_template.h12
-rw-r--r--audio/dbusaudio.c31
-rw-r--r--audio/mixeng.c83
-rw-r--r--audio/mixeng.h6
-rw-r--r--audio/pwaudio.c8
-rw-r--r--audio/trace-events2
10 files changed, 140 insertions, 40 deletions
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index cacae1e..9b6c01c 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -899,7 +899,7 @@ static void alsa_enable_in(HWVoiceIn *hw, bool enable)
static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo)
{
if (!apdo->has_try_poll) {
- apdo->try_poll = true;
+ apdo->try_poll = false;
apdo->has_try_poll = true;
}
}
diff --git a/audio/audio-hmp-cmds.c b/audio/audio-hmp-cmds.c
index c9608b7..8774c09 100644
--- a/audio/audio-hmp-cmds.c
+++ b/audio/audio-hmp-cmds.c
@@ -27,7 +27,7 @@
#include "monitor/hmp.h"
#include "monitor/monitor.h"
#include "qapi/error.h"
-#include "qapi/qmp/qdict.h"
+#include "qobject/qdict.h"
static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
diff --git a/audio/audio.c b/audio/audio.c
index af0ae33..89f091b 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -32,15 +32,15 @@
#include "qapi/qobject-input-visitor.h"
#include "qapi/qapi-visit-audio.h"
#include "qapi/qapi-commands-audio.h"
-#include "qapi/qmp/qdict.h"
+#include "qobject/qdict.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qemu/help_option.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/replay.h"
-#include "sysemu/runstate.h"
+#include "system/system.h"
+#include "system/replay.h"
+#include "system/runstate.h"
#include "ui/qemu-spice.h"
#include "trace.h"
@@ -905,6 +905,14 @@ size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size)
int AUD_get_buffer_size_out(SWVoiceOut *sw)
{
+ if (!sw) {
+ return 0;
+ }
+
+ if (audio_get_pdo_out(sw->s->dev)->mixing_engine) {
+ return sw->resample_buf.size * sw->info.bytes_per_frame;
+ }
+
return sw->hw->samples * sw->hw->info.bytes_per_frame;
}
@@ -1884,7 +1892,8 @@ CaptureVoiceOut *AUD_add_capture(
cap->buf = g_malloc0_n(hw->mix_buf.size, hw->info.bytes_per_frame);
if (hw->info.is_float) {
- hw->clip = mixeng_clip_float[hw->info.nchannels == 2];
+ hw->clip = mixeng_clip_float[hw->info.nchannels == 2]
+ [hw->info.swap_endianness];
} else {
hw->clip = mixeng_clip
[hw->info.nchannels == 2]
@@ -2274,17 +2283,19 @@ size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info)
ticks = now - rate->start_ticks;
bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
frames = (bytes - rate->bytes_sent) / info->bytes_per_frame;
- if (frames < 0 || frames > 65536) {
- AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n", frames);
- audio_rate_start(rate);
- frames = 0;
- }
+ rate->peeked_frames = frames;
- return frames * info->bytes_per_frame;
+ return frames < 0 ? 0 : frames * info->bytes_per_frame;
}
void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used)
{
+ if (rate->peeked_frames < 0 || rate->peeked_frames > 65536) {
+ AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n",
+ rate->peeked_frames);
+ audio_rate_start(rate);
+ }
+
rate->bytes_sent += bytes_used;
}
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 2d079d0..f78ca05 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -255,6 +255,7 @@ const char *audio_application_name(void);
typedef struct RateCtl {
int64_t start_ticks;
int64_t bytes_sent;
+ int64_t peeked_frames;
} RateCtl;
void audio_rate_start(RateCtl *rate);
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 7ccfec0..c29d79c 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -174,9 +174,11 @@ static int glue (audio_pcm_sw_init_, TYPE) (
if (sw->info.is_float) {
#ifdef DAC
- sw->conv = mixeng_conv_float[sw->info.nchannels == 2];
+ sw->conv = mixeng_conv_float[sw->info.nchannels == 2]
+ [sw->info.swap_endianness];
#else
- sw->clip = mixeng_clip_float[sw->info.nchannels == 2];
+ sw->clip = mixeng_clip_float[sw->info.nchannels == 2]
+ [sw->info.swap_endianness];
#endif
} else {
#ifdef DAC
@@ -303,9 +305,11 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
if (hw->info.is_float) {
#ifdef DAC
- hw->clip = mixeng_clip_float[hw->info.nchannels == 2];
+ hw->clip = mixeng_clip_float[hw->info.nchannels == 2]
+ [hw->info.swap_endianness];
#else
- hw->conv = mixeng_conv_float[hw->info.nchannels == 2];
+ hw->conv = mixeng_conv_float[hw->info.nchannels == 2]
+ [hw->info.swap_endianness];
#endif
} else {
#ifdef DAC
diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c
index 60fcf64..b44fdd1 100644
--- a/audio/dbusaudio.c
+++ b/audio/dbusaudio.c
@@ -43,9 +43,10 @@
#define DBUS_DISPLAY1_AUDIO_PATH DBUS_DISPLAY1_ROOT "/Audio"
-#define DBUS_AUDIO_NSAMPLES 1024 /* could be configured? */
+#define DBUS_DEFAULT_AUDIO_NSAMPLES 480
typedef struct DBusAudio {
+ Audiodev *dev;
GDBusObjectManagerServer *server;
bool p2p;
GDBusObjectSkeleton *audio;
@@ -105,7 +106,7 @@ static size_t dbus_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
assert(buf == vo->buf + vo->buf_pos && vo->buf_pos + size <= vo->buf_size);
vo->buf_pos += size;
- trace_dbus_audio_put_buffer_out(size);
+ trace_dbus_audio_put_buffer_out(vo->buf_pos, vo->buf_size);
if (vo->buf_pos < vo->buf_size) {
return size;
@@ -151,6 +152,18 @@ dbus_init_out_listener(QemuDBusDisplay1AudioOutListener *listener,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
+static guint
+dbus_audio_get_nsamples(DBusAudio *da)
+{
+ AudiodevDBusOptions *opts = &da->dev->u.dbus;
+
+ if (opts->has_nsamples && opts->nsamples) {
+ return opts->nsamples;
+ } else {
+ return DBUS_DEFAULT_AUDIO_NSAMPLES;
+ }
+}
+
static int
dbus_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
{
@@ -160,7 +173,7 @@ dbus_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
QemuDBusDisplay1AudioOutListener *listener = NULL;
audio_pcm_init_info(&hw->info, as);
- hw->samples = DBUS_AUDIO_NSAMPLES;
+ hw->samples = dbus_audio_get_nsamples(da);
audio_rate_start(&vo->rate);
g_hash_table_iter_init(&iter, da->out_listeners);
@@ -274,7 +287,7 @@ dbus_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
QemuDBusDisplay1AudioInListener *listener = NULL;
audio_pcm_init_info(&hw->info, as);
- hw->samples = DBUS_AUDIO_NSAMPLES;
+ hw->samples = dbus_audio_get_nsamples(da);
audio_rate_start(&vo->rate);
g_hash_table_iter_init(&iter, da->in_listeners);
@@ -399,6 +412,7 @@ dbus_audio_init(Audiodev *dev, Error **errp)
{
DBusAudio *da = g_new0(DBusAudio, 1);
+ da->dev = dev;
da->out_listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_object_unref);
da->in_listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -524,11 +538,17 @@ dbus_audio_register_listener(AudioState *s,
);
}
+ GDBusConnectionFlags flags =
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER;
+#ifdef WIN32
+ flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
+#endif
+
listener_conn =
g_dbus_connection_new_sync(
G_IO_STREAM(socket_conn),
guid,
- G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
+ flags,
NULL, NULL, &err);
if (err) {
error_report("Failed to setup peer connection: %s", err->message);
@@ -646,6 +666,7 @@ dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p)
"swapped-signal::handle-register-out-listener",
dbus_audio_register_out_listener, s,
NULL);
+ qemu_dbus_display1_audio_set_nsamples(da->iface, dbus_audio_get_nsamples(da));
g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(da->audio),
G_DBUS_INTERFACE_SKELETON(da->iface));
diff --git a/audio/mixeng.c b/audio/mixeng.c
index 69f6549..703ee54 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -283,10 +283,15 @@ static const float float_scale_reciprocal = 1.f / ((int64_t)INT32_MAX + 1);
#endif
#endif
+#define F32_TO_F32S(v) \
+ bswap32((union { uint32_t i; float f; }){ .f = (v) }.i)
+#define F32S_TO_F32(v) \
+ ((union { uint32_t i; float f; }){ .i = bswap32(v) }.f)
+
static void conv_natural_float_to_mono(struct st_sample *dst, const void *src,
int samples)
{
- float *in = (float *)src;
+ const float *in = src;
while (samples--) {
dst->r = dst->l = CONV_NATURAL_FLOAT(*in++);
@@ -294,10 +299,21 @@ static void conv_natural_float_to_mono(struct st_sample *dst, const void *src,
}
}
+static void conv_swap_float_to_mono(struct st_sample *dst, const void *src,
+ int samples)
+{
+ const uint32_t *in_f32s = src;
+
+ while (samples--) {
+ dst->r = dst->l = CONV_NATURAL_FLOAT(F32S_TO_F32(*in_f32s++));
+ dst++;
+ }
+}
+
static void conv_natural_float_to_stereo(struct st_sample *dst, const void *src,
int samples)
{
- float *in = (float *)src;
+ const float *in = src;
while (samples--) {
dst->l = CONV_NATURAL_FLOAT(*in++);
@@ -306,15 +322,33 @@ static void conv_natural_float_to_stereo(struct st_sample *dst, const void *src,
}
}
-t_sample *mixeng_conv_float[2] = {
- conv_natural_float_to_mono,
- conv_natural_float_to_stereo,
+static void conv_swap_float_to_stereo(struct st_sample *dst, const void *src,
+ int samples)
+{
+ const uint32_t *in_f32s = src;
+
+ while (samples--) {
+ dst->l = CONV_NATURAL_FLOAT(F32S_TO_F32(*in_f32s++));
+ dst->r = CONV_NATURAL_FLOAT(F32S_TO_F32(*in_f32s++));
+ dst++;
+ }
+}
+
+t_sample *mixeng_conv_float[2][2] = {
+ {
+ conv_natural_float_to_mono,
+ conv_swap_float_to_mono,
+ },
+ {
+ conv_natural_float_to_stereo,
+ conv_swap_float_to_stereo,
+ }
};
static void clip_natural_float_from_mono(void *dst, const struct st_sample *src,
int samples)
{
- float *out = (float *)dst;
+ float *out = dst;
while (samples--) {
*out++ = CLIP_NATURAL_FLOAT(src->l + src->r);
@@ -322,10 +356,21 @@ static void clip_natural_float_from_mono(void *dst, const struct st_sample *src,
}
}
+static void clip_swap_float_from_mono(void *dst, const struct st_sample *src,
+ int samples)
+{
+ uint32_t *out_f32s = dst;
+
+ while (samples--) {
+ *out_f32s++ = F32_TO_F32S(CLIP_NATURAL_FLOAT(src->l + src->r));
+ src++;
+ }
+}
+
static void clip_natural_float_from_stereo(
void *dst, const struct st_sample *src, int samples)
{
- float *out = (float *)dst;
+ float *out = dst;
while (samples--) {
*out++ = CLIP_NATURAL_FLOAT(src->l);
@@ -334,9 +379,27 @@ static void clip_natural_float_from_stereo(
}
}
-f_sample *mixeng_clip_float[2] = {
- clip_natural_float_from_mono,
- clip_natural_float_from_stereo,
+static void clip_swap_float_from_stereo(
+ void *dst, const struct st_sample *src, int samples)
+{
+ uint32_t *out_f32s = dst;
+
+ while (samples--) {
+ *out_f32s++ = F32_TO_F32S(CLIP_NATURAL_FLOAT(src->l));
+ *out_f32s++ = F32_TO_F32S(CLIP_NATURAL_FLOAT(src->r));
+ src++;
+ }
+}
+
+f_sample *mixeng_clip_float[2][2] = {
+ {
+ clip_natural_float_from_mono,
+ clip_swap_float_from_mono,
+ },
+ {
+ clip_natural_float_from_stereo,
+ clip_swap_float_from_stereo,
+ }
};
void audio_sample_to_uint64(const void *samples, int pos,
diff --git a/audio/mixeng.h b/audio/mixeng.h
index a5f56d2..ead93ac 100644
--- a/audio/mixeng.h
+++ b/audio/mixeng.h
@@ -42,9 +42,9 @@ typedef void (f_sample) (void *dst, const struct st_sample *src, int samples);
extern t_sample *mixeng_conv[2][2][2][3];
extern f_sample *mixeng_clip[2][2][2][3];
-/* indices: [stereo] */
-extern t_sample *mixeng_conv_float[2];
-extern f_sample *mixeng_clip_float[2];
+/* indices: [stereo][swap endianness] */
+extern t_sample *mixeng_conv_float[2][2];
+extern f_sample *mixeng_clip_float[2][2];
void *st_rate_start (int inrate, int outrate);
void st_rate_flow(void *opaque, st_sample *ibuf, st_sample *obuf,
diff --git a/audio/pwaudio.c b/audio/pwaudio.c
index 3b14e04..8e13b58 100644
--- a/audio/pwaudio.c
+++ b/audio/pwaudio.c
@@ -769,13 +769,15 @@ qpw_audio_init(Audiodev *dev, Error **errp)
pw->core = pw_context_connect(pw->context, NULL, 0);
if (pw->core == NULL) {
pw_thread_loop_unlock(pw->thread_loop);
- goto fail_error;
+ error_setg_errno(errp, errno, "Failed to connect to PipeWire instance");
+ goto fail;
}
if (pw_core_add_listener(pw->core, &pw->core_listener,
&core_events, pw) < 0) {
pw_thread_loop_unlock(pw->thread_loop);
- goto fail_error;
+ error_setg(errp, "Failed to add PipeWire listener");
+ goto fail;
}
if (wait_resync(pw) < 0) {
pw_thread_loop_unlock(pw->thread_loop);
@@ -785,8 +787,6 @@ qpw_audio_init(Audiodev *dev, Error **errp)
return g_steal_pointer(&pw);
-fail_error:
- error_setg(errp, "Failed to initialize PW context");
fail:
if (pw->thread_loop) {
pw_thread_loop_stop(pw->thread_loop);
diff --git a/audio/trace-events b/audio/trace-events
index ab04f02..7e3f159 100644
--- a/audio/trace-events
+++ b/audio/trace-events
@@ -15,7 +15,7 @@ oss_version(int version) "OSS version = 0x%x"
# dbusaudio.c
dbus_audio_register(const char *s, const char *dir) "sender = %s, dir = %s"
-dbus_audio_put_buffer_out(size_t len) "len = %zu"
+dbus_audio_put_buffer_out(size_t pos, size_t size) "buf_pos = %zu, buf_size = %zu"
dbus_audio_read(size_t len) "len = %zu"
# pwaudio.c