mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'audio-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging
Audio patches - add float sample endianness converters - various fixes # -----BEGIN PGP SIGNATURE----- # # iQJQBAABCgA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmgzGnEcHG1hcmNhbmRy # ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5YkCEACA7BmZRorXwWuozmOK # /I6ar0j6VjpKOzFQFo2Sy4vfLOb2rl5Q3Fb02Dk3nR9f3FpYmoIKF9sbBUdL095v # Nhj8wNyCiM/QTFFPXNKa92ubovCyC25pyVLogXmMaa5YhhZpF4wcx/ermhbyhhmL # GTmqfbnN8ki6jQ22ftKGBbcvny4xakKaLJdQtk/joSk0PF67FKZrenjVkcNThFwY # kHyyBCdm2G8VVVyxfHk+/S22+eMkeTZfJgMo2WfYpWWqLTTkrASJNjf8oG+bfzAa # +iMyUzEHDK+rOatcb5SbZltfEljdBh+2LaPEziEZWGfbwKA1/QHztBn3Rs6CwVdS # AU2F9gWhL1GOBIaop1I3EvJ1eGQZCZex08gV7jgdLdBh0x6NLKahqHU9CMHsY07a # zhp4FsFPs4G9cmmbw064qPAdI11hhLiqckaI91gYVIJQXOf92hGcyP5M03qXbPDL # D3WXjnBdVXhaB0Ih41TqYbkTwTMxGGC13lB10UsnNO03yzrIkGOMywJJ564dtpHX # TzchYDLO9Vg/p6Y9fW95jC+AbCZasStzmkOwxWiIK5hBhxoV2iAdiLsTtSMNO1P7 # eyMUE9P+LaPgTz57cXQ+QpD3126T/QKmAzfgPXu7AHDCmaz4/boc0sOQLa5UVRNN # KH506pqjeOLRaAcTdEubTDiriw== # =UYr7 # -----END PGP SIGNATURE----- # gpg: Signature made Sun 25 May 2025 09:26:09 EDT # gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5 # gpg: issuer "marcandre.lureau@redhat.com" # gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full] # gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full] # Primary key fingerprint: 87A9 BD93 3F87 C606 D276 F62D DAE8 E109 7596 9CE5 * tag 'audio-pull-request' of https://gitlab.com/marcandre.lureau/qemu: audio: Reset rate control when adding bytes alsaaudio: Set try-poll to false by default audio: add float sample endianness converters audio/mixeng: remove unnecessary pointer type casts hw/audio/asc: replace g_malloc0() with g_malloc() hw/audio/asc: fix SIGSEGV in asc_realize() audio: fix size calculation in AUD_get_buffer_size_out() audio: fix SIGSEGV in AUD_get_buffer_size_out() tests/functional: use 'none' audio driver for q800 tests Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
+1
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-7
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
+73
-10
@@ -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,
|
||||
|
||||
+3
-3
@@ -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,
|
||||
|
||||
+8
-1
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/irq.h"
|
||||
#include "audio/audio.h"
|
||||
@@ -653,11 +654,17 @@ static void asc_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
s->voice = AUD_open_out(&s->card, s->voice, "asc.out", s, asc_out_cb,
|
||||
&as);
|
||||
if (!s->voice) {
|
||||
AUD_remove_card(&s->card);
|
||||
error_setg(errp, "Initializing audio stream failed");
|
||||
return;
|
||||
}
|
||||
|
||||
s->shift = 1;
|
||||
s->samples = AUD_get_buffer_size_out(s->voice) >> s->shift;
|
||||
s->mixbuf = g_malloc0(s->samples << s->shift);
|
||||
|
||||
s->silentbuf = g_malloc0(s->samples << s->shift);
|
||||
s->silentbuf = g_malloc(s->samples << s->shift);
|
||||
memset(s->silentbuf, 0x80, s->samples << s->shift);
|
||||
|
||||
/* Add easc registers if required */
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@
|
||||
# @period-length: the period length in microseconds
|
||||
#
|
||||
# @try-poll: attempt to use poll mode, falling back to non-polling
|
||||
# access on failure (default true)
|
||||
# access on failure (default false)
|
||||
#
|
||||
# Since: 4.0
|
||||
##
|
||||
|
||||
+2
-2
@@ -965,7 +965,7 @@ SRST
|
||||
Sets the period length in microseconds.
|
||||
|
||||
``in|out.try-poll=on|off``
|
||||
Attempt to use poll mode with the device. Default is on.
|
||||
Attempt to use poll mode with the device. Default is off.
|
||||
|
||||
``threshold=threshold``
|
||||
Threshold (in microseconds) when playback starts. Default is 0.
|
||||
@@ -1002,7 +1002,7 @@ SRST
|
||||
``in|out.buffer-count=count``
|
||||
Sets the count of the buffers.
|
||||
|
||||
``in|out.try-poll=on|of``
|
||||
``in|out.try-poll=on|off``
|
||||
Attempt to use poll mode with the device. Default is on.
|
||||
|
||||
``try-mmap=on|off``
|
||||
|
||||
@@ -25,7 +25,8 @@ class Q800MachineTest(LinuxKernelTest):
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
'console=ttyS0 vga=off')
|
||||
self.vm.add_args('-kernel', kernel_path,
|
||||
'-append', kernel_command_line)
|
||||
'-append', kernel_command_line,
|
||||
'-audio', 'none')
|
||||
self.vm.launch()
|
||||
console_pattern = 'Kernel command line: %s' % kernel_command_line
|
||||
self.wait_for_console_pattern(console_pattern)
|
||||
|
||||
@@ -24,7 +24,8 @@ class M68kReplay(ReplayKernelBase):
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
'console=ttyS0 vga=off')
|
||||
console_pattern = 'No filesystem could mount root'
|
||||
self.run_rr(kernel_path, kernel_command_line, console_pattern)
|
||||
self.run_rr(kernel_path, kernel_command_line, console_pattern,
|
||||
args=('-audio', 'none'))
|
||||
|
||||
ASSET_MCF5208 = Asset(
|
||||
'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day07.tar.xz',
|
||||
|
||||
Reference in New Issue
Block a user