|
Packit Service |
cd2a00 |
/*
|
|
Packit Service |
cd2a00 |
* 4/5/6 -> 2 downmix with a simple spacialization
|
|
Packit Service |
cd2a00 |
*
|
|
Packit Service |
cd2a00 |
* Copyright (c) 2006 by Takashi Iwai <tiwai@suse.de>
|
|
Packit Service |
cd2a00 |
*
|
|
Packit Service |
cd2a00 |
* This library is free software; you can redistribute it and/or modify
|
|
Packit Service |
cd2a00 |
* it under the terms of the GNU Lesser General Public License as
|
|
Packit Service |
cd2a00 |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
cd2a00 |
* the License, or (at your option) any later version.
|
|
Packit Service |
cd2a00 |
*
|
|
Packit Service |
cd2a00 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
cd2a00 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
cd2a00 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
cd2a00 |
* GNU Lesser General Public License for more details.
|
|
Packit Service |
cd2a00 |
*
|
|
Packit Service |
cd2a00 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
cd2a00 |
* License along with this library; if not, write to the Free Software
|
|
Packit Service |
cd2a00 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit Service |
cd2a00 |
*/
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
#include <alsa/asoundlib.h>
|
|
Packit Service |
cd2a00 |
#include <alsa/pcm_external.h>
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
/* #define I_AM_POWERFUL */
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
#ifdef I_AM_POWERFUL
|
|
Packit Service |
cd2a00 |
#define RINGBUF_SIZE (1 << 9)
|
|
Packit Service |
cd2a00 |
#else
|
|
Packit Service |
cd2a00 |
#define RINGBUF_SIZE (1 << 7)
|
|
Packit Service |
cd2a00 |
#endif
|
|
Packit Service |
cd2a00 |
#define RINGBUF_MASK (RINGBUF_SIZE - 1)
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
struct vdownmix_tap {
|
|
Packit Service |
cd2a00 |
int delay;
|
|
Packit Service |
cd2a00 |
int weight;
|
|
Packit Service |
cd2a00 |
};
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
#define MAX_TAPS 30
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
struct vdownmix_filter {
|
|
Packit Service |
cd2a00 |
int taps;
|
|
Packit Service |
cd2a00 |
struct vdownmix_tap tap[MAX_TAPS];
|
|
Packit Service |
cd2a00 |
};
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
typedef struct {
|
|
Packit Service |
cd2a00 |
snd_pcm_extplug_t ext;
|
|
Packit Service |
cd2a00 |
int channels;
|
|
Packit Service |
cd2a00 |
unsigned int curpos;
|
|
Packit Service |
cd2a00 |
short rbuf[RINGBUF_SIZE][5];
|
|
Packit Service |
cd2a00 |
} snd_pcm_vdownmix_t;
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static const struct vdownmix_filter tap_filters[5] = {
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
#ifdef I_AM_POWERFUL
|
|
Packit Service |
cd2a00 |
18,
|
|
Packit Service |
cd2a00 |
#else
|
|
Packit Service |
cd2a00 |
14,
|
|
Packit Service |
cd2a00 |
#endif
|
|
Packit Service |
cd2a00 |
{{ 0, 0xfffffd0a },
|
|
Packit Service |
cd2a00 |
{ 1, 0x41d },
|
|
Packit Service |
cd2a00 |
{ 2, 0xffffe657 },
|
|
Packit Service |
cd2a00 |
{ 3, 0x6eb5 },
|
|
Packit Service |
cd2a00 |
{ 4, 0xffffe657 },
|
|
Packit Service |
cd2a00 |
{ 5, 0x41d },
|
|
Packit Service |
cd2a00 |
{ 6, 0xfffffd0a },
|
|
Packit Service |
cd2a00 |
{ 71, 0xffffff1c },
|
|
Packit Service |
cd2a00 |
{ 72, 0x12e },
|
|
Packit Service |
cd2a00 |
{ 73, 0xfffff81a },
|
|
Packit Service |
cd2a00 |
{ 74, 0x24de },
|
|
Packit Service |
cd2a00 |
{ 75, 0xfffff81a },
|
|
Packit Service |
cd2a00 |
{ 76, 0x12e },
|
|
Packit Service |
cd2a00 |
{ 77, 0xffffff1c },
|
|
Packit Service |
cd2a00 |
{ 265, 0xfffffc65 },
|
|
Packit Service |
cd2a00 |
{ 266, 0xee1 },
|
|
Packit Service |
cd2a00 |
{ 267, 0xfffffc65 },
|
|
Packit Service |
cd2a00 |
{ 395, 0x46a }},
|
|
Packit Service |
cd2a00 |
},
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
#ifdef I_AM_POWERFUL
|
|
Packit Service |
cd2a00 |
17,
|
|
Packit Service |
cd2a00 |
#else
|
|
Packit Service |
cd2a00 |
10,
|
|
Packit Service |
cd2a00 |
#endif
|
|
Packit Service |
cd2a00 |
{{ 8, 0xcf },
|
|
Packit Service |
cd2a00 |
{ 9, 0xa7b },
|
|
Packit Service |
cd2a00 |
{ 10, 0xcd7 },
|
|
Packit Service |
cd2a00 |
{ 11, 0x5b3 },
|
|
Packit Service |
cd2a00 |
{ 12, 0x859 },
|
|
Packit Service |
cd2a00 |
{ 13, 0xaf },
|
|
Packit Service |
cd2a00 |
{ 80, 0x38b },
|
|
Packit Service |
cd2a00 |
{ 81, 0x454 },
|
|
Packit Service |
cd2a00 |
{ 82, 0x218 },
|
|
Packit Service |
cd2a00 |
{ 83, 0x2c1 },
|
|
Packit Service |
cd2a00 |
{ 268, 0x58b },
|
|
Packit Service |
cd2a00 |
{ 275, 0xc2 },
|
|
Packit Service |
cd2a00 |
{ 397, 0xbd },
|
|
Packit Service |
cd2a00 |
{ 398, 0x1e8 },
|
|
Packit Service |
cd2a00 |
{ 506, 0xfffffeac },
|
|
Packit Service |
cd2a00 |
{ 507, 0x636 },
|
|
Packit Service |
cd2a00 |
{ 508, 0xfffffeac }},
|
|
Packit Service |
cd2a00 |
},
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
#ifdef I_AM_POWERFUL
|
|
Packit Service |
cd2a00 |
11,
|
|
Packit Service |
cd2a00 |
#else
|
|
Packit Service |
cd2a00 |
1,
|
|
Packit Service |
cd2a00 |
#endif
|
|
Packit Service |
cd2a00 |
{{ 3, 0x4000 },
|
|
Packit Service |
cd2a00 |
{ 125, 0x12a },
|
|
Packit Service |
cd2a00 |
{ 126, 0xda1 },
|
|
Packit Service |
cd2a00 |
{ 127, 0x12a },
|
|
Packit Service |
cd2a00 |
{ 193, 0xfffffed3 },
|
|
Packit Service |
cd2a00 |
{ 194, 0xdb9 },
|
|
Packit Service |
cd2a00 |
{ 195, 0xfffffed3 },
|
|
Packit Service |
cd2a00 |
{ 454, 0x10a },
|
|
Packit Service |
cd2a00 |
{ 483, 0xfffffe97 },
|
|
Packit Service |
cd2a00 |
{ 484, 0x698 },
|
|
Packit Service |
cd2a00 |
{ 485, 0xfffffe97 }},
|
|
Packit Service |
cd2a00 |
},
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
#ifdef I_AM_POWERFUL
|
|
Packit Service |
cd2a00 |
25,
|
|
Packit Service |
cd2a00 |
#else
|
|
Packit Service |
cd2a00 |
10,
|
|
Packit Service |
cd2a00 |
#endif
|
|
Packit Service |
cd2a00 |
{{ 5, 0x1cb },
|
|
Packit Service |
cd2a00 |
{ 6, 0x9c5 },
|
|
Packit Service |
cd2a00 |
{ 7, 0x117e },
|
|
Packit Service |
cd2a00 |
{ 8, 0x200 },
|
|
Packit Service |
cd2a00 |
{ 9, 0x533 },
|
|
Packit Service |
cd2a00 |
{ 10, 0x1c6 },
|
|
Packit Service |
cd2a00 |
{ 11, 0x167 },
|
|
Packit Service |
cd2a00 |
{ 12, 0x5ff },
|
|
Packit Service |
cd2a00 |
{ 13, 0x425 },
|
|
Packit Service |
cd2a00 |
{ 14, 0xd9 },
|
|
Packit Service |
cd2a00 |
{ 128, 0x247 },
|
|
Packit Service |
cd2a00 |
{ 129, 0x5e1 },
|
|
Packit Service |
cd2a00 |
{ 130, 0xb7 },
|
|
Packit Service |
cd2a00 |
{ 131, 0x122 },
|
|
Packit Service |
cd2a00 |
{ 135, 0x10a },
|
|
Packit Service |
cd2a00 |
{ 200, 0x1b6 },
|
|
Packit Service |
cd2a00 |
{ 201, 0xa7 },
|
|
Packit Service |
cd2a00 |
{ 202, 0x188 },
|
|
Packit Service |
cd2a00 |
{ 203, 0x1d9 },
|
|
Packit Service |
cd2a00 |
{ 445, 0xffffff44 },
|
|
Packit Service |
cd2a00 |
{ 446, 0x5e2 },
|
|
Packit Service |
cd2a00 |
{ 447, 0xffffff44 },
|
|
Packit Service |
cd2a00 |
{ 484, 0xffffff51 },
|
|
Packit Service |
cd2a00 |
{ 485, 0x449 },
|
|
Packit Service |
cd2a00 |
{ 486, 0xffffff51 }},
|
|
Packit Service |
cd2a00 |
},
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
#ifdef I_AM_POWERFUL
|
|
Packit Service |
cd2a00 |
21,
|
|
Packit Service |
cd2a00 |
#else
|
|
Packit Service |
cd2a00 |
7,
|
|
Packit Service |
cd2a00 |
#endif
|
|
Packit Service |
cd2a00 |
{{ 0, 0xfffffdee },
|
|
Packit Service |
cd2a00 |
{ 1, 0x28b },
|
|
Packit Service |
cd2a00 |
{ 2, 0xffffed1e },
|
|
Packit Service |
cd2a00 |
{ 3, 0x6336 },
|
|
Packit Service |
cd2a00 |
{ 4, 0xffffed1e },
|
|
Packit Service |
cd2a00 |
{ 5, 0x28b },
|
|
Packit Service |
cd2a00 |
{ 6, 0xfffffdee },
|
|
Packit Service |
cd2a00 |
{ 51, 0xffffff2c },
|
|
Packit Service |
cd2a00 |
{ 52, 0x105 },
|
|
Packit Service |
cd2a00 |
{ 53, 0xfffff86b },
|
|
Packit Service |
cd2a00 |
{ 54, 0x27d9 },
|
|
Packit Service |
cd2a00 |
{ 55, 0xfffff86b },
|
|
Packit Service |
cd2a00 |
{ 56, 0x105 },
|
|
Packit Service |
cd2a00 |
{ 57, 0xffffff2c },
|
|
Packit Service |
cd2a00 |
{ 333, 0xfffffd69 },
|
|
Packit Service |
cd2a00 |
{ 334, 0xb2f },
|
|
Packit Service |
cd2a00 |
{ 335, 0xfffffd69 },
|
|
Packit Service |
cd2a00 |
{ 339, 0xdf },
|
|
Packit Service |
cd2a00 |
{ 340, 0x168 },
|
|
Packit Service |
cd2a00 |
{ 342, 0xa6 },
|
|
Packit Service |
cd2a00 |
{ 343, 0xba }},
|
|
Packit Service |
cd2a00 |
},
|
|
Packit Service |
cd2a00 |
};
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static const int tap_index[5][2] = {
|
|
Packit Service |
cd2a00 |
/* left */
|
|
Packit Service |
cd2a00 |
{ 0, 1 },
|
|
Packit Service |
cd2a00 |
/* right */
|
|
Packit Service |
cd2a00 |
{ 1, 0 },
|
|
Packit Service |
cd2a00 |
/* rear left */
|
|
Packit Service |
cd2a00 |
{ 2, 3 },
|
|
Packit Service |
cd2a00 |
/* rear right */
|
|
Packit Service |
cd2a00 |
{ 3, 2 },
|
|
Packit Service |
cd2a00 |
/* center */
|
|
Packit Service |
cd2a00 |
{ 4, 4 },
|
|
Packit Service |
cd2a00 |
};
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static inline void *area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset)
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
unsigned int bitofs = area->first + area->step * offset;
|
|
Packit Service |
cd2a00 |
return (char *) area->addr + bitofs / 8;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static inline unsigned int area_step(const snd_pcm_channel_area_t *area)
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
return area->step / 8;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static snd_pcm_sframes_t
|
|
Packit Service |
cd2a00 |
vdownmix_transfer(snd_pcm_extplug_t *ext,
|
|
Packit Service |
cd2a00 |
const snd_pcm_channel_area_t *dst_areas,
|
|
Packit Service |
cd2a00 |
snd_pcm_uframes_t dst_offset,
|
|
Packit Service |
cd2a00 |
const snd_pcm_channel_area_t *src_areas,
|
|
Packit Service |
cd2a00 |
snd_pcm_uframes_t src_offset,
|
|
Packit Service |
cd2a00 |
snd_pcm_uframes_t size)
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
snd_pcm_vdownmix_t *mix = (snd_pcm_vdownmix_t *)ext;
|
|
Packit Service |
cd2a00 |
short *src[mix->channels], *ptr[2];
|
|
Packit Service |
cd2a00 |
unsigned int src_step[mix->channels], step[2];
|
|
Packit Service |
cd2a00 |
int i, ch, curpos, p, idx;
|
|
Packit Service |
cd2a00 |
int acc[2];
|
|
Packit Service |
cd2a00 |
int fr;
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
ptr[0] = area_addr(dst_areas, dst_offset);
|
|
Packit Service |
cd2a00 |
step[0] = area_step(dst_areas) / 2;
|
|
Packit Service |
cd2a00 |
ptr[1] = area_addr(dst_areas + 1, dst_offset);
|
|
Packit Service |
cd2a00 |
step[1] = area_step(dst_areas + 1) / 2;
|
|
Packit Service |
cd2a00 |
for (ch = 0; ch < mix->channels; ch++) {
|
|
Packit Service |
cd2a00 |
const snd_pcm_channel_area_t *src_area = &src_areas[ch];
|
|
Packit Service |
cd2a00 |
src[ch] = area_addr(src_area, src_offset);
|
|
Packit Service |
cd2a00 |
src_step[ch] = area_step(src_area) / 2;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
curpos = mix->curpos;
|
|
Packit Service |
cd2a00 |
fr = size;
|
|
Packit Service |
cd2a00 |
while (fr--) {
|
|
Packit Service |
cd2a00 |
acc[0] = acc[1] = 0;
|
|
Packit Service |
cd2a00 |
for (ch = 0; ch < mix->channels; ch++) {
|
|
Packit Service |
cd2a00 |
mix->rbuf[curpos][ch] = *src[ch];
|
|
Packit Service |
cd2a00 |
for (idx = 0; idx < 2; idx++) {
|
|
Packit Service |
cd2a00 |
int f = tap_index[ch][idx];
|
|
Packit Service |
cd2a00 |
const struct vdownmix_filter *filter;
|
|
Packit Service |
cd2a00 |
filter = &tap_filters[f];
|
|
Packit Service |
cd2a00 |
for (i = 0; i < filter->taps; i++) {
|
|
Packit Service |
cd2a00 |
p = (curpos + RINGBUF_SIZE - filter->tap[i].delay)
|
|
Packit Service |
cd2a00 |
& RINGBUF_MASK;
|
|
Packit Service |
cd2a00 |
acc[idx] += mix->rbuf[p][ch] * filter->tap[i].weight;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
src[ch] += src_step[ch];
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
for (idx = 0; idx < 2; idx++) {
|
|
Packit Service |
cd2a00 |
acc[idx] >>= 14;
|
|
Packit Service |
cd2a00 |
if (acc[idx] < -32768)
|
|
Packit Service |
cd2a00 |
*ptr[idx] = -32768;
|
|
Packit Service |
cd2a00 |
else if (acc[idx] > 32767)
|
|
Packit Service |
cd2a00 |
*ptr[idx] = 32767;
|
|
Packit Service |
cd2a00 |
else
|
|
Packit Service |
cd2a00 |
*ptr[idx] = acc[idx];
|
|
Packit Service |
cd2a00 |
ptr[idx] += step[idx];
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
curpos = (curpos + 1) & RINGBUF_MASK;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
mix->curpos = curpos;
|
|
Packit Service |
cd2a00 |
return size;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static int vdownmix_init(snd_pcm_extplug_t *ext)
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
snd_pcm_vdownmix_t *mix = (snd_pcm_vdownmix_t *)ext;
|
|
Packit Service |
cd2a00 |
mix->channels = ext->channels;
|
|
Packit Service |
cd2a00 |
if (mix->channels > 5) /* ignore LFE */
|
|
Packit Service |
cd2a00 |
mix->channels = 5;
|
|
Packit Service |
cd2a00 |
mix->curpos = 0;
|
|
Packit Service |
cd2a00 |
memset(mix->rbuf, 0, sizeof(mix->rbuf));
|
|
Packit Service |
cd2a00 |
return 0;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
#if SND_PCM_EXTPLUG_VERSION >= 0x10002
|
|
Packit Service |
cd2a00 |
static unsigned int chmap[6] = {
|
|
Packit Service |
cd2a00 |
SND_CHMAP_FL, SND_CHMAP_FR,
|
|
Packit Service |
cd2a00 |
SND_CHMAP_RL, SND_CHMAP_RR,
|
|
Packit Service |
cd2a00 |
SND_CHMAP_FC, SND_CHMAP_LFE,
|
|
Packit Service |
cd2a00 |
};
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static snd_pcm_chmap_query_t **vdownmix_query_chmaps(snd_pcm_extplug_t *ext ATTRIBUTE_UNUSED)
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
snd_pcm_chmap_query_t **maps;
|
|
Packit Service |
cd2a00 |
int i;
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
maps = calloc(4, sizeof(void *));
|
|
Packit Service |
cd2a00 |
if (!maps)
|
|
Packit Service |
cd2a00 |
return NULL;
|
|
Packit Service |
cd2a00 |
for (i = 0; i < 3; i++) {
|
|
Packit Service |
cd2a00 |
snd_pcm_chmap_query_t *p;
|
|
Packit Service |
cd2a00 |
p = maps[i] = calloc(i + 4 + 2, sizeof(int));
|
|
Packit Service |
cd2a00 |
if (!p) {
|
|
Packit Service |
cd2a00 |
snd_pcm_free_chmaps(maps);
|
|
Packit Service |
cd2a00 |
return NULL;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
p->type = SND_CHMAP_TYPE_FIXED;
|
|
Packit Service |
cd2a00 |
p->map.channels = i + 4;
|
|
Packit Service |
cd2a00 |
memcpy(p->map.pos, chmap, (i + 4) * sizeof(int));
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
return maps;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static snd_pcm_chmap_t *vdownmix_get_chmap(snd_pcm_extplug_t *ext)
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
snd_pcm_chmap_t *map;
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
if (ext->channels < 4 || ext->channels > 6)
|
|
Packit Service |
cd2a00 |
return NULL;
|
|
Packit Service |
cd2a00 |
map = malloc((ext->channels + 1) * sizeof(int));
|
|
Packit Service |
cd2a00 |
if (!map)
|
|
Packit Service |
cd2a00 |
return NULL;
|
|
Packit Service |
cd2a00 |
map->channels = ext->channels;
|
|
Packit Service |
cd2a00 |
memcpy(map->pos, chmap, ext->channels * sizeof(int));
|
|
Packit Service |
cd2a00 |
return map;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
#endif /* SND_PCM_EXTPLUG_VERSION >= 0x10002 */
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
static const snd_pcm_extplug_callback_t vdownmix_callback = {
|
|
Packit Service |
cd2a00 |
.transfer = vdownmix_transfer,
|
|
Packit Service |
cd2a00 |
.init = vdownmix_init,
|
|
Packit Service |
cd2a00 |
/* .dump = filr_dump, */
|
|
Packit Service |
cd2a00 |
#if SND_PCM_EXTPLUG_VERSION >= 0x10002
|
|
Packit Service |
cd2a00 |
.query_chmaps = vdownmix_query_chmaps,
|
|
Packit Service |
cd2a00 |
.get_chmap = vdownmix_get_chmap,
|
|
Packit Service |
cd2a00 |
#endif
|
|
Packit Service |
cd2a00 |
};
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
SND_PCM_PLUGIN_DEFINE_FUNC(vdownmix)
|
|
Packit Service |
cd2a00 |
{
|
|
Packit Service |
cd2a00 |
snd_config_iterator_t i, next;
|
|
Packit Service |
cd2a00 |
snd_pcm_vdownmix_t *mix;
|
|
Packit Service |
cd2a00 |
snd_config_t *sconf = NULL;
|
|
Packit Service |
cd2a00 |
int err;
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
snd_config_for_each(i, next, conf) {
|
|
Packit Service |
cd2a00 |
snd_config_t *n = snd_config_iterator_entry(i);
|
|
Packit Service |
cd2a00 |
const char *id;
|
|
Packit Service |
cd2a00 |
if (snd_config_get_id(n, &id) < 0)
|
|
Packit Service |
cd2a00 |
continue;
|
|
Packit Service |
cd2a00 |
if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0 || strcmp(id, "hint") == 0)
|
|
Packit Service |
cd2a00 |
continue;
|
|
Packit Service |
cd2a00 |
if (strcmp(id, "slave") == 0) {
|
|
Packit Service |
cd2a00 |
sconf = n;
|
|
Packit Service |
cd2a00 |
continue;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
SNDERR("Unknown field %s", id);
|
|
Packit Service |
cd2a00 |
return -EINVAL;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
if (! sconf) {
|
|
Packit Service |
cd2a00 |
SNDERR("No slave configuration for vdownmix pcm");
|
|
Packit Service |
cd2a00 |
return -EINVAL;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
mix = calloc(1, sizeof(*mix));
|
|
Packit Service |
cd2a00 |
if (mix == NULL)
|
|
Packit Service |
cd2a00 |
return -ENOMEM;
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
mix->ext.version = SND_PCM_EXTPLUG_VERSION;
|
|
Packit Service |
cd2a00 |
mix->ext.name = "Vdownmix Plugin";
|
|
Packit Service |
cd2a00 |
mix->ext.callback = &vdownmix_callback;
|
|
Packit Service |
cd2a00 |
mix->ext.private_data = mix;
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
err = snd_pcm_extplug_create(&mix->ext, name, root, sconf, stream, mode);
|
|
Packit Service |
cd2a00 |
if (err < 0) {
|
|
Packit Service |
cd2a00 |
free(mix);
|
|
Packit Service |
cd2a00 |
return err;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
/* 4/5/6 -> 2 downmix */
|
|
Packit Service |
cd2a00 |
snd_pcm_extplug_set_param_minmax(&mix->ext, SND_PCM_EXTPLUG_HW_CHANNELS,
|
|
Packit Service |
cd2a00 |
4, 6);
|
|
Packit Service |
cd2a00 |
snd_pcm_extplug_set_slave_param(&mix->ext, SND_PCM_EXTPLUG_HW_CHANNELS, 2);
|
|
Packit Service |
cd2a00 |
snd_pcm_extplug_set_param(&mix->ext, SND_PCM_EXTPLUG_HW_FORMAT,
|
|
Packit Service |
cd2a00 |
SND_PCM_FORMAT_S16);
|
|
Packit Service |
cd2a00 |
snd_pcm_extplug_set_slave_param(&mix->ext, SND_PCM_EXTPLUG_HW_FORMAT,
|
|
Packit Service |
cd2a00 |
SND_PCM_FORMAT_S16);
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
*pcmp = mix->ext.pcm;
|
|
Packit Service |
cd2a00 |
return 0;
|
|
Packit Service |
cd2a00 |
}
|
|
Packit Service |
cd2a00 |
|
|
Packit Service |
cd2a00 |
SND_PCM_PLUGIN_SYMBOL(vdownmix);
|