1 /* Audio filter that adds and removes channels, according to the
2 command line parameter channels. It is stupid and can only add
3 silence or copy channels not mix or filter.
15 typedef struct af_channels_s
{
21 // Local function for copying data
22 static void copy(void* in
, void* out
, int ins
, int inos
,int outs
, int outos
, int len
, int bps
)
26 int8_t* tin
= (int8_t*)in
;
27 int8_t* tout
= (int8_t*)out
;
39 int16_t* tin
= (int16_t*)in
;
40 int16_t* tout
= (int16_t*)out
;
52 int8_t* tin
= (int8_t*)in
;
53 int8_t* tout
= (int8_t*)out
;
56 len
= len
/ ( 3 * ins
);
67 int32_t* tin
= (int32_t*)in
;
68 int32_t* tout
= (int32_t*)out
;
80 int64_t* tin
= (int64_t*)in
;
81 int64_t* tout
= (int64_t*)out
;
93 af_msg(AF_MSG_ERROR
,"[channels] Unsupported number of bytes/sample: %i"
94 " please report this error on the MPlayer mailing list. \n",bps
);
98 // Make sure the routes are sane
99 static int check_routes(af_channels_t
* s
, int nin
, int nout
)
102 if((s
->nr
< 1) || (s
->nr
> AF_NCH
)){
103 af_msg(AF_MSG_ERROR
,"[channels] The number of routing pairs must be"
104 " between 1 and %i. Current value is %i\n",AF_NCH
,s
->nr
);
108 for(i
=0;i
<s
->nr
;i
++){
109 if((s
->route
[i
][FR
] >= nin
) || (s
->route
[i
][TO
] >= nout
)){
110 af_msg(AF_MSG_ERROR
,"[channels] Invalid routing in pair nr. %i.\n", i
);
117 // Initialization and runtime control
118 static int control(struct af_instance_s
* af
, int cmd
, void* arg
)
120 af_channels_t
* s
= af
->setup
;
122 case AF_CONTROL_REINIT
:
124 // Set default channel assignment
127 // Make sure this filter isn't redundant
128 if(af
->data
->nch
== ((af_data_t
*)arg
)->nch
)
131 // If mono: fake stereo
132 if(((af_data_t
*)arg
)->nch
== 1){
133 s
->nr
= min(af
->data
->nch
,2);
134 for(i
=0;i
<s
->nr
;i
++){
140 s
->nr
= min(af
->data
->nch
, ((af_data_t
*)arg
)->nch
);
141 for(i
=0;i
<s
->nr
;i
++){
148 af
->data
->rate
= ((af_data_t
*)arg
)->rate
;
149 af
->data
->format
= ((af_data_t
*)arg
)->format
;
150 af
->data
->bps
= ((af_data_t
*)arg
)->bps
;
151 af
->mul
= (double)af
->data
->nch
/ ((af_data_t
*)arg
)->nch
;
152 return check_routes(s
,((af_data_t
*)arg
)->nch
,af
->data
->nch
);
153 case AF_CONTROL_COMMAND_LINE
:{
156 // Check number of channels and number of routing pairs
157 sscanf(arg
, "%i:%i%n", &nch
, &s
->nr
, &n
);
159 // If router scan commandline for routing pairs
161 char* cp
= &((char*)arg
)[n
];
164 if((s
->nr
< 1) || (s
->nr
> AF_NCH
)){
165 af_msg(AF_MSG_ERROR
,"[channels] The number of routing pairs must be"
166 " between 1 and %i. Current value is %i\n",AF_NCH
,s
->nr
);
169 // Scan for pairs on commandline
170 while((*cp
== ':') && (ch
< s
->nr
)){
171 sscanf(cp
, ":%i:%i%n" ,&s
->route
[ch
][FR
], &s
->route
[ch
][TO
], &n
);
172 af_msg(AF_MSG_VERBOSE
,"[channels] Routing from channel %i to"
173 " channel %i\n",s
->route
[ch
][FR
],s
->route
[ch
][TO
]);
179 if(AF_OK
!= af
->control(af
,AF_CONTROL_CHANNELS
| AF_CONTROL_SET
,&nch
))
183 case AF_CONTROL_CHANNELS
| AF_CONTROL_SET
:
184 // Reinit must be called after this function has been called
187 if(((int*)arg
)[0] <= 0 || ((int*)arg
)[0] > AF_NCH
){
188 af_msg(AF_MSG_ERROR
,"[channels] The number of output channels must be"
189 " between 1 and %i. Current value is %i\n",AF_NCH
,((int*)arg
)[0]);
193 af
->data
->nch
=((int*)arg
)[0];
195 af_msg(AF_MSG_VERBOSE
,"[channels] Changing number of channels"
196 " to %i\n",af
->data
->nch
);
198 case AF_CONTROL_CHANNELS
| AF_CONTROL_GET
:
199 *(int*)arg
= af
->data
->nch
;
201 case AF_CONTROL_CHANNELS_ROUTING
| AF_CONTROL_SET
:{
202 int ch
= ((af_control_ext_t
*)arg
)->ch
;
203 int* route
= ((af_control_ext_t
*)arg
)->arg
;
204 s
->route
[ch
][FR
] = route
[FR
];
205 s
->route
[ch
][TO
] = route
[TO
];
208 case AF_CONTROL_CHANNELS_ROUTING
| AF_CONTROL_GET
:{
209 int ch
= ((af_control_ext_t
*)arg
)->ch
;
210 int* route
= ((af_control_ext_t
*)arg
)->arg
;
211 route
[FR
] = s
->route
[ch
][FR
];
212 route
[TO
] = s
->route
[ch
][TO
];
215 case AF_CONTROL_CHANNELS_NR
| AF_CONTROL_SET
:
218 case AF_CONTROL_CHANNELS_NR
| AF_CONTROL_GET
:
221 case AF_CONTROL_CHANNELS_ROUTER
| AF_CONTROL_SET
:
222 s
->router
= *(int*)arg
;
224 case AF_CONTROL_CHANNELS_ROUTER
| AF_CONTROL_GET
:
225 *(int*)arg
= s
->router
;
232 static void uninit(struct af_instance_s
* af
)
236 free(af
->data
->audio
);
240 // Filter data through filter
241 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
243 af_data_t
* c
= data
; // Current working data
244 af_data_t
* l
= af
->data
; // Local data
245 af_channels_t
* s
= af
->setup
;
248 if(AF_OK
!= RESIZE_LOCAL_BUFFER(af
,data
))
251 // Reset unused channels
252 memset(l
->audio
,0,c
->len
/ c
->nch
* l
->nch
);
254 if(AF_OK
== check_routes(s
,c
->nch
,l
->nch
))
256 copy(c
->audio
,l
->audio
,c
->nch
,s
->route
[i
][FR
],
257 l
->nch
,s
->route
[i
][TO
],c
->len
,c
->bps
);
261 c
->len
= c
->len
/ c
->nch
* l
->nch
;
267 // Allocate memory and set function pointers
268 static int af_open(af_instance_t
* af
){
273 af
->data
=calloc(1,sizeof(af_data_t
));
274 af
->setup
=calloc(1,sizeof(af_channels_t
));
275 if((af
->data
== NULL
) || (af
->setup
== NULL
))
280 // Description of this filter
281 af_info_t af_info_channels
= {
282 "Insert or remove channels",