From 019b5ba7b31cf4512fd1bd927d4d7cc53c27cdc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 8 Mar 2020 20:33:16 +0100 Subject: [PATCH 1/6] qapi/audio: add documentation for AudioFormat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The review for patch ed2a4a7941 "audio: proper support for float samples in mixeng" suggested this would be a good idea. Acked-by: Markus Armbruster Signed-off-by: Volker Rümelin Tested-by: John Arbuckle Message-id: 20200308193321.20668-1-vr_qemu@t-online.de Signed-off-by: Gerd Hoffmann --- qapi/audio.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/qapi/audio.json b/qapi/audio.json index d8c507cced..c31251f45b 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -273,6 +273,20 @@ # # An enumeration of possible audio formats. # +# @u8: unsigned 8 bit integer +# +# @s8: signed 8 bit integer +# +# @u16: unsigned 16 bit integer +# +# @s16: signed 16 bit integer +# +# @u32: unsigned 32 bit integer +# +# @s32: signed 32 bit integer +# +# @f32: single precision floating-point (since 5.0) +# # Since: 4.0 ## { 'enum': 'AudioFormat', From dd381319a39d90e3fddd7afbedf5293a49d6f1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 8 Mar 2020 20:33:17 +0100 Subject: [PATCH 2/6] audio: change naming scheme of FLOAT_CONV macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch changes the naming scheme of the FLOAT_CONV_TO and FLOAT_CONV_FROM macros to the scheme used in mixeng_template.h. Signed-off-by: Volker Rümelin Message-id: 20200308193321.20668-2-vr_qemu@t-online.de Signed-off-by: Gerd Hoffmann --- audio/mixeng.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/audio/mixeng.c b/audio/mixeng.c index c14b0d874c..b57fad83bf 100644 --- a/audio/mixeng.c +++ b/audio/mixeng.c @@ -268,17 +268,17 @@ f_sample *mixeng_clip[2][2][2][3] = { }; #ifdef FLOAT_MIXENG -#define FLOAT_CONV_TO(x) (x) -#define FLOAT_CONV_FROM(x) (x) +#define CONV_NATURAL_FLOAT(x) (x) +#define CLIP_NATURAL_FLOAT(x) (x) #else static const float float_scale = UINT_MAX; -#define FLOAT_CONV_TO(x) ((x) * float_scale) +#define CONV_NATURAL_FLOAT(x) ((x) * float_scale) #ifdef RECIPROCAL static const float float_scale_reciprocal = 1.f / UINT_MAX; -#define FLOAT_CONV_FROM(x) ((x) * float_scale_reciprocal) +#define CLIP_NATURAL_FLOAT(x) ((x) * float_scale_reciprocal) #else -#define FLOAT_CONV_FROM(x) ((x) / float_scale) +#define CLIP_NATURAL_FLOAT(x) ((x) / float_scale) #endif #endif @@ -288,7 +288,7 @@ static void conv_natural_float_to_mono(struct st_sample *dst, const void *src, float *in = (float *)src; while (samples--) { - dst->r = dst->l = FLOAT_CONV_TO(*in++); + dst->r = dst->l = CONV_NATURAL_FLOAT(*in++); dst++; } } @@ -299,8 +299,8 @@ static void conv_natural_float_to_stereo(struct st_sample *dst, const void *src, float *in = (float *)src; while (samples--) { - dst->l = FLOAT_CONV_TO(*in++); - dst->r = FLOAT_CONV_TO(*in++); + dst->l = CONV_NATURAL_FLOAT(*in++); + dst->r = CONV_NATURAL_FLOAT(*in++); dst++; } } @@ -316,7 +316,7 @@ static void clip_natural_float_from_mono(void *dst, const struct st_sample *src, float *out = (float *)dst; while (samples--) { - *out++ = FLOAT_CONV_FROM(src->l) + FLOAT_CONV_FROM(src->r); + *out++ = CLIP_NATURAL_FLOAT(src->l) + CLIP_NATURAL_FLOAT(src->r); src++; } } @@ -327,8 +327,8 @@ static void clip_natural_float_from_stereo( float *out = (float *)dst; while (samples--) { - *out++ = FLOAT_CONV_FROM(src->l); - *out++ = FLOAT_CONV_FROM(src->r); + *out++ = CLIP_NATURAL_FLOAT(src->l); + *out++ = CLIP_NATURAL_FLOAT(src->r); src++; } } From 33a93baeae4ca8f03a84b194c55f6e5ee09c33f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 8 Mar 2020 20:33:18 +0100 Subject: [PATCH 3/6] audio: consistency changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the clip_natural_float_from_mono() function in audio/mixeng.c to be consistent with the clip_*_from_mono() functions in audio/mixeng_template.h. Signed-off-by: Volker Rümelin Message-id: 20200308193321.20668-3-vr_qemu@t-online.de Signed-off-by: Gerd Hoffmann --- audio/mixeng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audio/mixeng.c b/audio/mixeng.c index b57fad83bf..725b529be7 100644 --- a/audio/mixeng.c +++ b/audio/mixeng.c @@ -316,7 +316,7 @@ static void clip_natural_float_from_mono(void *dst, const struct st_sample *src, float *out = (float *)dst; while (samples--) { - *out++ = CLIP_NATURAL_FLOAT(src->l) + CLIP_NATURAL_FLOAT(src->r); + *out++ = CLIP_NATURAL_FLOAT(src->l + src->r); src++; } } From 4218fdd77f1c8ab4dab5ced30c3a0db946a6f04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 8 Mar 2020 20:33:19 +0100 Subject: [PATCH 4/6] audio: change mixing engine float range to [-1.f, 1.f] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the internal float range of the mixing engine is [-.5f, .5f]. PulseAudio, SDL2 and libasound use a [-1.f, 1.f] range. This means with float samples the audio playback volume is 6dB too low and audio recording signals will be clipped in most cases. To avoid another scaling factor in the conv_natural_float_* and clip_natural_float_* functions with FLOAT_MIXENG defined this patch changes the mixing engine float range to [-1.f, 1.f]. Signed-off-by: Volker Rümelin Message-id: 20200308193321.20668-4-vr_qemu@t-online.de Signed-off-by: Gerd Hoffmann --- audio/mixeng.c | 4 ++-- audio/mixeng_template.h | 17 ++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/audio/mixeng.c b/audio/mixeng.c index 725b529be7..739a500449 100644 --- a/audio/mixeng.c +++ b/audio/mixeng.c @@ -271,11 +271,11 @@ f_sample *mixeng_clip[2][2][2][3] = { #define CONV_NATURAL_FLOAT(x) (x) #define CLIP_NATURAL_FLOAT(x) (x) #else -static const float float_scale = UINT_MAX; +static const float float_scale = UINT_MAX / 2.f; #define CONV_NATURAL_FLOAT(x) ((x) * float_scale) #ifdef RECIPROCAL -static const float float_scale_reciprocal = 1.f / UINT_MAX; +static const float float_scale_reciprocal = 2.f / UINT_MAX; #define CLIP_NATURAL_FLOAT(x) ((x) * float_scale_reciprocal) #else #define CLIP_NATURAL_FLOAT(x) ((x) / float_scale) diff --git a/audio/mixeng_template.h b/audio/mixeng_template.h index 77cc89b9e8..fc8e1d4d9e 100644 --- a/audio/mixeng_template.h +++ b/audio/mixeng_template.h @@ -41,32 +41,31 @@ static inline mixeng_real glue (conv_, ET) (IN_T v) #ifdef RECIPROCAL #ifdef SIGNED - return nv * (1.f / (mixeng_real) (IN_MAX - IN_MIN)); + return nv * (2.f / ((mixeng_real)IN_MAX - IN_MIN)); #else - return (nv - HALF) * (1.f / (mixeng_real) IN_MAX); + return (nv - HALF) * (2.f / (mixeng_real)IN_MAX); #endif #else /* !RECIPROCAL */ #ifdef SIGNED - return nv / (mixeng_real) ((mixeng_real) IN_MAX - IN_MIN); + return nv / (((mixeng_real)IN_MAX - IN_MIN) / 2.f); #else - return (nv - HALF) / (mixeng_real) IN_MAX; + return (nv - HALF) / ((mixeng_real)IN_MAX / 2.f); #endif #endif } static inline IN_T glue (clip_, ET) (mixeng_real v) { - if (v >= 0.5) { + if (v >= 1.f) { return IN_MAX; - } - else if (v < -0.5) { + } else if (v < -1.f) { return IN_MIN; } #ifdef SIGNED - return ENDIAN_CONVERT ((IN_T) (v * ((mixeng_real) IN_MAX - IN_MIN))); + return ENDIAN_CONVERT((IN_T)(v * (((mixeng_real)IN_MAX - IN_MIN) / 2.f))); #else - return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF)); + return ENDIAN_CONVERT((IN_T)((v * ((mixeng_real)IN_MAX / 2.f)) + HALF)); #endif } From 194bdf50697689768335096b6c01c5b010f023ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 8 Mar 2020 20:33:20 +0100 Subject: [PATCH 5/6] audio: fix saturation nonlinearity in clip_* functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current positive limit for the saturation nonlinearity is only correct if the type of the result has 8 bits or less. Signed-off-by: Volker Rümelin Message-id: 20200308193321.20668-5-vr_qemu@t-online.de Signed-off-by: Gerd Hoffmann --- audio/mixeng_template.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/audio/mixeng_template.h b/audio/mixeng_template.h index fc8e1d4d9e..bc8509e423 100644 --- a/audio/mixeng_template.h +++ b/audio/mixeng_template.h @@ -83,10 +83,9 @@ static inline int64_t glue (conv_, ET) (IN_T v) static inline IN_T glue (clip_, ET) (int64_t v) { - if (v >= 0x7f000000) { + if (v >= 0x7fffffffLL) { return IN_MAX; - } - else if (v < -2147483648LL) { + } else if (v < -2147483648LL) { return IN_MIN; } From 49f77e6faf36cddd84417f9080462413acdbcc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 8 Mar 2020 20:33:21 +0100 Subject: [PATCH 6/6] audio: add audiodev format=f32 option documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentaion for -audiodev format=f32 option was missing. Signed-off-by: Volker Rümelin Message-id: 20200308193321.20668-6-vr_qemu@t-online.de Signed-off-by: Gerd Hoffmann --- qemu-options.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 1d8f852d89..962a5ebaa6 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -551,7 +551,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, " in|out.frequency= frequency to use with fixed settings\n" " in|out.channels= number of channels to use with fixed settings\n" " in|out.format= sample format to use with fixed settings\n" - " valid values: s8, s16, s32, u8, u16, u32\n" + " valid values: s8, s16, s32, u8, u16, u32, f32\n" " in|out.voices= number of voices to use\n" " in|out.buffer-length= length of buffer in microseconds\n" "-audiodev none,id=id,[,prop[=value][,...]]\n" @@ -647,7 +647,7 @@ SRST ``in|out.format=format`` Specify the sample format to use when using fixed-settings. Valid values are: ``s8``, ``s16``, ``s32``, ``u8``, ``u16``, - ``u32``. Default is ``s16``. + ``u32``, ``f32``. Default is ``s16``. ``in|out.voices=voices`` Specify the number of voices to use. Default is 1.