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

@ -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;