spa: add interleave DSD param

And make alsa report the interleaving.
This commit is contained in:
Wim Taymans 2021-09-17 18:04:21 +02:00
parent 25d39a5ea1
commit af6e887077
6 changed files with 33 additions and 8 deletions

View file

@ -45,23 +45,24 @@ extern "C" {
/* DSD bits are transfered in a buffer grouped in bytes with the bitorder
* defined by \a bitorder.
*
* Channels are placed in separate planes or interleaved using the stride
* field of the buffer. The stride is then the number of bytes grouped per
* channel.
* Channels are placed in separate planes (interleave = 0) or interleaved
* using the interleave value. A negative interleave value means that the
* bytes need to be reversed in the group.
*
* Planar:
* Planar (interleave = 0):
* plane1: l1 l2 l3 l4 l5 ...
* plane2: r1 r2 r3 r4 r5 ...
*
* Interleaved stride 4:
* Interleaved 4:
* plane1: l1 l2 l3 l4 r1 r2 r3 r4 l5 l6 l7 l8 r5 r6 r7 r8 l9 ...
*
* Interleaved stride 2:
* Interleaved 2:
* plane1: l1 l2 r1 r2 l3 l4 r3 r4 ...
*/
struct spa_audio_info_dsd {
enum spa_param_bitorder bitorder; /*< the order of the bits */
uint32_t flags; /*< extra flags */
int32_t interleave; /*< interleave bytes */
uint32_t rate; /*< sample rate (in bits per second) */
uint32_t channels; /*< channels */
uint32_t position[SPA_AUDIO_MAX_CHANNELS]; /*< channel position from enum spa_audio_channel */

View file

@ -88,6 +88,7 @@ spa_format_audio_dsd_parse(const struct spa_pod *format, struct spa_audio_info_d
res = spa_pod_parse_object(format,
SPA_TYPE_OBJECT_Format, NULL,
SPA_FORMAT_AUDIO_bitorder, SPA_POD_Id(&info->bitorder),
SPA_FORMAT_AUDIO_interleave, SPA_POD_Int(&info->interleave),
SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&info->rate),
SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&info->channels),
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
@ -167,8 +168,13 @@ spa_format_audio_dsd_build(struct spa_pod_builder *builder, uint32_t id, struct
spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsd),
SPA_FORMAT_AUDIO_bitorder, SPA_POD_Id(info->bitorder),
0);
if (info->bitorder != SPA_PARAM_BITORDER_unknown)
spa_pod_builder_add(builder,
SPA_FORMAT_AUDIO_bitorder, SPA_POD_Id(info->bitorder), 0);
if (info->interleave != 0)
spa_pod_builder_add(builder,
SPA_FORMAT_AUDIO_interleave, SPA_POD_Int(info->interleave), 0);
if (info->rate != 0)
spa_pod_builder_add(builder,
SPA_FORMAT_AUDIO_rate, SPA_POD_Int(info->rate), 0);

View file

@ -115,6 +115,7 @@ enum spa_format {
SPA_FORMAT_AUDIO_iec958Codec, /**< codec used (IEC958) (Id enum spa_audio_iec958_codec) */
SPA_FORMAT_AUDIO_bitorder, /**< bit order (Id enum spa_param_bitorder) */
SPA_FORMAT_AUDIO_interleave, /**< Interleave bytes (Int) */
/* Video Format keys */
SPA_FORMAT_START_Video = 0x20000,

View file

@ -195,6 +195,7 @@ enum spa_param_process_latency {
};
enum spa_param_bitorder {
SPA_PARAM_BITORDER_unknown, /**< unknown bitorder */
SPA_PARAM_BITORDER_msb, /**< most significant bit */
SPA_PARAM_BITORDER_lsb, /**< least significant bit */
};

View file

@ -94,6 +94,7 @@ static const struct spa_type_info spa_type_prop_iec958_codec[] = {
#define SPA_TYPE_INFO_PARAM_BITORDER_BASE SPA_TYPE_INFO_ParamBitorder ":"
static const struct spa_type_info spa_type_param_bitorder[] = {
{ SPA_PARAM_BITORDER_unknown, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BITORDER_BASE "unknown", NULL },
{ SPA_PARAM_BITORDER_msb, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BITORDER_BASE "msb", NULL },
{ SPA_PARAM_BITORDER_lsb, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BITORDER_BASE "lsb", NULL },
{ 0, 0, NULL, NULL },
@ -280,6 +281,7 @@ static const struct spa_type_info spa_type_format[] = {
{ SPA_FORMAT_AUDIO_bitorder, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "bitorder",
spa_type_param_bitorder },
{ SPA_FORMAT_AUDIO_interleave, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "interleave", NULL },
{ SPA_FORMAT_VIDEO_format, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "format",
spa_type_video_format, },

View file

@ -720,6 +720,7 @@ static int enum_dsd_formats(struct state *state, uint32_t index, uint32_t *next,
snd_pcm_hw_params_t *params;
snd_pcm_format_mask_t *fmask;
struct spa_pod_frame f[2];
int32_t interleave;
if ((index & 0xffff) > 0)
return 0;
@ -731,7 +732,17 @@ static int enum_dsd_formats(struct state *state, uint32_t index, uint32_t *next,
snd_pcm_format_mask_alloca(&fmask);
snd_pcm_hw_params_get_format_mask(params, fmask);
if (!snd_pcm_format_mask_test(fmask, SND_PCM_FORMAT_DSD_U32_BE))
if (snd_pcm_format_mask_test(fmask, SND_PCM_FORMAT_DSD_U32_BE))
interleave = 4;
else if (snd_pcm_format_mask_test(fmask, SND_PCM_FORMAT_DSD_U32_LE))
interleave = -4;
else if (snd_pcm_format_mask_test(fmask, SND_PCM_FORMAT_DSD_U16_BE))
interleave = 2;
else if (snd_pcm_format_mask_test(fmask, SND_PCM_FORMAT_DSD_U16_LE))
interleave = -2;
else if (snd_pcm_format_mask_test(fmask, SND_PCM_FORMAT_DSD_U8))
interleave = 1;
else
return 0;
CHECK(snd_pcm_hw_params_set_rate_resample(hndl, params, 0), "set_rate_resample");
@ -745,6 +756,9 @@ static int enum_dsd_formats(struct state *state, uint32_t index, uint32_t *next,
spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_bitorder, 0);
spa_pod_builder_id(b, SPA_PARAM_BITORDER_msb);
spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_interleave, 0);
spa_pod_builder_int(b, interleave);
if ((res = add_rate(state, index & 0xffff, next, params, b)) != 1)
return res;