Commit 6624eaaf authored by Julian Bouzas's avatar Julian Bouzas Committed by George Kiagiadakis
Browse files

m-si-audio-adapter: remove unused audio utilities

parent eff97aed
Pipeline #427733 passed with stages
in 1 minute and 40 seconds
......@@ -104,7 +104,6 @@ shared_library(
'wireplumber-module-si-audio-adapter',
[
'module-si-audio-adapter.c',
'module-si-audio-adapter/audio-utils.c',
],
c_args : [common_c_args, '-DG_LOG_DOMAIN="m-si-audio-adapter"'],
install : true,
......
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include <wp/wp.h>
#include <pipewire/pipewire.h>
#include <spa/param/format-utils.h>
#include <spa/param/audio/format.h>
#include "audio-utils.h"
static enum spa_audio_format
select_format (WpSpaPod *value)
{
enum spa_audio_format ret = SPA_AUDIO_FORMAT_UNKNOWN;
static enum spa_audio_format fmt_order[] = {
/* float 32 is the best because it needs
no conversion from our internal pipeline format */
SPA_AUDIO_FORMAT_F32,
/* signed 16-bit is known to work very well;
unsigned should also be fine */
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_U16,
/* then go for the formats that are aligned to sizeof(int),
from the best quality to the worst */
SPA_AUDIO_FORMAT_S32,
SPA_AUDIO_FORMAT_U32,
SPA_AUDIO_FORMAT_S24_32,
SPA_AUDIO_FORMAT_U24_32,
/* then float 64, which should need little conversion from float 32 */
SPA_AUDIO_FORMAT_F64,
/* and then try the reverse endianess too */
SPA_AUDIO_FORMAT_F32_OE,
SPA_AUDIO_FORMAT_S16_OE,
SPA_AUDIO_FORMAT_U16_OE,
SPA_AUDIO_FORMAT_S32_OE,
SPA_AUDIO_FORMAT_U32_OE,
SPA_AUDIO_FORMAT_S24_32_OE,
SPA_AUDIO_FORMAT_U24_32_OE,
SPA_AUDIO_FORMAT_F64_OE,
/* then go for unaligned strange formats */
SPA_AUDIO_FORMAT_S24,
SPA_AUDIO_FORMAT_U24,
SPA_AUDIO_FORMAT_S20,
SPA_AUDIO_FORMAT_U20,
SPA_AUDIO_FORMAT_S18,
SPA_AUDIO_FORMAT_U18,
SPA_AUDIO_FORMAT_S24_OE,
SPA_AUDIO_FORMAT_U24_OE,
SPA_AUDIO_FORMAT_S20_OE,
SPA_AUDIO_FORMAT_U20_OE,
SPA_AUDIO_FORMAT_S18_OE,
SPA_AUDIO_FORMAT_U18_OE,
/* leave 8-bit last, that's bad quality */
SPA_AUDIO_FORMAT_S8,
SPA_AUDIO_FORMAT_U8,
/* plannar formats are problematic currently, discourage their use */
SPA_AUDIO_FORMAT_F32P,
SPA_AUDIO_FORMAT_S16P,
SPA_AUDIO_FORMAT_S32P,
SPA_AUDIO_FORMAT_S24_32P,
SPA_AUDIO_FORMAT_S24P,
SPA_AUDIO_FORMAT_F64P,
SPA_AUDIO_FORMAT_U8P,
};
guint32 best = SPA_N_ELEMENTS(fmt_order);
/* Just return the value if it is not a choice value */
if (!wp_spa_pod_is_choice (value)) {
wp_spa_pod_get_id (value, &ret);
return ret;
}
guint32 choice_type =
wp_spa_id_value_number (wp_spa_pod_get_choice_type (value));
/* None */
if (choice_type == SPA_CHOICE_None) {
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value);
wp_spa_pod_get_id (child, &ret);
}
/* Enum */
else if (choice_type == SPA_CHOICE_Enum) {
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (value);
GValue next = G_VALUE_INIT;
while (wp_iterator_next (it, &next)) {
enum spa_audio_format *format_id = (enum spa_audio_format *)
g_value_get_pointer (&next);
for (guint j = 0; j < SPA_N_ELEMENTS(fmt_order); j++) {
if (*format_id == fmt_order[j] && best > j) {
best = j;
break;
}
}
g_value_unset (&next);
}
if (best < SPA_N_ELEMENTS(fmt_order))
ret = fmt_order[best];
}
return ret;
}
static gint
select_rate (WpSpaPod *value)
{
gint ret = 0;
/* Just return the value if it is not a choice value */
if (!wp_spa_pod_is_choice (value)) {
wp_spa_pod_get_int (value, &ret);
return ret;
}
guint32 choice_type =
wp_spa_id_value_number (wp_spa_pod_get_choice_type (value));
/* None */
if (choice_type == SPA_CHOICE_None) {
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value);
wp_spa_pod_get_int (child, &ret);
}
/* Enum */
else if (choice_type == SPA_CHOICE_Enum) {
/* pick the one closest to 48Khz */
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (value);
GValue next = G_VALUE_INIT;
while (wp_iterator_next (it, &next)) {
gint *rate = (gint *) g_value_get_pointer (&next);
if (abs (*rate - 48000) < abs (ret - 48000))
ret = *rate;
g_value_unset (&next);
}
}
/* Range */
else if (choice_type == SPA_CHOICE_Range) {
/* a range is typically 3 items: default, min, max;
however, sometimes ALSA drivers give bad min & max values
and pipewire picks a bad default... try to fix that here;
the default should be the one closest to 48K */
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (value);
GValue next = G_VALUE_INIT;
gint vals[3];
gint i = 0, min, max;
while (wp_iterator_next (it, &next) && i < 3) {
vals[i] = *(gint *) g_value_get_pointer (&next);
g_value_unset (&next);
i++;
}
min = SPA_MIN (vals[1], vals[2]);
max = SPA_MAX (vals[1], vals[2]);
ret = SPA_CLAMP (48000, min, max);
}
return ret;
}
static gint
select_channels (WpSpaPod *value, gint preference)
{
gint ret = 0;
/* Just return the value if it is not a choice value */
if (!wp_spa_pod_is_choice (value)) {
wp_spa_pod_get_int (value, &ret);
return ret;
}
guint32 choice_type =
wp_spa_id_value_number (wp_spa_pod_get_choice_type (value));
/* None */
if (choice_type == SPA_CHOICE_None) {
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value);
wp_spa_pod_get_int (child, &ret);
}
/* Enum */
else if (choice_type == SPA_CHOICE_Enum) {
/* choose the most channels */
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (value);
GValue next = G_VALUE_INIT;
gint diff = SPA_AUDIO_MAX_CHANNELS;
while (wp_iterator_next (it, &next)) {
gint *channel = (gint *) g_value_get_pointer (&next);
if (abs (*channel - preference) < diff) {
diff = abs (*channel - preference);
ret = *channel;
}
g_value_unset (&next);
}
}
/* Range */
else if (choice_type == SPA_CHOICE_Range) {
/* a range is typically 3 items: default, min, max;
we want the most channels, but let's not trust max
to really be the max... ALSA drivers can be broken */
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (value);
GValue next = G_VALUE_INIT;
gint vals[3];
gint i = 0;
while (wp_iterator_next (it, &next) && i < 3) {
vals[i] = *(gint *) g_value_get_pointer (&next);
g_value_unset (&next);
i++;
}
ret = SPA_MAX (vals[1], preference);
ret = SPA_MIN (ret, vals[2]);
}
return ret;
}
gboolean
choose_sensible_raw_audio_format (WpIterator *formats,
gint channels_preference, struct spa_audio_info_raw *result)
{
guint most_channels = 0;
struct spa_audio_info_raw raw;
g_auto (GValue) item = G_VALUE_INIT;
for (; wp_iterator_next (formats, &item); g_value_unset (&item)) {
WpSpaPod *pod = g_value_get_boxed (&item);
uint32_t mtype, mstype;
/* initialize all fields to zero (SPA_AUDIO_FORMAT_UNKNOWN etc) and set
the unpositioned flag, which means there is no channel position array */
spa_memzero (&raw, sizeof(struct spa_audio_info_raw));
SPA_FLAG_SET(raw.flags, SPA_AUDIO_FLAG_UNPOSITIONED);
if (!wp_spa_pod_is_object (pod)) {
g_warning ("non-object POD appeared on formats list; this node is buggy");
continue;
}
if (!wp_spa_pod_get_object (pod, NULL,
"mediaType", "I", &mtype,
"mediaSubtype", "I", &mstype,
NULL)) {
g_warning ("format does not have media type / subtype");
continue;
}
if (!(mtype == SPA_MEDIA_TYPE_audio && mstype == SPA_MEDIA_SUBTYPE_raw))
continue;
/* go through the fields and populate raw */
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (pod);
GValue next = G_VALUE_INIT;
while (wp_iterator_next (it, &next)) {
WpSpaPod *p = g_value_get_boxed (&next);
const gchar *key = NULL;
g_autoptr (WpSpaPod) value = NULL;
wp_spa_pod_get_property (p, &key, &value);
/* format */
if (g_strcmp0 (key, "format") == 0) {
raw.format = select_format (value);
}
/* rate */
else if (g_strcmp0 (key, "rate") == 0) {
raw.rate = select_rate (value);
}
/* channels */
else if (g_strcmp0 (key, "channels") == 0) {
raw.channels = select_channels (value, channels_preference);
}
/* position */
else if (g_strcmp0 (key, "position") == 0) {
/* just copy the array, there is no choice here */
g_return_val_if_fail (wp_spa_pod_is_array (value), FALSE);
SPA_FLAG_CLEAR (raw.flags, SPA_AUDIO_FLAG_UNPOSITIONED);
g_autoptr (WpIterator) array_it = wp_spa_pod_new_iterator (value);
GValue array_next = G_VALUE_INIT;
guint j = 0;
while (wp_iterator_next (array_it, &array_next)) {
guint32 *pos_id = (guint32 *)g_value_get_pointer (&array_next);
raw.position[j] = *pos_id;
g_value_unset (&array_next);
j++;
}
}
g_value_unset (&next);
}
/* figure out if this one is the best so far */
if (raw.format != SPA_AUDIO_FORMAT_UNKNOWN &&
raw.channels > most_channels ) {
most_channels = raw.channels;
*result = raw;
}
}
/* if we picked a format, most_channels must be > 0 */
return (most_channels > 0);
}
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
struct spa_audio_info_raw;
gboolean choose_sensible_raw_audio_format (WpIterator *formats,
gint channels_preference, struct spa_audio_info_raw *result);
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include <wp/wp.h>
#include <pipewire/pipewire.h>
#include <spa/pod/builder.h>
#include <spa/param/audio/raw.h>
#include <spa/param/audio/layout.h>
#include <spa/param/audio/format.h>
#include <spa/param/audio/format-utils.h>
#include "../../modules/module-si-audio-adapter/audio-utils.h"
static void
test_choose_sensible_raw_audio_format (void)
{
uint32_t layout[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR,
SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR };
struct spa_audio_info_raw info;
g_autoptr (GPtrArray) formats =
g_ptr_array_new_with_free_func ((GDestroyNotify) wp_spa_pod_unref);
{
g_ptr_array_remove_range (formats, 0, formats->len);
g_autoptr (WpSpaPod) param1 = wp_spa_pod_new_object (
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio),
"mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
"format", SPA_POD_CHOICE_ENUM_Id(3,
SPA_AUDIO_FORMAT_F32_OE,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S20),
"rate", SPA_POD_CHOICE_RANGE_Int(22000, 44100, 8000),
"channels", SPA_POD_CHOICE_RANGE_Int(2, 1, 8),
NULL);
g_assert_nonnull (param1);
g_ptr_array_add (formats, g_steal_pointer (&param1));
g_autoptr (WpIterator) it =
wp_iterator_new_ptr_array (g_ptr_array_ref (formats), WP_TYPE_SPA_POD);
g_assert_true (choose_sensible_raw_audio_format (it, 34, &info));
g_assert_cmpint (info.format, ==, SPA_AUDIO_FORMAT_S16);
g_assert_cmpint (info.rate, ==, 44100);
g_assert_cmpint (info.channels, ==, 8);
g_assert_cmpint (info.flags, ==, SPA_AUDIO_FLAG_UNPOSITIONED);
}
{
g_ptr_array_remove_range (formats, 0, formats->len);
g_autoptr (WpSpaPod) param1 = wp_spa_pod_new_object (
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio),
"mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
"format", SPA_POD_CHOICE_ENUM_Id(3,
SPA_AUDIO_FORMAT_F32_OE,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S20),
"rate", SPA_POD_CHOICE_RANGE_Int(22000, 44100, 8000),
"channels", SPA_POD_CHOICE_RANGE_Int(2, 1, 8),
NULL);
g_assert_nonnull (param1);
g_ptr_array_add (formats, g_steal_pointer (&param1));
g_autoptr (WpIterator) it =
wp_iterator_new_ptr_array (g_ptr_array_ref (formats), WP_TYPE_SPA_POD);
g_assert_true (choose_sensible_raw_audio_format (it, 2, &info));
g_assert_cmpint (info.format, ==, SPA_AUDIO_FORMAT_S16);
g_assert_cmpint (info.rate, ==, 44100);
g_assert_cmpint (info.channels, ==, 2);
g_assert_cmpint (info.flags, ==, SPA_AUDIO_FLAG_UNPOSITIONED);
}
{
g_ptr_array_remove_range (formats, 0, formats->len);
g_autoptr (WpSpaPod) param2 = wp_spa_pod_new_object (
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio),
"mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
"format", SPA_POD_CHOICE_ENUM_Id(3,
SPA_AUDIO_FORMAT_S32,
SPA_AUDIO_FORMAT_U8,
SPA_AUDIO_FORMAT_F32),
"rate", SPA_POD_CHOICE_RANGE_Int(56000, 44100, 96000),
"channels", SPA_POD_Int(2),
"position", SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, 2, layout),
NULL);
g_assert_nonnull (param2);
g_ptr_array_add (formats, g_steal_pointer (&param2));
g_autoptr (WpSpaPod) param3 = wp_spa_pod_new_object (
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio),
"mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
"format", SPA_POD_CHOICE_ENUM_Id(3,
SPA_AUDIO_FORMAT_S32,
SPA_AUDIO_FORMAT_U8,
SPA_AUDIO_FORMAT_F32),
"rate", SPA_POD_CHOICE_RANGE_Int(56000, 44100, 96000),
"channels", SPA_POD_Int(5),
"position", SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, 5, layout),
NULL);
g_assert_nonnull (param3);
g_ptr_array_add (formats, g_steal_pointer (&param3));
g_autoptr (WpIterator) it =
wp_iterator_new_ptr_array (g_ptr_array_ref (formats), WP_TYPE_SPA_POD);
g_assert_true (choose_sensible_raw_audio_format (it, 34, &info));
g_assert_cmpint (info.format, ==, SPA_AUDIO_FORMAT_F32);
g_assert_cmpint (info.rate, ==, 48000);
g_assert_cmpint (info.channels, ==, 5);
g_assert_cmpint (info.flags, ==, SPA_AUDIO_FLAG_NONE);
g_assert_cmpint (info.position[0], ==, layout[0]);
g_assert_cmpint (info.position[1], ==, layout[1]);
g_assert_cmpint (info.position[2], ==, layout[2]);
g_assert_cmpint (info.position[3], ==, layout[3]);
g_assert_cmpint (info.position[4], ==, layout[4]);
g_assert_cmpint (info.position[5], ==, 0);
}
}
int
main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_log_set_writer_func (wp_log_writer_default, NULL, NULL);
g_test_add_func ("/modules/audio_utils/choose_sensible_raw_audio_format",
test_choose_sensible_raw_audio_format);
return g_test_run ();
}
......@@ -6,17 +6,6 @@ common_args = [
'-DG_LOG_USE_STRUCTURED',
]
test(
'test-audio-utils',
executable('test-audio-utils',
[
'audio-utils.c',
'../../modules/module-si-audio-adapter/audio-utils.c'
],
dependencies: common_deps, c_args: common_args),
env: common_env,
)
test(
'test-reserve-device',
executable('test-reserve-device', 'reserve-device.c',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment