audio: remove layout from audio

Make special format types for planar and interleaved instead of
having a field.
Add enum for audio channel positions
Add some default audio channel layouts
Place the channel layout in the audio format when possible
alsa: place audio channel positions in format
Add sse optimized channel mixing for some common cases
Remove name from port info, it's not mandatory and in the properties
Add direction to port info
This commit is contained in:
Wim Taymans 2018-09-13 17:03:56 +02:00
parent fb3379e587
commit 5196f7f053
38 changed files with 981 additions and 369 deletions

View file

@ -33,29 +33,41 @@ extern "C" {
static inline int
spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_raw *info)
{
return spa_pod_object_parse(format,
struct spa_pod *position = NULL;
int res;
res = spa_pod_object_parse(format,
":", SPA_FORMAT_AUDIO_format, "I", &info->format,
":", SPA_FORMAT_AUDIO_layout, "I", &info->layout,
":", SPA_FORMAT_AUDIO_rate, "i", &info->rate,
":", SPA_FORMAT_AUDIO_channels, "i", &info->channels,
":", SPA_FORMAT_AUDIO_flags, "?i", &info->flags,
":", SPA_FORMAT_AUDIO_channelMask, "?l", &info->channel_mask, NULL);
":", SPA_FORMAT_AUDIO_position, "?P", &position, NULL);
if (position && position->type == SPA_TYPE_Array &&
SPA_POD_ARRAY_TYPE(position) == SPA_TYPE_Id) {
uint32_t *values = SPA_POD_ARRAY_VALUES(position);
uint32_t n_values = SPA_MIN(SPA_POD_ARRAY_N_VALUES(position), SPA_AUDIO_MAX_CHANNELS);
memcpy(info->position, values, n_values * sizeof(uint32_t));
}
return res;
}
static inline struct spa_pod *
spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_raw *info)
{
return spa_pod_builder_object(builder,
SPA_TYPE_OBJECT_Format, id,
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, id);
spa_pod_builder_props(builder,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(info->format),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(info->layout),
SPA_FORMAT_AUDIO_rate, &SPA_POD_Int(info->rate),
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(info->channels),
0);
spa_pod_builder_prop(builder, SPA_FORMAT_AUDIO_position, 0);
spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id, info->channels, info->position);
return spa_pod_builder_pop(builder);
}
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -26,9 +26,14 @@ extern "C" {
#include <endian.h>
#define SPA_AUDIO_MAX_CHANNELS 64
enum spa_audio_format {
SPA_AUDIO_FORMAT_UNKNOWN,
SPA_AUDIO_FORMAT_ENCODED,
/* interleaved formats */
SPA_AUDIO_FORMAT_START_Interleaved = 0x100,
SPA_AUDIO_FORMAT_S8,
SPA_AUDIO_FORMAT_U8,
SPA_AUDIO_FORMAT_S16_LE,
@ -60,6 +65,18 @@ enum spa_audio_format {
SPA_AUDIO_FORMAT_F64_LE,
SPA_AUDIO_FORMAT_F64_BE,
/* planar formats */
SPA_AUDIO_FORMAT_START_Planar = 0x200,
SPA_AUDIO_FORMAT_U8P,
SPA_AUDIO_FORMAT_S16P,
SPA_AUDIO_FORMAT_S24_32P,
SPA_AUDIO_FORMAT_S32P,
SPA_AUDIO_FORMAT_S24P,
SPA_AUDIO_FORMAT_F32P,
SPA_AUDIO_FORMAT_F64P,
SPA_AUDIO_FORMAT_START_Other = 0x300,
#if __BYTE_ORDER == __BIG_ENDIAN
SPA_AUDIO_FORMAT_S16 = SPA_AUDIO_FORMAT_S16_BE,
SPA_AUDIO_FORMAT_U16 = SPA_AUDIO_FORMAT_U16_BE,
@ -121,26 +138,97 @@ enum spa_audio_format {
#endif
};
#define SPA_AUDIO_FORMAT_IS_INTERLEAVED(fmt) ((fmt) > SPA_AUDIO_FORMAT_START_Interleaved && (fmt) < SPA_AUDIO_FORMAT_START_Planar)
#define SPA_AUDIO_FORMAT_IS_PLANAR(fmt) ((fmt) > SPA_AUDIO_FORMAT_START_Planar && (fmt) < SPA_AUDIO_FORMAT_START_Other)
enum spa_audio_channel {
SPA_AUDIO_CHANNEL_UNKNOWN, /**< unspecified */
SPA_AUDIO_CHANNEL_NA, /**< N/A, silent */
SPA_AUDIO_CHANNEL_MONO, /**< mono stream */
SPA_AUDIO_CHANNEL_FL, /**< front left */
SPA_AUDIO_CHANNEL_FR, /**< front right */
SPA_AUDIO_CHANNEL_RL, /**< rear left */
SPA_AUDIO_CHANNEL_RR, /**< rear right */
SPA_AUDIO_CHANNEL_FC, /**< front center */
SPA_AUDIO_CHANNEL_LFE, /**< LFE */
SPA_AUDIO_CHANNEL_SL, /**< side left */
SPA_AUDIO_CHANNEL_SR, /**< side right */
SPA_AUDIO_CHANNEL_RC, /**< rear center */
SPA_AUDIO_CHANNEL_FLC, /**< front left center */
SPA_AUDIO_CHANNEL_FRC, /**< front right center */
SPA_AUDIO_CHANNEL_RLC, /**< rear left center */
SPA_AUDIO_CHANNEL_RRC, /**< rear right center */
SPA_AUDIO_CHANNEL_FLW, /**< front left wide */
SPA_AUDIO_CHANNEL_FRW, /**< front right wide */
SPA_AUDIO_CHANNEL_FLH, /**< front left high */
SPA_AUDIO_CHANNEL_FCH, /**< front center high */
SPA_AUDIO_CHANNEL_FRH, /**< front right high */
SPA_AUDIO_CHANNEL_TC, /**< top center */
SPA_AUDIO_CHANNEL_TFL, /**< top front left */
SPA_AUDIO_CHANNEL_TFR, /**< top front right */
SPA_AUDIO_CHANNEL_TFC, /**< top front center */
SPA_AUDIO_CHANNEL_TRL, /**< top rear left */
SPA_AUDIO_CHANNEL_TRR, /**< top rear right */
SPA_AUDIO_CHANNEL_TRC, /**< top rear center */
SPA_AUDIO_CHANNEL_TFLC, /**< top front left center */
SPA_AUDIO_CHANNEL_TFRC, /**< top front right center */
SPA_AUDIO_CHANNEL_TSL, /**< top side left */
SPA_AUDIO_CHANNEL_TSR, /**< top side right */
SPA_AUDIO_CHANNEL_LLFE, /**< left LFE */
SPA_AUDIO_CHANNEL_RLFE, /**< right LFE */
SPA_AUDIO_CHANNEL_BC, /**< bottom center */
SPA_AUDIO_CHANNEL_BLC, /**< bottom left center */
SPA_AUDIO_CHANNEL_BRC, /**< bottom right center */
SPA_AUDIO_CHANNEL_CUSTOM_START = 0x10000,
};
#define SPA_AUDIO_CHANNEL_MASK(ch) (1LL << SPA_AUDIO_CHANNEL_ ## ch)
enum spa_audio_layout {
SPA_AUDIO_LAYOUT_DEFAULT, /**< default layout for the number of channels */
SPA_AUDIO_LAYOUT_CUSTOM, /**< custom layout, either the order of the channels is
* non-standard or the channel position array contains
* custom channels. */
SPA_AUDIO_LAYOUT_MONO, /**< MONO */
SPA_AUDIO_LAYOUT_STEREO, /**< FL FR */
SPA_AUDIO_LAYOUT_2_1, /**< FL FR LFE */
SPA_AUDIO_LAYOUT_2RC, /**< FL FR RC */
SPA_AUDIO_LAYOUT_2FC, /**< FL FR FC */
SPA_AUDIO_LAYOUT_3_1, /**< FL FR FC LFE */
SPA_AUDIO_LAYOUT_4_0, /**< FL FR FC RC */
SPA_AUDIO_LAYOUT_4_1, /**< FL FR FC RC LFE */
SPA_AUDIO_LAYOUT_2_2, /**< FL FR SL SR */
SPA_AUDIO_LAYOUT_QUAD, /**< FL FR RL RR */
SPA_AUDIO_LAYOUT_5_0, /**< FL FR FC SL SR */
SPA_AUDIO_LAYOUT_5_1, /**< FL FR FC SL SR LFE */
SPA_AUDIO_LAYOUT_5_0R, /**< FL FR FC RL RR */
SPA_AUDIO_LAYOUT_5_1R, /**< FL FR FC RL RR LFE */
SPA_AUDIO_LAYOUT_6_0, /**< FL FR FC SL SR RC */
SPA_AUDIO_LAYOUT_6_0F, /**< FL FR SL SR FLC FRC */
SPA_AUDIO_LAYOUT_HEXAGONAL, /**< FL FR FC RL RR RC */
SPA_AUDIO_LAYOUT_6_1, /**< FL FR FC SL SR LFE RC */
SPA_AUDIO_LAYOUT_6_1R, /**< FL FR FC RL RR LFE RC */
SPA_AUDIO_LAYOUT_6_1F, /**< FL FR SL SR FLC FRC LFE */
SPA_AUDIO_LAYOUT_7_0, /**< FL FR FC SL SR RL RR */
SPA_AUDIO_LAYOUT_7_0F, /**< FL FR FC SL SR FLC FRC */
SPA_AUDIO_LAYOUT_7_1, /**< FL FR FC SL SR LFE RL RR */
SPA_AUDIO_LAYOUT_7_1W, /**< FL FR FC SL SR LFE FLC FRC */
SPA_AUDIO_LAYOUT_7_1WR, /**< FL FR FC RL RR LFE FLC FRC */
SPA_AUDIO_LAYOUT_OCTAGONAL, /**< FL FR FC SL SR RL RC RR */
};
/** Extra audio flags */
#define SPA_AUDIO_FLAG_NONE (0) /*< no valid flag */
#define SPA_AUDIO_FLAG_UNPOSITIONED (1 << 0) /*< the position array explicitly
* contains unpositioned channels. */
/** Layout of the audio samples for the different channels. */
enum spa_audio_layout {
SPA_AUDIO_LAYOUT_INVALID,
SPA_AUDIO_LAYOUT_INTERLEAVED, /*< interleaved audio */
SPA_AUDIO_LAYOUT_NON_INTERLEAVED, /*< non-interleaved audio */
};
/** Audio information description */
struct spa_audio_info_raw {
enum spa_audio_format format; /*< format, one of enum spa_audio_format */
uint32_t flags; /*< extra flags */
enum spa_audio_layout layout; /*< sample layout */
uint32_t rate; /*< sample rate */
uint32_t channels; /*< number of channels */
uint64_t channel_mask; /*< channel mask */
uint32_t position[SPA_AUDIO_MAX_CHANNELS]; /*< channel position from enum spa_audio_channel */
};
#define SPA_AUDIO_INFO_RAW_INIT(...) (struct spa_audio_info_raw) { __VA_ARGS__ }

View file

@ -62,6 +62,15 @@ static const struct spa_type_info spa_type_audio_format[] = {
{ SPA_AUDIO_FORMAT_F32_BE, SPA_TYPE_AUDIO_FORMAT_BASE "F32BE", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_F64_LE, SPA_TYPE_AUDIO_FORMAT_BASE "F64LE", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_F64_BE, SPA_TYPE_AUDIO_FORMAT_BASE "F64BE", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_U8P, SPA_TYPE_AUDIO_FORMAT_BASE "U8P", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_S16P, SPA_TYPE_AUDIO_FORMAT_BASE "S16P", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_S24_32P, SPA_TYPE_AUDIO_FORMAT_BASE "S24_32P", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_S32P, SPA_TYPE_AUDIO_FORMAT_BASE "S32P", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_S24P, SPA_TYPE_AUDIO_FORMAT_BASE "S24P", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_F32P, SPA_TYPE_AUDIO_FORMAT_BASE "F32P", SPA_TYPE_Int, },
{ SPA_AUDIO_FORMAT_F64P, SPA_TYPE_AUDIO_FORMAT_BASE "F64P", SPA_TYPE_Int, },
{ 0, NULL, },
};
@ -74,13 +83,82 @@ static const struct spa_type_info spa_type_audio_flags[] = {
{ 0, NULL, },
};
#define SPA_TYPE__AudioChannel SPA_TYPE_ENUM_BASE "AudioChannel"
#define SPA_TYPE_AUDIO_CHANNEL_BASE SPA_TYPE__AudioChannel ":"
static const struct spa_type_info spa_type_audio_channel[] = {
{ SPA_AUDIO_CHANNEL_UNKNOWN, SPA_TYPE_AUDIO_CHANNEL_BASE "UNK", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_NA, SPA_TYPE_AUDIO_CHANNEL_BASE "NA", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_MONO, SPA_TYPE_AUDIO_CHANNEL_BASE "MONO", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FL, SPA_TYPE_AUDIO_CHANNEL_BASE "FL", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FR, SPA_TYPE_AUDIO_CHANNEL_BASE "FR", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_RL, SPA_TYPE_AUDIO_CHANNEL_BASE "RL", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_RR, SPA_TYPE_AUDIO_CHANNEL_BASE "RR", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FC, SPA_TYPE_AUDIO_CHANNEL_BASE "FC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_LFE, SPA_TYPE_AUDIO_CHANNEL_BASE "LFE", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_SL, SPA_TYPE_AUDIO_CHANNEL_BASE "SL", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_SR, SPA_TYPE_AUDIO_CHANNEL_BASE "SR", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_RC, SPA_TYPE_AUDIO_CHANNEL_BASE "RC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FLC, SPA_TYPE_AUDIO_CHANNEL_BASE "FLC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FRC, SPA_TYPE_AUDIO_CHANNEL_BASE "FRC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_RLC, SPA_TYPE_AUDIO_CHANNEL_BASE "RLC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_RRC, SPA_TYPE_AUDIO_CHANNEL_BASE "RRC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FLW, SPA_TYPE_AUDIO_CHANNEL_BASE "FLW", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FRW, SPA_TYPE_AUDIO_CHANNEL_BASE "FRW", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FLH, SPA_TYPE_AUDIO_CHANNEL_BASE "FLH", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FCH, SPA_TYPE_AUDIO_CHANNEL_BASE "FCH", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_FRH, SPA_TYPE_AUDIO_CHANNEL_BASE "FRH", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TC, SPA_TYPE_AUDIO_CHANNEL_BASE "TC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TFL, SPA_TYPE_AUDIO_CHANNEL_BASE "TFL", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TFR, SPA_TYPE_AUDIO_CHANNEL_BASE "TFR", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TFC, SPA_TYPE_AUDIO_CHANNEL_BASE "TFC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TRL, SPA_TYPE_AUDIO_CHANNEL_BASE "TRL", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TRR, SPA_TYPE_AUDIO_CHANNEL_BASE "TRR", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TRC, SPA_TYPE_AUDIO_CHANNEL_BASE "TRC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TFLC, SPA_TYPE_AUDIO_CHANNEL_BASE "TFLC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TFRC, SPA_TYPE_AUDIO_CHANNEL_BASE "TFRC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TSL, SPA_TYPE_AUDIO_CHANNEL_BASE "TSL", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_TSR, SPA_TYPE_AUDIO_CHANNEL_BASE "TSR", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_LLFE, SPA_TYPE_AUDIO_CHANNEL_BASE "LLFR", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_RLFE, SPA_TYPE_AUDIO_CHANNEL_BASE "RLFE", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_BC, SPA_TYPE_AUDIO_CHANNEL_BASE "BC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_BLC, SPA_TYPE_AUDIO_CHANNEL_BASE "BLC", SPA_TYPE_Int, },
{ SPA_AUDIO_CHANNEL_BRC, SPA_TYPE_AUDIO_CHANNEL_BASE "BRC", SPA_TYPE_Int, },
{ 0, NULL, },
};
#define SPA_TYPE__AudioLayout SPA_TYPE_ENUM_BASE "AudioLayout"
#define SPA_TYPE_AUDIO_ENUM_BASE SPA_TYPE__AudioLayout ":"
#define SPA_TYPE_AUDIO_LAYOUT_BASE SPA_TYPE__AudioLayout ":"
static const struct spa_type_info spa_type_audio_layout[] = {
{ SPA_AUDIO_LAYOUT_INVALID, SPA_TYPE_AUDIO_ENUM_BASE "Invalid", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_INTERLEAVED, SPA_TYPE_AUDIO_ENUM_BASE "Interleaved", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_NON_INTERLEAVED, SPA_TYPE_AUDIO_ENUM_BASE "Non-Interleaved", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_DEFAULT, SPA_TYPE_AUDIO_LAYOUT_BASE "Default", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_CUSTOM, SPA_TYPE_AUDIO_LAYOUT_BASE "Custom", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_MONO, SPA_TYPE_AUDIO_LAYOUT_BASE "Mono", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_STEREO, SPA_TYPE_AUDIO_LAYOUT_BASE "Stereo", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_2_1, SPA_TYPE_AUDIO_LAYOUT_BASE "2.1", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_2RC, SPA_TYPE_AUDIO_LAYOUT_BASE "2.1 Rear", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_2FC, SPA_TYPE_AUDIO_LAYOUT_BASE "2.1 Front", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_3_1, SPA_TYPE_AUDIO_LAYOUT_BASE "3.1", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_4_0, SPA_TYPE_AUDIO_LAYOUT_BASE "4.0", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_4_1, SPA_TYPE_AUDIO_LAYOUT_BASE "4.1", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_2_2, SPA_TYPE_AUDIO_LAYOUT_BASE "2.2", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_QUAD, SPA_TYPE_AUDIO_LAYOUT_BASE "Quad", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_5_0, SPA_TYPE_AUDIO_LAYOUT_BASE "5.0", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_5_1, SPA_TYPE_AUDIO_LAYOUT_BASE "5.1", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_5_0R, SPA_TYPE_AUDIO_LAYOUT_BASE "5.0 Rear", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_5_1R, SPA_TYPE_AUDIO_LAYOUT_BASE "5.1 Rear", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_6_0, SPA_TYPE_AUDIO_LAYOUT_BASE "6.0", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_6_0F, SPA_TYPE_AUDIO_LAYOUT_BASE "6.0 Front", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_HEXAGONAL, SPA_TYPE_AUDIO_LAYOUT_BASE "Hexagonal", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_6_1, SPA_TYPE_AUDIO_LAYOUT_BASE "6.1", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_6_1R, SPA_TYPE_AUDIO_LAYOUT_BASE "6.1 Rear", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_6_1F, SPA_TYPE_AUDIO_LAYOUT_BASE "6.1 Front", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_7_0, SPA_TYPE_AUDIO_LAYOUT_BASE "7.0", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_7_0F, SPA_TYPE_AUDIO_LAYOUT_BASE "7.0 Front", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_7_1, SPA_TYPE_AUDIO_LAYOUT_BASE "7.1", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_7_1W, SPA_TYPE_AUDIO_LAYOUT_BASE "7.1 Wide", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_7_1WR, SPA_TYPE_AUDIO_LAYOUT_BASE "7.1 Wide Rear", SPA_TYPE_Int, },
{ SPA_AUDIO_LAYOUT_OCTAGONAL, SPA_TYPE_AUDIO_LAYOUT_BASE "Octagonal", SPA_TYPE_Int, },
{ 0, NULL, },
};

View file

@ -88,12 +88,11 @@ enum spa_format {
/* Audio format keys */
SPA_FORMAT_START_Audio,
SPA_FORMAT_AUDIO_format,
SPA_FORMAT_AUDIO_format, /**< audio format, one of enum spa_audio_format */
SPA_FORMAT_AUDIO_flags,
SPA_FORMAT_AUDIO_layout,
SPA_FORMAT_AUDIO_rate,
SPA_FORMAT_AUDIO_channels,
SPA_FORMAT_AUDIO_channelMask,
SPA_FORMAT_AUDIO_channels, /**< number of audio channels */
SPA_FORMAT_AUDIO_position, /**< channel positions one of enum spa_audio_position */
/* Video Format keys */
SPA_FORMAT_START_Video = 0x10000,

View file

@ -209,11 +209,9 @@ static const struct spa_type_info spa_type_format[] = {
spa_type_audio_format },
{ SPA_FORMAT_AUDIO_flags, SPA_TYPE_FORMAT_AUDIO_BASE "flags", SPA_TYPE_Id,
spa_type_audio_flags },
{ SPA_FORMAT_AUDIO_layout, SPA_TYPE_FORMAT_AUDIO_BASE "layout", SPA_TYPE_Id,
spa_type_audio_layout },
{ SPA_FORMAT_AUDIO_rate, SPA_TYPE_FORMAT_AUDIO_BASE "rate", SPA_TYPE_Int, },
{ SPA_FORMAT_AUDIO_channels, SPA_TYPE_FORMAT_AUDIO_BASE "channels", SPA_TYPE_Int, },
{ SPA_FORMAT_AUDIO_channelMask, SPA_TYPE_FORMAT_AUDIO_BASE "channelMask", SPA_TYPE_Int, },
{ SPA_FORMAT_AUDIO_position, SPA_TYPE_FORMAT_AUDIO_BASE "position", SPA_TYPE_Id, spa_type_audio_channel },
{ SPA_FORMAT_VIDEO_format, SPA_TYPE_FORMAT_VIDEO_BASE "format", SPA_TYPE_Id,
spa_type_video_format, },

View file

@ -113,6 +113,7 @@ struct spa_pod_bitmap {
#define SPA_POD_ARRAY_TYPE(arr) (SPA_POD_TYPE(SPA_POD_ARRAY_CHILD(arr)))
#define SPA_POD_ARRAY_SIZE(arr) (SPA_POD_BODY_SIZE(SPA_POD_ARRAY_CHILD(arr)))
#define SPA_POD_ARRAY_N_VALUES(arr) ((SPA_POD_BODY_SIZE(arr) - sizeof(struct spa_pod_array_body)) / SPA_POD_ARRAY_SIZE(arr))
#define SPA_POD_ARRAY_VALUES(arr) SPA_POD_CONTENTS(struct spa_pod_array, arr)
struct spa_pod_array_body {
struct spa_pod child;

View file

@ -58,33 +58,34 @@ int spa_alsa_close(struct state *state)
struct format_info {
uint32_t spa_format;
uint32_t spa_pformat;
snd_pcm_format_t format;
};
static const struct format_info format_info[] = {
{ SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_UNKNOWN},
{ SPA_AUDIO_FORMAT_S8, SND_PCM_FORMAT_S8},
{ SPA_AUDIO_FORMAT_U8, SND_PCM_FORMAT_U8},
{ SPA_AUDIO_FORMAT_S16_LE, SND_PCM_FORMAT_S16_LE},
{ SPA_AUDIO_FORMAT_S16_BE, SND_PCM_FORMAT_S16_BE},
{ SPA_AUDIO_FORMAT_U16_LE, SND_PCM_FORMAT_U16_LE},
{ SPA_AUDIO_FORMAT_U16_BE, SND_PCM_FORMAT_U16_BE},
{ SPA_AUDIO_FORMAT_S24_32_LE, SND_PCM_FORMAT_S24_LE},
{ SPA_AUDIO_FORMAT_S24_32_BE, SND_PCM_FORMAT_S24_BE},
{ SPA_AUDIO_FORMAT_U24_32_LE, SND_PCM_FORMAT_U24_LE},
{ SPA_AUDIO_FORMAT_U24_32_BE, SND_PCM_FORMAT_U24_BE},
{ SPA_AUDIO_FORMAT_S24_LE, SND_PCM_FORMAT_S24_3LE},
{ SPA_AUDIO_FORMAT_S24_BE, SND_PCM_FORMAT_S24_3BE},
{ SPA_AUDIO_FORMAT_U24_LE, SND_PCM_FORMAT_U24_3LE},
{ SPA_AUDIO_FORMAT_U24_BE, SND_PCM_FORMAT_U24_3BE},
{ SPA_AUDIO_FORMAT_S32_LE, SND_PCM_FORMAT_S32_LE},
{ SPA_AUDIO_FORMAT_S32_BE, SND_PCM_FORMAT_S32_BE},
{ SPA_AUDIO_FORMAT_U32_LE, SND_PCM_FORMAT_U32_LE},
{ SPA_AUDIO_FORMAT_U32_BE, SND_PCM_FORMAT_U32_BE},
{ SPA_AUDIO_FORMAT_F32_LE, SND_PCM_FORMAT_FLOAT_LE},
{ SPA_AUDIO_FORMAT_F32_BE, SND_PCM_FORMAT_FLOAT_BE},
{ SPA_AUDIO_FORMAT_F64_LE, SND_PCM_FORMAT_FLOAT64_LE},
{ SPA_AUDIO_FORMAT_F64_BE, SND_PCM_FORMAT_FLOAT64_BE},
{ SPA_AUDIO_FORMAT_UNKNOWN, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_UNKNOWN},
{ SPA_AUDIO_FORMAT_S8, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_S8},
{ SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8P, SND_PCM_FORMAT_U8},
{ SPA_AUDIO_FORMAT_S16_LE, SPA_AUDIO_FORMAT_S16P, SND_PCM_FORMAT_S16_LE},
{ SPA_AUDIO_FORMAT_S16_BE, SPA_AUDIO_FORMAT_S16P, SND_PCM_FORMAT_S16_BE},
{ SPA_AUDIO_FORMAT_U16_LE, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_U16_LE},
{ SPA_AUDIO_FORMAT_U16_BE, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_U16_BE},
{ SPA_AUDIO_FORMAT_S24_32_LE, SPA_AUDIO_FORMAT_S24_32P, SND_PCM_FORMAT_S24_LE},
{ SPA_AUDIO_FORMAT_S24_32_BE, SPA_AUDIO_FORMAT_S24_32P, SND_PCM_FORMAT_S24_BE},
{ SPA_AUDIO_FORMAT_U24_32_LE, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_U24_LE},
{ SPA_AUDIO_FORMAT_U24_32_BE, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_U24_BE},
{ SPA_AUDIO_FORMAT_S24_LE, SPA_AUDIO_FORMAT_S24P, SND_PCM_FORMAT_S24_3LE},
{ SPA_AUDIO_FORMAT_S24_BE, SPA_AUDIO_FORMAT_S24P, SND_PCM_FORMAT_S24_3BE},
{ SPA_AUDIO_FORMAT_U24_LE, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_U24_3LE},
{ SPA_AUDIO_FORMAT_U24_BE, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_U24_3BE},
{ SPA_AUDIO_FORMAT_S32_LE, SPA_AUDIO_FORMAT_S32P, SND_PCM_FORMAT_S32_LE},
{ SPA_AUDIO_FORMAT_S32_BE, SPA_AUDIO_FORMAT_S32P, SND_PCM_FORMAT_S32_BE},
{ SPA_AUDIO_FORMAT_U32_LE, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_U32_LE},
{ SPA_AUDIO_FORMAT_U32_BE, SPA_AUDIO_FORMAT_UNKNOWN, SND_PCM_FORMAT_U32_BE},
{ SPA_AUDIO_FORMAT_F32_LE, SPA_AUDIO_FORMAT_F32P, SND_PCM_FORMAT_FLOAT_LE},
{ SPA_AUDIO_FORMAT_F32_BE, SPA_AUDIO_FORMAT_F32P, SND_PCM_FORMAT_FLOAT_BE},
{ SPA_AUDIO_FORMAT_F64_LE, SPA_AUDIO_FORMAT_F64P, SND_PCM_FORMAT_FLOAT64_LE},
{ SPA_AUDIO_FORMAT_F64_BE, SPA_AUDIO_FORMAT_F64P, SND_PCM_FORMAT_FLOAT64_BE},
};
static snd_pcm_format_t spa_format_to_alsa(uint32_t format)
@ -98,48 +99,54 @@ static snd_pcm_format_t spa_format_to_alsa(uint32_t format)
return SND_PCM_FORMAT_UNKNOWN;
}
static uint64_t map_to_mask(snd_pcm_chmap_t* map)
struct chmap_info {
enum snd_pcm_chmap_position pos;
enum spa_audio_channel channel;
};
static const struct chmap_info chmap_info[] = {
[SND_CHMAP_UNKNOWN] = { SND_CHMAP_UNKNOWN, SPA_AUDIO_CHANNEL_UNKNOWN },
[SND_CHMAP_NA] = { SND_CHMAP_NA, SPA_AUDIO_CHANNEL_NA },
[SND_CHMAP_MONO] = { SND_CHMAP_MONO, SPA_AUDIO_CHANNEL_MONO },
[SND_CHMAP_FL] = { SND_CHMAP_FL, SPA_AUDIO_CHANNEL_FL },
[SND_CHMAP_FR] = { SND_CHMAP_FR, SPA_AUDIO_CHANNEL_FR },
[SND_CHMAP_RL] = { SND_CHMAP_RL, SPA_AUDIO_CHANNEL_RL },
[SND_CHMAP_RR] = { SND_CHMAP_RR, SPA_AUDIO_CHANNEL_RR },
[SND_CHMAP_FC] = { SND_CHMAP_FC, SPA_AUDIO_CHANNEL_FC },
[SND_CHMAP_LFE] = { SND_CHMAP_LFE, SPA_AUDIO_CHANNEL_LFE },
[SND_CHMAP_SL] = { SND_CHMAP_SL, SPA_AUDIO_CHANNEL_SL },
[SND_CHMAP_SR] = { SND_CHMAP_SR, SPA_AUDIO_CHANNEL_SR },
[SND_CHMAP_RC] = { SND_CHMAP_RC, SPA_AUDIO_CHANNEL_RC },
[SND_CHMAP_FLC] = { SND_CHMAP_FLC, SPA_AUDIO_CHANNEL_FLC },
[SND_CHMAP_FRC] = { SND_CHMAP_FRC, SPA_AUDIO_CHANNEL_FRC },
[SND_CHMAP_RLC] = { SND_CHMAP_RLC, SPA_AUDIO_CHANNEL_RLC },
[SND_CHMAP_RRC] = { SND_CHMAP_RRC, SPA_AUDIO_CHANNEL_RRC },
[SND_CHMAP_FLW] = { SND_CHMAP_FLW, SPA_AUDIO_CHANNEL_FLW },
[SND_CHMAP_FRW] = { SND_CHMAP_FRW, SPA_AUDIO_CHANNEL_FRW },
[SND_CHMAP_FLH] = { SND_CHMAP_FLH, SPA_AUDIO_CHANNEL_FLH },
[SND_CHMAP_FCH] = { SND_CHMAP_FCH, SPA_AUDIO_CHANNEL_FCH },
[SND_CHMAP_FRH] = { SND_CHMAP_FRH, SPA_AUDIO_CHANNEL_FRH },
[SND_CHMAP_TC] = { SND_CHMAP_TC, SPA_AUDIO_CHANNEL_TC },
[SND_CHMAP_TFL] = { SND_CHMAP_TFL, SPA_AUDIO_CHANNEL_TFL },
[SND_CHMAP_TFR] = { SND_CHMAP_TFR, SPA_AUDIO_CHANNEL_TFR },
[SND_CHMAP_TFC] = { SND_CHMAP_TFC, SPA_AUDIO_CHANNEL_TFC },
[SND_CHMAP_TRL] = { SND_CHMAP_TRL, SPA_AUDIO_CHANNEL_TRL },
[SND_CHMAP_TRR] = { SND_CHMAP_TRR, SPA_AUDIO_CHANNEL_TRR },
[SND_CHMAP_TRC] = { SND_CHMAP_TRC, SPA_AUDIO_CHANNEL_TRC },
[SND_CHMAP_TFLC] = { SND_CHMAP_TFLC, SPA_AUDIO_CHANNEL_TFLC },
[SND_CHMAP_TFRC] = { SND_CHMAP_TFRC, SPA_AUDIO_CHANNEL_TFRC },
[SND_CHMAP_TSL] = { SND_CHMAP_TSL, SPA_AUDIO_CHANNEL_TSL },
[SND_CHMAP_TSR] = { SND_CHMAP_TSR, SPA_AUDIO_CHANNEL_TSR },
[SND_CHMAP_LLFE] = { SND_CHMAP_LLFE, SPA_AUDIO_CHANNEL_LLFE },
[SND_CHMAP_RLFE] = { SND_CHMAP_RLFE, SPA_AUDIO_CHANNEL_RLFE },
[SND_CHMAP_BC] = { SND_CHMAP_BC, SPA_AUDIO_CHANNEL_BC },
[SND_CHMAP_BLC] = { SND_CHMAP_BLC, SPA_AUDIO_CHANNEL_BLC },
[SND_CHMAP_BRC] = { SND_CHMAP_BRC, SPA_AUDIO_CHANNEL_BRC },
};
static enum spa_audio_channel chmap_position_to_channel(enum snd_pcm_chmap_position pos)
{
uint64_t result = 0;
int i;
for (i = 0; i < map->channels; i++) {
switch (map->pos[i]) {
case SND_CHMAP_UNKNOWN:
case SND_CHMAP_NA: /* N/A, silent */
case SND_CHMAP_MONO: /* mono stream */
break;
case SND_CHMAP_FL: /* front left */
case SND_CHMAP_FR: /* front right */
case SND_CHMAP_RL: /* rear left */
case SND_CHMAP_RR: /* rear right */
case SND_CHMAP_FC: /* front center */
case SND_CHMAP_LFE: /* LFE */
case SND_CHMAP_SL: /* side left */
case SND_CHMAP_SR: /* side right */
case SND_CHMAP_RC: /* rear center */
case SND_CHMAP_FLC: /* front left center */
case SND_CHMAP_FRC: /* front right center */
case SND_CHMAP_RLC: /* rear left center */
case SND_CHMAP_RRC: /* rear right center */
case SND_CHMAP_FLW: /* front left wide */
case SND_CHMAP_FRW: /* front right wide */
case SND_CHMAP_FLH: /* front left high */
case SND_CHMAP_FCH: /* front center high */
case SND_CHMAP_FRH: /* front right high */
case SND_CHMAP_TC: /* top center */
case SND_CHMAP_TFL: /* top front left */
case SND_CHMAP_TFR: /* top front right */
case SND_CHMAP_TFC: /* top front center */
case SND_CHMAP_TRL: /* top rear left */
case SND_CHMAP_TRR: /* top rear right */
case SND_CHMAP_TRC: /* top rear center */
result |= (1LL << (map->pos[i] - 3));
break;
}
}
return result;
return chmap_info[pos].channel;
}
int
@ -187,6 +194,9 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
snd_pcm_format_mask_alloca(&fmask);
snd_pcm_hw_params_get_format_mask(params, fmask);
snd_pcm_access_mask_alloca(&amask);
snd_pcm_hw_params_get_access_mask(params, amask);
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_format, 0);
choice = spa_pod_builder_deref(&b,
@ -196,37 +206,24 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
const struct format_info *fi = &format_info[i];
if (snd_pcm_format_mask_test(fmask, fi->format)) {
if (j++ == 0)
spa_pod_builder_id(&b, fi->spa_format);
spa_pod_builder_id(&b, fi->spa_format);
}
}
if (j > 1)
choice->body.type = SPA_CHOICE_Enum;
spa_pod_builder_pop(&b);
snd_pcm_access_mask_alloca(&amask);
snd_pcm_hw_params_get_access_mask(params, amask);
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_layout, 0);
choice = spa_pod_builder_deref(&b,
spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0));
j = 0;
if (snd_pcm_access_mask_test(amask, SND_PCM_ACCESS_MMAP_INTERLEAVED)) {
if (j++ == 0)
spa_pod_builder_id(&b, SPA_AUDIO_LAYOUT_INTERLEAVED);
spa_pod_builder_id(&b, SPA_AUDIO_LAYOUT_INTERLEAVED);
spa_pod_builder_id(&b, fi->spa_format);
spa_pod_builder_id(&b, fi->spa_format);
}
if (snd_pcm_access_mask_test(amask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) {
if (snd_pcm_access_mask_test(amask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED) &&
fi->spa_pformat != SPA_AUDIO_FORMAT_UNKNOWN) {
if (j++ == 0)
spa_pod_builder_id(&b, SPA_AUDIO_LAYOUT_NON_INTERLEAVED);
spa_pod_builder_id(&b, SPA_AUDIO_LAYOUT_NON_INTERLEAVED);
spa_pod_builder_id(&b, fi->spa_pformat);
spa_pod_builder_id(&b, fi->spa_pformat);
}
}
}
if (j > 1)
choice->body.type = SPA_CHOICE_Enum;
spa_pod_builder_pop(&b);
CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min");
CHECK(snd_pcm_hw_params_get_rate_max(params, &max, &dir), "get_rate_max");
@ -259,12 +256,16 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
spa_pod_builder_pop(&b);
if ((maps = snd_pcm_query_chmaps(hndl)) != NULL) {
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_channelMask, 0);
uint32_t channel;
spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0);
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_position, 0);
spa_pod_builder_push_array(&b);
for (i = 0; maps[i]; i++) {
uint64_t mask = map_to_mask(&maps[i]->map);
spa_pod_builder_long(&b, mask);
snd_pcm_chmap_t* map = &maps[i]->map;
for (j = 0; j < map->channels; j++) {
channel = chmap_position_to_channel(map->pos[j]);
spa_pod_builder_id(&b, channel);
}
}
spa_pod_builder_pop(&b);

View file

@ -0,0 +1,262 @@
/* Spa
* Copyright (C) 2018 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <xmmintrin.h>
static void
channelmix_copy_sse(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, n, n_samples = n_bytes / sizeof(float), unrolled, remain;
float **d = (float **)dst;
float **s = (float **)src;
float *m = matrix;
float v = m[0];
__m128 vol = _mm_set1_ps(v);
if (v <= VOLUME_MIN) {
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (i = 0; i < n_dst; i++)
memcpy(d[i], s[i], n_bytes);
}
else {
unrolled = n_samples / 4;
remain = n_samples & 3;
for (i = 0; i < n_dst; i++) {
float *di = d[i], *si = s[i];
for(n = 0; unrolled--; n += 4)
_mm_storeu_ps(&di[n], _mm_mul_ps(_mm_loadu_ps(&si[n]), vol));
for(; remain--; n++)
_mm_store_ss(&di[n], _mm_mul_ss(_mm_load_ss(&si[n]), vol));
}
}
}
static void
channelmix_f32_2_4_sse(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, n, n_samples = n_bytes / sizeof(float), unrolled, remain;
float **d = (float **)dst;
float **s = (float **)src;
float *m = matrix;
float v = m[0];
__m128 vol = _mm_set1_ps(v);
__m128 in;
if (v <= VOLUME_MIN) {
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
float *d0 = d[0], *d1 = d[1], *d2 = d[2], *d3 = d[3], *s0 = s[0], *s1 = s[1];
unrolled = n_samples / 4;
remain = n_samples & 3;
for(n = 0; unrolled--; n += 4) {
in = _mm_loadu_ps(&s0[n]);
_mm_storeu_ps(&d0[n], in);
_mm_storeu_ps(&d2[n], in);
in = _mm_loadu_ps(&s1[n]);
_mm_storeu_ps(&d1[n], in);
_mm_storeu_ps(&d3[n], in);
}
for(; remain--; n++) {
in = _mm_load_ss(&s0[n]);
_mm_store_ss(&d0[n], in);
_mm_store_ss(&d2[n], in);
in = _mm_load_ss(&s1[n]);
_mm_store_ss(&d1[n], in);
_mm_store_ss(&d3[n], in);
}
}
else {
float *d0 = d[0], *d1 = d[1], *d2 = d[2], *d3 = d[3], *s0 = s[0], *s1 = s[1];
unrolled = n_samples / 4;
remain = n_samples & 3;
for(n = 0; unrolled--; n += 4) {
in = _mm_mul_ps(_mm_loadu_ps(&s0[n]), vol);
_mm_storeu_ps(&d0[n], in);
_mm_storeu_ps(&d2[n], in);
in = _mm_mul_ps(_mm_loadu_ps(&s1[n]), vol);
_mm_storeu_ps(&d1[n], in);
_mm_storeu_ps(&d3[n], in);
}
for(; remain--; n++) {
in = _mm_mul_ss(_mm_load_ss(&s0[n]), vol);
_mm_store_ss(&d0[n], in);
_mm_store_ss(&d2[n], in);
in = _mm_mul_ss(_mm_load_ss(&s1[n]), vol);
_mm_store_ss(&d1[n], in);
_mm_store_ss(&d3[n], in);
}
}
}
/* FL+FR+RL+RR+FC+LFE -> FL+FR */
static void
channelmix_f32_5p1_2_sse(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int n, n_samples = n_bytes / sizeof(float), unrolled, remain;
float **d = (float **) dst;
float **s = (float **) src;
float *m = matrix;
float v = m[0];
__m128 clev = _mm_set1_ps(0.7071f);
__m128 slev = _mm_set1_ps(0.7071f);
__m128 vol = _mm_set1_ps(v);
__m128 in, ctr;
if (v <= VOLUME_MIN) {
memset(d[0], 0, n_bytes);
memset(d[1], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
float *d0 = d[0], *d1 = d[1], *s0 = s[0], *s1 = s[1], *s2 = s[2], *s3 = s[3], *s4 = s[4];
unrolled = n_samples / 4;
remain = n_samples & 3;
for(n = 0; unrolled--; n += 4) {
ctr = _mm_mul_ps(_mm_loadu_ps(&s4[n]), clev);
in = _mm_mul_ps(_mm_loadu_ps(&s2[n]), slev);
in = _mm_add_ps(in, ctr);
in = _mm_add_ps(in, _mm_loadu_ps(&s0[n]));
_mm_storeu_ps(&d0[n], in);
in = _mm_mul_ps(_mm_loadu_ps(&s3[n]), slev);
in = _mm_add_ps(in, ctr);
in = _mm_add_ps(in, _mm_loadu_ps(&s1[n]));
_mm_storeu_ps(&d1[n], in);
}
for(; remain--; n++) {
ctr = _mm_mul_ss(_mm_load_ss(&s4[n]), clev);
in = _mm_mul_ss(_mm_load_ss(&s2[n]), slev);
in = _mm_add_ss(in, ctr);
in = _mm_add_ss(in, _mm_load_ss(&s0[n]));
_mm_store_ss(&d0[n], in);
in = _mm_mul_ss(_mm_load_ss(&s3[n]), slev);
in = _mm_add_ss(in, ctr);
in = _mm_add_ss(in, _mm_load_ss(&s1[n]));
_mm_store_ss(&d1[n], in);
}
}
else {
float *d0 = d[0], *d1 = d[1], *s0 = s[0], *s1 = s[1], *s2 = s[2], *s3 = s[3], *s4 = s[4];
unrolled = n_samples / 4;
remain = n_samples & 3;
for(n = 0; unrolled--; n += 4) {
ctr = _mm_mul_ps(_mm_loadu_ps(&s4[n]), clev);
in = _mm_mul_ps(_mm_loadu_ps(&s2[n]), slev);
in = _mm_add_ps(in, ctr);
in = _mm_add_ps(in, _mm_loadu_ps(&s0[n]));
in = _mm_mul_ps(in, vol);
_mm_storeu_ps(&d0[n], in);
in = _mm_mul_ps(_mm_loadu_ps(&s3[n]), slev);
in = _mm_add_ps(in, ctr);
in = _mm_add_ps(in, _mm_loadu_ps(&s1[n]));
in = _mm_mul_ps(in, vol);
_mm_storeu_ps(&d1[n], in);
}
for(; remain--; n++) {
ctr = _mm_mul_ss(_mm_load_ss(&s4[n]), clev);
in = _mm_mul_ss(_mm_load_ss(&s2[n]), slev);
in = _mm_add_ss(in, ctr);
in = _mm_add_ss(in, _mm_load_ss(&s0[n]));
in = _mm_mul_ss(in, vol);
_mm_store_ss(&d0[n], in);
in = _mm_mul_ss(_mm_load_ss(&s3[n]), slev);
in = _mm_add_ss(in, ctr);
in = _mm_add_ss(in, _mm_load_ss(&s1[n]));
in = _mm_mul_ss(in, vol);
_mm_store_ss(&d1[n], in);
}
}
}
/* FL+FR+RL+RR+FC+LFE -> FL+FR+RL+RR*/
static void
channelmix_f32_5p1_4_sse(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, n, n_samples = n_bytes / sizeof(float), unrolled, remain;
float **d = (float **) dst;
float **s = (float **) src;
float *m = matrix;
float v = m[0];
__m128 clev = _mm_set1_ps(0.7071f);
__m128 vol = _mm_set1_ps(v);
__m128 ctr;
if (v <= VOLUME_MIN) {
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
float *s0 = s[0], *s1 = s[1], *s2 = s[2], *s3 = s[3], *s4 = d[4];
float *d0 = d[0], *d1 = d[1], *d2 = d[2], *d3 = d[3];
unrolled = n_samples / 4;
remain = n_samples & 3;
for(n = 0; unrolled--; n += 4) {
ctr = _mm_mul_ps(_mm_loadu_ps(&s4[n]), clev);
_mm_storeu_ps(&d0[n], _mm_add_ps(_mm_loadu_ps(&s0[n]), ctr));
_mm_storeu_ps(&d1[n], _mm_add_ps(_mm_loadu_ps(&s1[n]), ctr));
_mm_storeu_ps(&d2[n], _mm_loadu_ps(&s2[n]));
_mm_storeu_ps(&d3[n], _mm_loadu_ps(&s3[n]));
}
for(; remain--; n++) {
ctr = _mm_mul_ss(_mm_load_ss(&s4[n]), clev);
_mm_store_ss(&d0[n], _mm_add_ss(_mm_load_ss(&s0[n]), ctr));
_mm_store_ss(&d1[n], _mm_add_ss(_mm_load_ss(&s1[n]), ctr));
_mm_store_ss(&d2[n], _mm_load_ss(&s2[n]));
_mm_store_ss(&d3[n], _mm_load_ss(&s3[n]));
}
}
else {
float *s0 = s[0], *s1 = s[1], *s2 = s[2], *s3 = s[3], *s4 = d[4];
float *d0 = d[0], *d1 = d[1], *d2 = d[2], *d3 = d[3];
unrolled = n_samples / 4;
remain = n_samples & 3;
for(n = 0; unrolled--; n += 4) {
ctr = _mm_mul_ps(_mm_loadu_ps(&s4[n]), clev);
_mm_storeu_ps(&d0[n], _mm_mul_ps(_mm_add_ps(_mm_loadu_ps(&s0[n]), ctr), vol));
_mm_storeu_ps(&d1[n], _mm_mul_ps(_mm_add_ps(_mm_loadu_ps(&s1[n]), ctr), vol));
_mm_storeu_ps(&d2[n], _mm_mul_ps(_mm_loadu_ps(&s2[n]), vol));
_mm_storeu_ps(&d3[n], _mm_mul_ps(_mm_loadu_ps(&s3[n]), vol));
}
for(; remain--; n++) {
ctr = _mm_mul_ss(_mm_load_ss(&s4[n]), clev);
_mm_store_ss(&d0[n], _mm_mul_ss(_mm_add_ss(_mm_load_ss(&s0[n]), ctr), vol));
_mm_store_ss(&d1[n], _mm_mul_ss(_mm_add_ss(_mm_load_ss(&s1[n]), ctr), vol));
_mm_store_ss(&d2[n], _mm_mul_ss(_mm_load_ss(&s2[n]), vol));
_mm_store_ss(&d3[n], _mm_mul_ss(_mm_load_ss(&s3[n]), vol));
}
}
}

View file

@ -25,30 +25,32 @@
#define VOLUME_MIN 0.0f
#define VOLUME_NORM 1.0f
#if defined (__SSE__)
#include "channelmix-ops-sse.c"
#endif
static void
channelmix_copy(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, j;
int i, n, n_samples = n_bytes / sizeof(float);
float **d = (float **)dst;
float **s = (float **)src;
float *m = matrix;
float v = m[0];
if (v <= VOLUME_MIN) {
for (i = 0; i < n_src; i++)
memset(dst[i], 0, n_bytes);
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (i = 0; i < n_src; i++)
memcpy(dst[i], src[i], n_bytes);
for (i = 0; i < n_dst; i++)
memcpy(d[i], s[i], n_bytes);
}
else {
float **d = (float **) dst;
float **s = (float **) src;
int n_samples = n_bytes / sizeof(float);
for (i = 0; i < n_src; i++)
for (j = 0; j < n_samples; j++)
d[i][j] = s[i][j] * v;
for (i = 0; i < n_dst; i++)
for (n = 0; n < n_samples; n++)
d[i][n] = s[i][n] * v;
}
}
@ -56,12 +58,11 @@ static void
channelmix_f32_n_m(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, j, n, n_samples;
int i, j, n, n_samples = n_bytes / sizeof(float);
float **d = (float **) dst;
float **s = (float **) src;
float *m = matrix;
n_samples = n_bytes / sizeof(float);
for (n = 0; n < n_samples; n++) {
for (i = 0; i < n_dst; i++) {
float sum = 0.0f;
@ -78,23 +79,23 @@ static void
channelmix_f32_1_2(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int n, n_samples;
float **d = (float **) dst;
const float *s = src[0];
int n, n_samples = n_bytes / sizeof(float);
float **d = (float **)dst;
float **s = (float **)src;
float *m = matrix;
float v = m[0];
n_samples = n_bytes / sizeof(float);
if (v <= VOLUME_MIN) {
memset(d[0], 0, n_bytes);
memset(d[1], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (n = 0; n < n_samples; n++)
d[0][n] = d[1][n] = s[n];
d[0][n] = d[1][n] = s[0][n];
}
else {
for (n = 0; n < n_samples; n++)
d[0][n] = d[1][n] = s[n] * v;
d[0][n] = d[1][n] = s[0][n] * v;
}
}
@ -102,24 +103,209 @@ static void
channelmix_f32_2_1(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int n, n_samples;
float *d = dst[0];
int n, n_samples = n_bytes / sizeof(float);
float **d = (float **)dst;
float **s = (float **)src;
float *m = matrix;
float v = m[0];
if (v <= VOLUME_MIN) {
memset(d[0], 0, n_bytes);
}
else {
const float f = v * 0.5f;
for (n = 0; n < n_samples; n++)
d[0][n] = (s[0][n] + s[1][n]) * f;
}
}
static void
channelmix_f32_2_4(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, n, n_samples = n_bytes / sizeof(float);
float **d = (float **)dst;
float **s = (float **)src;
float *m = matrix;
float v = m[0];
if (v <= VOLUME_MIN) {
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (n = 0; n < n_samples; n++) {
d[0][n] = d[2][n] = s[0][n];
d[1][n] = d[3][n] = s[1][n];
}
}
else {
for (n = 0; n < n_samples; n++) {
d[0][n] = d[2][n] = s[0][n] * v;
d[1][n] = d[3][n] = s[1][n] * v;
}
}
}
static void
channelmix_f32_2_3p1(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, n, n_samples = n_bytes / sizeof(float);
float **d = (float **)dst;
float **s = (float **)src;
float *m = matrix;
float v = m[0];
if (v <= VOLUME_MIN) {
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (n = 0; n < n_samples; n++) {
d[0][n] = s[0][n];
d[1][n] = s[1][n];
d[2][n] = (s[0][n] + s[1][n]) * 0.5f;
d[3][n] = 0.0f;
}
}
else {
const float f = 0.5f * v;
for (n = 0; n < n_samples; n++) {
d[0][n] = s[0][n] * v;
d[1][n] = s[1][n] * v;
d[2][n] = (s[0][n] + s[1][n]) * f;
d[3][n] = 0.0f;
}
}
}
static void
channelmix_f32_2_5p1(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, n, n_samples = n_bytes / sizeof(float);
float **d = (float **)dst;
float **s = (float **)src;
float *m = matrix;
float v = m[0];
if (v <= VOLUME_MIN) {
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (n = 0; n < n_samples; n++) {
d[0][n] = d[2][n] = s[0][n];
d[1][n] = d[3][n] = s[1][n];
d[4][n] = (s[0][n] + s[1][n]) * 0.5f;
d[5][n] = 0.0f;
}
}
else {
const float f = 0.5f * v;
for (n = 0; n < n_samples; n++) {
d[0][n] = d[2][n] = s[0][n] * v;
d[1][n] = d[3][n] = s[1][n] * v;
d[4][n] = (s[0][n] + s[1][n]) * f;
d[5][n] = 0.0f;
}
}
}
/* FL+FR+RL+RR+FC+LFE -> FL+FR */
static void
channelmix_f32_5p1_2(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int n, n_samples = n_bytes / sizeof(float);
float **d = (float **) dst;
float **s = (float **) src;
float *m = matrix;
float v = m[0];
const float clev = 0.7071f;
const float slev = 0.7071f;
if (v <= VOLUME_MIN) {
memset(d[0], 0, n_bytes);
memset(d[1], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (n = 0; n < n_samples; n++) {
const float ctr = clev * s[4][n];
d[0][n] = s[0][n] + ctr + (slev * s[2][n]);
d[1][n] = s[1][n] + ctr + (slev * s[3][n]);
}
}
else {
for (n = 0; n < n_samples; n++) {
const float ctr = clev * s[4][n];
d[0][n] = (s[0][n] + ctr + (slev * s[2][n])) * v;
d[1][n] = (s[1][n] + ctr + (slev * s[3][n])) * v;
}
}
}
/* FL+FR+RL+RR+FC+LFE -> FL+FR+FC+LFE*/
static void
channelmix_f32_5p1_3p1(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, n, n_samples;
float **d = (float **) dst;
float **s = (float **) src;
float *m = matrix;
float v = m[0];
n_samples = n_bytes / sizeof(float);
if (v <= VOLUME_MIN) {
memset(d, 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (n = 0; n < n_samples; n++)
d[n] = (s[0][n] + s[1][n]) * 0.5f;
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else {
v *= 0.5f;
for (n = 0; n < n_samples; n++)
d[n] = (s[0][n] + s[1][n]) * v;
const float f1 = 0.5f * v;
for (n = 0; n < n_samples; n++) {
d[0][n] = (s[0][n] + s[2][n]) * f1;
d[1][n] = (s[1][n] + s[3][n]) * f1;
d[2][n] = s[4][n] * v;
d[3][n] = s[5][n] * v;
}
}
}
/* FL+FR+RL+RR+FC+LFE -> FL+FR+RL+RR*/
static void
channelmix_f32_5p1_4(void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], void *matrix, int n_bytes)
{
int i, n, n_samples;
float **d = (float **) dst;
float **s = (float **) src;
float *m = matrix;
float v = m[0];
n_samples = n_bytes / sizeof(float);
if (v <= VOLUME_MIN) {
for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_bytes);
}
else if (v == VOLUME_NORM) {
for (n = 0; n < n_samples; n++) {
float ctr = s[4][n] * 0.7071f;
d[0][n] = s[0][n] + ctr;
d[1][n] = s[1][n] + ctr;
d[2][n] = s[2][n];
d[3][n] = s[3][n];
}
}
else {
for (n = 0; n < n_samples; n++) {
float ctr = s[4][n] * 0.7071f;
d[0][n] = (s[0][n] + ctr) * v;
d[1][n] = (s[1][n] + ctr) * v;
d[2][n] = s[2][n] * v;
d[3][n] = s[3][n] * v;
}
}
}
@ -130,30 +316,53 @@ typedef void (*channelmix_func_t) (void *data, int n_dst, void *dst[n_dst],
static const struct channelmix_info {
uint32_t src_chan;
uint64_t src_mask;
uint32_t dst_chan;
uint64_t dst_mask;
channelmix_func_t func;
uint32_t flags;
#define FEATURE_SSE (1<<0)
uint32_t features;
} channelmix_table[] =
{
{ -2, -2, channelmix_copy, 0 },
{ 1, 2, channelmix_f32_1_2, 0 },
{ 2, 1, channelmix_f32_2_1, 0 },
{ -1, -1, channelmix_f32_n_m, 0 },
#if defined (__SSE2__)
{ -2, 0, -2, 0, channelmix_copy_sse, 0 },
#endif
{ -2, 0, -2, 0, channelmix_copy, 0 },
{ 1, 0, 2, 0, channelmix_f32_1_2, 0 },
{ 2, 0, 1, 0, channelmix_f32_2_1, 0 },
#if defined (__SSE2__)
{ 2, 0, 4, 0, channelmix_f32_2_4_sse, FEATURE_SSE },
#endif
{ 2, 0, 4, 0, channelmix_f32_2_4, 0 },
{ 2, 0, 4, 0, channelmix_f32_2_3p1, 0 },
{ 2, 0, 6, 0, channelmix_f32_2_5p1, 0 },
#if defined (__SSE2__)
{ 6, 0, 2, 0, channelmix_f32_5p1_2_sse, FEATURE_SSE },
#endif
{ 6, 0, 2, 0, channelmix_f32_5p1_2, 0 },
#if defined (__SSE2__)
{ 6, 0, 4, 0, channelmix_f32_5p1_4_sse, FEATURE_SSE },
#endif
{ 6, 0, 4, 0, channelmix_f32_5p1_4, 0 },
{ 6, 0, 4, 0, channelmix_f32_5p1_3p1, 0 },
{ -1, 0, -1, 0, channelmix_f32_n_m, 0 },
};
#define MATCH_CHAN(a,b) ((a) == -1 || (a) == (b))
static const struct channelmix_info *find_channelmix_info(uint32_t src_chan, uint32_t dst_chan)
static const struct channelmix_info *find_channelmix_info(uint32_t src_chan, uint64_t src_mask,
uint32_t dst_chan, uint64_t dst_mask, uint32_t features)
{
int i;
if (src_chan == dst_chan)
if (src_chan == dst_chan && src_mask == dst_mask)
return &channelmix_table[0];
for (i = 1; i < SPA_N_ELEMENTS(channelmix_table); i++) {
if (MATCH_CHAN(channelmix_table[i].src_chan, src_chan) &&
MATCH_CHAN(channelmix_table[i].dst_chan, dst_chan))
MATCH_CHAN(channelmix_table[i].dst_chan, dst_chan) &&
(channelmix_table[i].features == 0 || (channelmix_table[i].features & features) != 0))
return &channelmix_table[i];
}
return NULL;

View file

@ -143,23 +143,23 @@ static int setup_convert(struct impl *this,
src_chan = src_info->info.raw.channels;
dst_chan = dst_info->info.raw.channels;
spa_log_info(this->log, NAME " %p: %d/%d@%d.%d->%d/%d@%d.%d", this,
spa_log_info(this->log, NAME " %p: %d/%d@%d->%d/%d@%d", this,
src_info->info.raw.format,
src_chan,
src_info->info.raw.rate,
src_info->info.raw.layout,
dst_info->info.raw.format,
dst_chan,
dst_info->info.raw.rate,
dst_info->info.raw.layout);
dst_info->info.raw.rate);
if (src_info->info.raw.rate != dst_info->info.raw.rate)
return -EINVAL;
/* find convert function */
if ((chanmix_info = find_channelmix_info(src_chan, dst_chan)) == NULL)
if ((chanmix_info = find_channelmix_info(src_chan, 0, dst_chan, 0, FEATURE_SSE)) == NULL)
return -ENOTSUP;
spa_log_info(this->log, NAME " %p: got channelmix features %08x", this, chanmix_info->features);
this->convert = chanmix_info->func;
/* set up the matrix if needed */
@ -311,8 +311,7 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32P),
SPA_FORMAT_AUDIO_rate, &SPA_POD_Int(other->format.info.raw.rate),
SPA_FORMAT_AUDIO_channels, &SPA_POD_CHOICE_RANGE_Int(DEFAULT_CHANNELS, 1, INT32_MAX),
0);
@ -321,8 +320,7 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32P),
SPA_FORMAT_AUDIO_rate, &SPA_POD_CHOICE_RANGE_Int(DEFAULT_RATE, 1, INT32_MAX),
SPA_FORMAT_AUDIO_channels, &SPA_POD_CHOICE_RANGE_Int(DEFAULT_CHANNELS, 1, INT32_MAX),
0);
@ -516,9 +514,7 @@ static int port_set_format(struct spa_node *node,
if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
return -EINVAL;
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32)
return -EINVAL;
if (info.info.raw.layout != SPA_AUDIO_LAYOUT_NON_INTERLEAVED)
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32P)
return -EINVAL;
port->stride = sizeof(float);

View file

@ -675,64 +675,92 @@ static const struct conv_info {
#define FEATURE_SSE (1<<0)
uint32_t features;
convert_func_t i2i;
convert_func_t i2d;
convert_func_t d2i;
convert_func_t func;
} conv_table[] =
{
/* to f32 */
{ SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_F32, 0,
conv_u8_to_f32, conv_u8_to_f32d, conv_u8d_to_f32 },
{ SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_F32, 0, conv_u8_to_f32 },
{ SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_F32P, 0, conv_u8_to_f32d },
{ SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_F32, 0, conv_u8d_to_f32 },
{ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32, 0, conv_s16_to_f32 },
#if defined (__SSE2__)
{ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32, FEATURE_SSE,
conv_s16_to_f32, conv_s16_to_f32d_sse, conv_s16d_to_f32 },
{ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32P, FEATURE_SSE, conv_s16_to_f32d_sse },
#endif
{ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32, 0,
conv_s16_to_f32, conv_s16_to_f32d, conv_s16d_to_f32 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32, 0,
conv_copy, deinterleave_32, interleave_32 },
{ SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32, 0,
conv_s32_to_f32, conv_s32_to_f32d, conv_s32d_to_f32 },
{ SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32, 0,
conv_s24_to_f32, conv_s24_to_f32d, conv_s24d_to_f32 },
{ SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_F32, 0,
conv_s24_32_to_f32, conv_s24_32_to_f32d, conv_s24_32d_to_f32 },
{ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32P, 0, conv_s16_to_f32d },
{ SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_F32, 0, conv_s16d_to_f32 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32, 0, conv_copy },
{ SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32P, 0, conv_copy },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32P, 0, deinterleave_32 },
{ SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32, 0, interleave_32 },
{ SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32, 0, conv_s32_to_f32 },
{ SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32P, 0, conv_s32_to_f32d },
{ SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_F32, 0, conv_s32d_to_f32 },
{ SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32, 0, conv_s24_to_f32 },
{ SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, 0, conv_s24_to_f32d },
{ SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_F32, 0, conv_s24d_to_f32 },
{ SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_F32, 0, conv_s24_32_to_f32 },
{ SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_F32P, 0, conv_s24_32_to_f32d },
{ SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_F32, 0, conv_s24_32d_to_f32 },
/* from f32 */
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8, 0,
conv_f32_to_u8, conv_f32_to_u8d, conv_f32d_to_u8 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S16, 0,
conv_f32_to_s16, conv_f32_to_s16d, conv_f32d_to_s16 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8, 0, conv_f32_to_u8 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8P, 0, conv_f32_to_u8d },
{ SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U8, 0, conv_f32d_to_u8 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S16, 0, conv_f32_to_s16 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S16P, 0, conv_f32_to_s16d },
{ SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S16, 0, conv_f32d_to_s16 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S32, 0, conv_f32_to_s32 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S32P, 0, conv_f32_to_s32d },
#if defined (__SSE2__)
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S32, FEATURE_SSE,
conv_f32_to_s32, conv_f32_to_s32d, conv_f32d_to_s32_sse },
{ SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32, FEATURE_SSE, conv_f32d_to_s32_sse },
#endif
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S32, 0,
conv_f32_to_s32, conv_f32_to_s32d, conv_f32d_to_s32 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24, 0,
conv_f32_to_s24, conv_f32_to_s24d, conv_f32d_to_s24 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24_32, 0,
conv_f32_to_s24_32, conv_f32_to_s24_32d, conv_f32d_to_s24_32 },
{ SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32, 0, conv_f32d_to_s32 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24, 0, conv_f32_to_s24 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24P, 0, conv_f32_to_s24d },
{ SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24, 0, conv_f32d_to_s24 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24_32, 0, conv_f32_to_s24_32 },
{ SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24_32P, 0, conv_f32_to_s24_32d },
{ SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24_32, 0, conv_f32d_to_s24_32 },
/* u8 */
{ SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8, 0,
conv_copy, deinterleave_8, interleave_8 },
{ SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8, 0, conv_copy },
{ SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_U8P, 0, conv_copy },
{ SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8P, 0, deinterleave_8 },
{ SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_U8, 0, interleave_8 },
/* s16 */
{ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16, 0,
conv_copy, deinterleave_16, interleave_16 },
{ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16, 0, conv_copy },
{ SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_S16P, 0, conv_copy },
{ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16P, 0, deinterleave_16 },
{ SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_S16, 0, interleave_16 },
/* s32 */
{ SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32, 0,
conv_copy, deinterleave_32, interleave_32 },
{ SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32, 0, conv_copy },
{ SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32P, 0, conv_copy },
{ SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32P, 0, deinterleave_32 },
{ SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32, 0, interleave_32 },
/* s24 */
{ SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_S24, 0,
conv_copy, deinterleave_24, interleave_24 },
{ SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_S24, 0, conv_copy },
{ SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_S24P, 0, conv_copy },
{ SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_S24P, 0, deinterleave_24 },
{ SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_S24, 0, interleave_24 },
/* s24_32 */
{ SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32, 0,
conv_copy, deinterleave_32, interleave_32 },
{ SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32, 0, conv_copy },
{ SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32P, 0, conv_copy },
{ SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32P, 0, deinterleave_32 },
{ SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32, 0, interleave_32 },
};
static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt, uint32_t features)

View file

@ -160,15 +160,13 @@ static int setup_convert(struct impl *this)
src_fmt = informat.format.info.raw.format;
dst_fmt = outformat.format.info.raw.format;
spa_log_info(this->log, NAME " %p: %s/%d@%d.%d->%s/%d@%d.%d", this,
spa_log_info(this->log, NAME " %p: %s/%d@%d->%s/%d@%d", this,
spa_debug_type_find_name(spa_type_audio_format, src_fmt),
informat.format.info.raw.channels,
informat.format.info.raw.rate,
informat.format.info.raw.layout,
spa_debug_type_find_name(spa_type_audio_format, dst_fmt),
outformat.format.info.raw.channels,
outformat.format.info.raw.rate,
outformat.format.info.raw.layout);
outformat.format.info.raw.rate);
if (informat.format.info.raw.channels != outformat.format.info.raw.channels)
return -EINVAL;
@ -181,18 +179,8 @@ static int setup_convert(struct impl *this)
if (conv != NULL) {
spa_log_info(this->log, NAME " %p: got converter features %08x", this,
conv->features);
if (informat.format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED) {
if (outformat.format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED)
this->convert = conv->i2i;
else
this->convert = conv->i2d;
}
else {
if (outformat.format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED)
this->convert = conv->d2i;
else
this->convert = conv->i2i;
}
this->convert = conv->func;
return 0;
}
return -ENOTSUP;
@ -428,11 +416,7 @@ static int port_enum_formats(struct spa_node *node,
other->info.raw.format,
other->info.raw.format,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_F32_OE),
SPA_FORMAT_AUDIO_layout, &SPA_POD_CHOICE_ENUM_Id(3,
other->info.raw.layout,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_AUDIO_FORMAT_F32P),
SPA_FORMAT_AUDIO_rate, &SPA_POD_Int(other->info.raw.rate),
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(other->info.raw.channels),
0);
@ -441,23 +425,25 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_CHOICE_ENUM_Id(12,
SPA_FORMAT_AUDIO_format, &SPA_POD_CHOICE_ENUM_Id(18,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_U8P,
SPA_AUDIO_FORMAT_U8,
SPA_AUDIO_FORMAT_S16P,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S16_OE,
SPA_AUDIO_FORMAT_F32P,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_F32_OE,
SPA_AUDIO_FORMAT_S32P,
SPA_AUDIO_FORMAT_S32,
SPA_AUDIO_FORMAT_S32_OE,
SPA_AUDIO_FORMAT_S24P,
SPA_AUDIO_FORMAT_S24,
SPA_AUDIO_FORMAT_S24_OE,
SPA_AUDIO_FORMAT_S24_32P,
SPA_AUDIO_FORMAT_S24_32,
SPA_AUDIO_FORMAT_S24_32_OE),
SPA_FORMAT_AUDIO_layout, &SPA_POD_CHOICE_ENUM_Id(3,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_rate, &SPA_POD_CHOICE_RANGE_Int(
DEFAULT_RATE, 1, INT32_MAX),
SPA_FORMAT_AUDIO_channels, &SPA_POD_CHOICE_RANGE_Int(
@ -632,7 +618,6 @@ static int clear_buffers(struct impl *this, struct port *port)
static int compatible_format(struct spa_audio_info *info, struct spa_audio_info *info2)
{
if (info->info.raw.format != info2->info.raw.format ||
info->info.raw.layout != info2->info.raw.layout ||
info->info.raw.rate != info2->info.raw.rate)
return -EINVAL;
return 0;
@ -686,12 +671,12 @@ static int port_set_format(struct spa_node *node,
port->stride = calc_width(&info);
if (info.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED) {
port->stride *= info.info.raw.channels;
port->blocks = 1;
if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) {
port->blocks = info.info.raw.channels;
}
else {
port->blocks = info.info.raw.channels;
port->stride *= info.info.raw.channels;
port->blocks = 1;
}
if (this->n_formats[SPA_DIRECTION_INPUT] == this->n_ports[SPA_DIRECTION_INPUT] &&

View file

@ -319,23 +319,20 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_CHOICE_ENUM_Id(12,
SPA_FORMAT_AUDIO_format, &SPA_POD_CHOICE_ENUM_Id(13,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_F32_OE,
SPA_AUDIO_FORMAT_F32P,
SPA_AUDIO_FORMAT_S32,
SPA_AUDIO_FORMAT_S32_OE,
SPA_AUDIO_FORMAT_S32P,
SPA_AUDIO_FORMAT_S24_32,
SPA_AUDIO_FORMAT_S24_32_OE,
SPA_AUDIO_FORMAT_S24_32P,
SPA_AUDIO_FORMAT_S24,
SPA_AUDIO_FORMAT_S24_OE,
SPA_AUDIO_FORMAT_S24P,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S16_OE,
SPA_AUDIO_FORMAT_U8),
SPA_FORMAT_AUDIO_layout, &SPA_POD_CHOICE_ENUM_Id(3,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_AUDIO_FORMAT_S16P,
SPA_AUDIO_FORMAT_U8,
SPA_AUDIO_FORMAT_U8P),
SPA_FORMAT_AUDIO_rate, rate,
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(this->port_count),
0);
@ -345,8 +342,7 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32P),
SPA_FORMAT_AUDIO_rate, rate,
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(1),
0);
@ -512,33 +508,21 @@ static int setup_convert(struct impl *this)
src_fmt = inport->format.info.raw.format;
dst_fmt = outport->format.info.raw.format;
spa_log_info(this->log, NAME " %p: %s/%d@%d.%dx%d->%s/%d@%d.%d", this,
spa_log_info(this->log, NAME " %p: %s/%d@%dx%d->%s/%d@%d", this,
spa_debug_type_find_name(spa_type_audio_format, src_fmt),
inport->format.info.raw.channels,
inport->format.info.raw.rate,
inport->format.info.raw.layout,
this->port_count,
spa_debug_type_find_name(spa_type_audio_format, dst_fmt),
outport->format.info.raw.channels,
outport->format.info.raw.rate,
outport->format.info.raw.layout);
outport->format.info.raw.rate);
conv = find_conv_info(src_fmt, dst_fmt, FEATURE_SSE);
if (conv != NULL) {
spa_log_info(this->log, NAME " %p: got converter features %08x", this,
conv->features);
if (inport->format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED) {
if (outport->format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED)
this->convert = conv->i2i;
else
this->convert = conv->i2d;
}
else {
if (outport->format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED)
this->convert = conv->d2i;
else
this->convert = conv->i2i;
}
this->convert = conv->func;
return 0;
}
return -ENOTSUP;
@ -602,9 +586,7 @@ static int port_set_format(struct spa_node *node,
if (info.info.raw.channels != this->port_count)
return -EINVAL;
} else {
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32)
return -EINVAL;
if (info.info.raw.layout != SPA_AUDIO_LAYOUT_NON_INTERLEAVED)
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32P)
return -EINVAL;
if (info.info.raw.channels != 1)
return -EINVAL;
@ -612,12 +594,12 @@ static int port_set_format(struct spa_node *node,
port->format = info;
port->stride = calc_width(&info);
if (info.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED) {
port->stride *= info.info.raw.channels;
port->blocks = 1;
if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) {
port->blocks = info.info.raw.channels;
}
else {
port->blocks = info.info.raw.channels;
port->stride *= info.info.raw.channels;
port->blocks = 1;
}
spa_log_debug(this->log, NAME " %p: %d %d %d", this, port_id, port->stride, port->blocks);
@ -958,7 +940,6 @@ impl_init(const struct spa_handle_factory *factory,
const char *str;
int rate;
spa_return_val_if_fail(factory != NULL, -EINVAL);
spa_return_val_if_fail(handle != NULL, -EINVAL);

View file

@ -115,15 +115,13 @@ static int setup_convert(struct impl *this,
dst_info = info;
}
spa_log_info(this->log, NAME " %p: %d/%d@%d.%d->%d/%d@%d.%d", this,
spa_log_info(this->log, NAME " %p: %d/%d@%d->%d/%d@%d", this,
src_info->info.raw.format,
src_info->info.raw.channels,
src_info->info.raw.rate,
src_info->info.raw.layout,
dst_info->info.raw.format,
dst_info->info.raw.channels,
dst_info->info.raw.rate,
dst_info->info.raw.layout);
dst_info->info.raw.rate);
if (src_info->info.raw.channels != dst_info->info.raw.channels)
return -EINVAL;
@ -285,8 +283,7 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32P),
SPA_FORMAT_AUDIO_rate, &SPA_POD_CHOICE_RANGE_Int(
other->format.info.raw.rate, 1, INT32_MAX),
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(other->format.info.raw.channels),
@ -296,8 +293,7 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32P),
SPA_FORMAT_AUDIO_rate, &SPA_POD_CHOICE_RANGE_Int(DEFAULT_RATE, 1, INT32_MAX),
SPA_FORMAT_AUDIO_channels, &SPA_POD_CHOICE_RANGE_Int(DEFAULT_CHANNELS, 1, INT32_MAX),
0);
@ -488,9 +484,7 @@ static int port_set_format(struct spa_node *node,
if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
return -EINVAL;
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32)
return -EINVAL;
if (info.info.raw.layout != SPA_AUDIO_LAYOUT_NON_INTERLEAVED)
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32P)
return -EINVAL;
port->stride = sizeof(float);

View file

@ -317,23 +317,25 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_CHOICE_ENUM_Id(12,
SPA_FORMAT_AUDIO_format, &SPA_POD_CHOICE_ENUM_Id(18,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_F32P,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_F32_OE,
SPA_AUDIO_FORMAT_S32P,
SPA_AUDIO_FORMAT_S32,
SPA_AUDIO_FORMAT_S32_OE,
SPA_AUDIO_FORMAT_S24_32P,
SPA_AUDIO_FORMAT_S24_32,
SPA_AUDIO_FORMAT_S24_32_OE,
SPA_AUDIO_FORMAT_S24P,
SPA_AUDIO_FORMAT_S24,
SPA_AUDIO_FORMAT_S24_OE,
SPA_AUDIO_FORMAT_S16P,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S16_OE,
SPA_AUDIO_FORMAT_U8P,
SPA_AUDIO_FORMAT_U8),
SPA_FORMAT_AUDIO_layout, &SPA_POD_CHOICE_ENUM_Id(3,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_rate, prate,
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(this->port_count),
0);
@ -343,8 +345,7 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32P),
SPA_FORMAT_AUDIO_rate, prate,
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(1),
0);
@ -513,33 +514,21 @@ static int setup_convert(struct impl *this)
src_fmt = inport->format.info.raw.format;
dst_fmt = outport->format.info.raw.format;
spa_log_info(this->log, NAME " %p: %s/%d@%d.%dx%d->%s/%d@%d.%d", this,
spa_log_info(this->log, NAME " %p: %s/%d@%dx%d->%s/%d@%d", this,
spa_debug_type_find_name(spa_type_audio_format, src_fmt),
inport->format.info.raw.channels,
inport->format.info.raw.rate,
inport->format.info.raw.layout,
this->port_count,
spa_debug_type_find_name(spa_type_audio_format, dst_fmt),
outport->format.info.raw.channels,
outport->format.info.raw.rate,
outport->format.info.raw.layout);
outport->format.info.raw.rate);
conv = find_conv_info(src_fmt, dst_fmt, FEATURE_SSE);
if (conv != NULL) {
spa_log_info(this->log, NAME " %p: got converter features %08x", this,
conv->features);
if (inport->format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED) {
if (outport->format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED)
this->convert = conv->i2i;
else
this->convert = conv->i2d;
}
else {
if (outport->format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED)
this->convert = conv->d2i;
else
this->convert = conv->i2i;
}
this->convert = conv->func;
return 0;
}
return -ENOTSUP;
@ -549,10 +538,13 @@ static int calc_width(struct spa_audio_info *info)
{
switch (info->info.raw.format) {
case SPA_AUDIO_FORMAT_U8:
case SPA_AUDIO_FORMAT_U8P:
return 1;
case SPA_AUDIO_FORMAT_S16P:
case SPA_AUDIO_FORMAT_S16:
case SPA_AUDIO_FORMAT_S16_OE:
return 2;
case SPA_AUDIO_FORMAT_S24P:
case SPA_AUDIO_FORMAT_S24:
case SPA_AUDIO_FORMAT_S24_OE:
return 3;
@ -603,9 +595,7 @@ static int port_set_format(struct spa_node *node,
if (info.info.raw.channels != this->port_count)
return -EINVAL;
} else {
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32)
return -EINVAL;
if (info.info.raw.layout != SPA_AUDIO_LAYOUT_NON_INTERLEAVED)
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32P)
return -EINVAL;
if (info.info.raw.channels != 1)
return -EINVAL;
@ -613,13 +603,12 @@ static int port_set_format(struct spa_node *node,
port->format = info;
port->stride = calc_width(&info);
if (info.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED) {
if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) {
port->blocks = info.info.raw.channels;
} else {
port->stride *= info.info.raw.channels;
port->blocks = 1;
}
else {
port->blocks = info.info.raw.channels;
}
spa_log_debug(this->log, NAME " %p: %d %d %d", this, port_id, port->stride, port->blocks);
this->have_format = true;

View file

@ -541,7 +541,6 @@ port_enum_formats(struct impl *this,
SPA_AUDIO_FORMAT_S32,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_F64),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_INTERLEAVED),
SPA_FORMAT_AUDIO_rate, &SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX),
SPA_FORMAT_AUDIO_channels, &SPA_POD_CHOICE_RANGE_Int(2, 1, INT32_MAX),
0);

View file

@ -975,7 +975,6 @@ impl_node_port_enum_params(struct spa_node *node,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_S16),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_INTERLEAVED),
SPA_FORMAT_AUDIO_rate, &SPA_POD_Int(rate),
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(channels),
0);

View file

@ -377,7 +377,6 @@ static int negotiate_formats(struct data *data)
filter = spa_format_audio_raw_build(&b, 0,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_S16,
.layout = SPA_AUDIO_LAYOUT_INTERLEAVED,
.rate = 44100,
.channels = 2 ));

View file

@ -210,7 +210,6 @@ static int negotiate_formats(struct data *data)
format = spa_format_audio_raw_build(&b, 0,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_S16,
.layout = SPA_AUDIO_LAYOUT_INTERLEAVED,
.rate = 44100,
.channels = 2 ));
@ -236,8 +235,7 @@ static int negotiate_formats(struct data *data)
spa_pod_builder_init(&b, buffer, sizeof(buffer));
format = spa_format_audio_raw_build(&b, 0,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_F32,
.layout = SPA_AUDIO_LAYOUT_NON_INTERLEAVED,
.format = SPA_AUDIO_FORMAT_F32P,
.rate = 44100,
.channels = 2 ));

View file

@ -260,7 +260,6 @@ static int negotiate_formats(struct data *data)
format = spa_format_audio_raw_build(&b, 0,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_S16,
.layout = SPA_AUDIO_LAYOUT_INTERLEAVED,
.rate = 44100,
.channels = 2 ));
@ -270,8 +269,7 @@ static int negotiate_formats(struct data *data)
spa_pod_builder_init(&b, buffer, sizeof(buffer));
format = spa_format_audio_raw_build(&b, 0,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_S16,
.layout = SPA_AUDIO_LAYOUT_NON_INTERLEAVED,
.format = SPA_AUDIO_FORMAT_S16P,
.rate = 48000,
.channels = 1 ));

View file

@ -351,7 +351,6 @@ static int negotiate_formats(struct data *data)
filter = spa_format_audio_raw_build(&b, 0,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_S16,
.layout = SPA_AUDIO_LAYOUT_INTERLEAVED,
.rate = 44100,
.channels = 2 ));

View file

@ -478,7 +478,6 @@ static int negotiate_formats(struct data *data)
filter = spa_format_audio_raw_build(&b, 0,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_S16,
.layout = SPA_AUDIO_LAYOUT_INTERLEAVED,
.rate = 44100,
.channels = 2 ));

View file

@ -275,7 +275,6 @@ static int negotiate_formats(struct data *data)
filter = spa_format_audio_raw_build(&b, 0,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_S16,
.layout = SPA_AUDIO_LAYOUT_INTERLEAVED,
.rate = 44100,
.channels = 2 ));

View file

@ -115,7 +115,6 @@ int main(int argc, char *argv[])
params[0] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
&SPA_AUDIO_INFO_RAW_INIT(
.format = SPA_AUDIO_FORMAT_F32,
.layout = SPA_AUDIO_LAYOUT_INTERLEAVED,
.channels = DEFAULT_CHANNELS,
.rate = DEFAULT_RATE ));

View file

@ -179,14 +179,12 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_CHOICE_ENUM_Id(3,
SPA_FORMAT_AUDIO_format, &SPA_POD_CHOICE_ENUM_Id(5,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S16P,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_F32P,
SPA_AUDIO_FORMAT_F32),
SPA_FORMAT_AUDIO_layout, &SPA_POD_CHOICE_ENUM_Id(3,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_channels, &SPA_POD_CHOICE_RANGE_Int(2, 1, INT32_MAX),
SPA_FORMAT_AUDIO_rate, &SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX),
0);

View file

@ -190,8 +190,8 @@ static void node_proxy_destroy(void *data)
if (n->info)
pw_node_info_free(n->info);
if (n->session) {
n->session = NULL;
spa_list_remove(&n->session_link);
n->session = NULL;
}
}
@ -276,6 +276,11 @@ handle_node(struct impl *impl, uint32_t id, uint32_t parent_id,
sess->need_dsp = need_dsp;
sess->enabled = true;
sess->node = node;
if ((str = spa_dict_lookup(props, "node.plugged")) != NULL)
sess->plugged = pw_properties_parse_uint64(str);
else
sess->plugged = SPA_TIMESPEC_TO_TIME(&impl->now);
spa_list_init(&sess->node_list);
spa_list_append(&impl->session_list, &sess->l);
@ -397,8 +402,6 @@ registry_global(void *data,uint32_t id, uint32_t parent_id,
{
struct impl *impl = data;
clock_gettime(CLOCK_MONOTONIC, &impl->now);
pw_log_debug(NAME " %p: new global '%d'", impl, id);
switch (type) {
@ -699,7 +702,6 @@ static void dsp_node_event_info(void *object, struct pw_node_info *info)
s->dsp = dsp;
spa_hook_remove(&s->listener);
dsp->session = s;
dsp->direction = s->direction;
dsp->type = NODE_TYPE_DSP;
}
@ -727,7 +729,7 @@ static void rescan_session(struct impl *impl, struct session *sess)
props = pw_properties_new_dict(node->info->props);
pw_properties_setf(props, "audio-dsp.direction", "%d", sess->direction);
pw_properties_setf(props, "audio-dsp.channels", "%d", node->format.channels);
pw_properties_setf(props, "audio-dsp.channelmask", "%"PRIu64, node->format.channel_mask);
pw_properties_setf(props, "audio-dsp.channelmask", "%d", 0);
pw_properties_setf(props, "audio-dsp.rate", "%d", node->format.rate);
pw_properties_setf(props, "audio-dsp.maxbuffer", "%ld", MAX_QUANTUM_SIZE * sizeof(float));
@ -749,6 +751,8 @@ static void do_rescan(struct impl *impl)
struct session *sess;
struct node *node;
clock_gettime(CLOCK_MONOTONIC, &impl->now);
spa_list_for_each(sess, &impl->session_list, l)
rescan_session(impl, sess);
spa_list_for_each(node, &impl->node_list, l)

View file

@ -454,6 +454,7 @@ handle_audio_fields (ConvertData *d)
choice->body.type = SPA_CHOICE_None;
}
#if 0
value = gst_structure_get_value (d->cs, "layout");
if (value) {
const char *v;
@ -478,6 +479,7 @@ handle_audio_fields (ConvertData *d)
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
#endif
value = gst_structure_get_value (d->cs, "rate");
if (value) {
int v;

View file

@ -896,6 +896,9 @@ static void client_node_initialized(void *data)
spa_debug_type_find_name(spa_type_media_subtype, media_subtype));
if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG))
spa_debug_format(2, NULL, format);
if (!exclusive &&
media_type == SPA_MEDIA_TYPE_audio &&
media_subtype == SPA_MEDIA_SUBTYPE_raw) {

View file

@ -646,7 +646,6 @@ static int collect_audio_format(void *data, uint32_t id,
if (info.channels > d->channels) {
d->channels = info.channels;
d->channelmask = info.channel_mask;
d->rate = info.rate;
}
return 0;

View file

@ -144,7 +144,8 @@ static const struct pw_port_implementation port_implementation = {
static const char *chmap_names[] =
{
"FL",
"MONO", /**< mono */
"FL", /**< front left */
"FR", /**< front right */
"RL", /**< rear left */
"RR", /**< rear right */
@ -242,6 +243,8 @@ struct pw_node *pw_audio_dsp_new(struct pw_core *core,
pw_properties_set(pr, "node.session", str);
pw_properties_setf(pr, "node.format.rate", "%d", sample_rate);
pw_properties_setf(pr, "node.format.channels", "%d", channels);
pw_properties_setf(pr, "node.format.channelmask", "%"PRIu64, channelmask);
node = pw_spa_node_load(core, NULL, NULL,
"audioconvert/libspa-audioconvert",
@ -293,6 +296,7 @@ struct pw_node *pw_audio_dsp_new(struct pw_core *core,
alias,
direction == PW_DIRECTION_INPUT ? "in" : "out",
channel_name);
pw_properties_setf(props, "port.channel", "%s", channel_name);
port = pw_port_new(direction,
i,

View file

@ -331,8 +331,7 @@ static int port_enum_formats(struct spa_node *node,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, &SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, &SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32),
SPA_FORMAT_AUDIO_layout, &SPA_POD_Id(SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
SPA_FORMAT_AUDIO_format, &SPA_POD_Id(SPA_AUDIO_FORMAT_F32P),
SPA_FORMAT_AUDIO_rate, &SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX),
SPA_FORMAT_AUDIO_channels, &SPA_POD_Int(1),
0);
@ -550,7 +549,7 @@ static int port_set_format(struct spa_node *node,
if (memcmp(&info, &this->format, sizeof(struct spa_audio_info)))
return -EINVAL;
} else {
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32)
if (info.info.raw.format != SPA_AUDIO_FORMAT_F32P)
return -EINVAL;
this->stride = sizeof(float);

View file

@ -777,8 +777,8 @@ static void port_marshal_info(void *object, struct pw_port_info *info)
spa_pod_builder_add(b,
"[",
"i", info->id,
"i", info->direction,
"l", info->change_mask,
"s", info->name,
"i", n_items, NULL);
for (i = 0; i < n_items; i++) {
@ -803,8 +803,8 @@ static int port_demarshal_info(void *object, void *data, size_t size)
if (spa_pod_parser_get(&prs,
"["
"i", &info.id,
"i", &info.direction,
"l", &info.change_mask,
"s", &info.name,
"i", &props.n_items, NULL) < 0)
return -EINVAL;

View file

@ -242,13 +242,9 @@ struct pw_port_info *pw_port_info_update(struct pw_port_info *info,
return NULL;
}
info->id = update->id;
info->direction = update->direction;
info->change_mask = update->change_mask;
if (update->change_mask & PW_PORT_CHANGE_MASK_NAME) {
if (info->name)
free((void *) info->name);
info->name = update->name ? strdup(update->name) : NULL;
}
if (update->change_mask & PW_PORT_CHANGE_MASK_PROPS) {
if (info->props)
pw_spa_dict_destroy(info->props);
@ -260,8 +256,6 @@ struct pw_port_info *pw_port_info_update(struct pw_port_info *info,
void pw_port_info_free(struct pw_port_info *info)
{
if (info->name)
free((void *) info->name);
if (info->props)
pw_spa_dict_destroy(info->props);
free(info);

View file

@ -167,11 +167,10 @@ pw_node_info_free(struct pw_node_info *info);
struct pw_port_info {
uint32_t id; /**< id of the global */
#define PW_PORT_CHANGE_MASK_NAME (1 << 0)
#define PW_PORT_CHANGE_MASK_PROPS (1 << 1)
#define PW_PORT_CHANGE_MASK_ENUM_PARAMS (1 << 2)
enum pw_direction direction; /**< port direction */
#define PW_PORT_CHANGE_MASK_PROPS (1 << 0)
#define PW_PORT_CHANGE_MASK_ENUM_PARAMS (1 << 1)
uint64_t change_mask; /**< bitfield of changed fields since last call */
const char *name; /**< name the port, suitable for display */
struct spa_dict *props; /**< the properties of the port */
};

View file

@ -889,8 +889,8 @@ uint32_t pw_node_get_free_port_id(struct pw_node *node, enum pw_direction direct
n_ports = node->info.n_output_ports;
portmap = &node->output_port_map;
}
pw_log_debug("node %p: direction %d %u %u",
node, direction, n_ports, max_ports);
pw_log_debug("node %p: direction %s n_ports:%u max_ports:%u",
node, pw_direction_as_string(direction), n_ports, max_ports);
if (n_ports >= max_ports)
goto no_mem;

View file

@ -214,6 +214,7 @@ struct pw_port *pw_port_new(enum pw_direction direction,
if (user_data_size > 0)
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
this->info.direction = direction;
this->info.props = &this->properties->dict;
spa_list_init(&this->links);

View file

@ -555,9 +555,8 @@ static void info_port(struct proxy_data *pd)
struct pw_port_info *info = pd->info;
info_global(pd);
fprintf(stdout, "%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
print_properties(info->props, MARK_CHANGE(1), true);
fprintf(stdout, "%c\tenum_params\n", MARK_CHANGE(2));
print_properties(info->props, MARK_CHANGE(0), true);
fprintf(stdout, "%c\tenum_params\n", MARK_CHANGE(1));
info->change_mask = 0;
}

View file

@ -289,8 +289,8 @@ static void print_port(struct proxy_data *data)
printf("\ttype: %s (version %d)\n", PW_TYPE_INTERFACE__Port, data->version);
if (print_all) {
int i;
printf("%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
printf("%c\tparams:\n", MARK_CHANGE(2));
printf(" \tdirection: \"%s\"\n", pw_direction_as_string(info->direction));
printf("%c\tparams:\n", MARK_CHANGE(1));
for (i = 0; i < data->n_params; i++) {
if (spa_pod_is_object_type(data->params[i], SPA_TYPE_OBJECT_Format))
spa_debug_format(12, NULL, data->params[i]);