mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-21 08:56:56 -05:00
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:
parent
fb3379e587
commit
5196f7f053
38 changed files with 981 additions and 369 deletions
|
|
@ -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,36 +206,23 @@ 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)
|
||||
if (snd_pcm_access_mask_test(amask, SND_PCM_ACCESS_MMAP_INTERLEAVED)) {
|
||||
if (j++ == 0)
|
||||
spa_pod_builder_id(&b, fi->spa_format);
|
||||
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) &&
|
||||
fi->spa_pformat != SPA_AUDIO_FORMAT_UNKNOWN) {
|
||||
if (j++ == 0)
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
if (snd_pcm_access_mask_test(amask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) {
|
||||
if (j++ == 0)
|
||||
spa_pod_builder_id(&b, SPA_AUDIO_LAYOUT_NON_INTERLEAVED);
|
||||
spa_pod_builder_id(&b, SPA_AUDIO_LAYOUT_NON_INTERLEAVED);
|
||||
}
|
||||
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);
|
||||
|
||||
|
|
|
|||
262
spa/plugins/audioconvert/channelmix-ops-sse.c
Normal file
262
spa/plugins/audioconvert/channelmix-ops-sse.c
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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] &&
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue