mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-06 13:30:01 -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
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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue