2 * Audio filter that adds and removes channels, according to the
3 * command line parameter channels. It is stupid and can only add
4 * silence or copy channels, not mix or filter.
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 typedef struct af_channels_s
{
39 // Local function for copying data
40 static void copy(void* in
, void* out
, int ins
, int inos
,int outs
, int outos
, int len
, int bps
)
44 int8_t* tin
= (int8_t*)in
;
45 int8_t* tout
= (int8_t*)out
;
57 int16_t* tin
= (int16_t*)in
;
58 int16_t* tout
= (int16_t*)out
;
70 int8_t* tin
= (int8_t*)in
;
71 int8_t* tout
= (int8_t*)out
;
74 len
= len
/ ( 3 * ins
);
85 int32_t* tin
= (int32_t*)in
;
86 int32_t* tout
= (int32_t*)out
;
98 int64_t* tin
= (int64_t*)in
;
99 int64_t* tout
= (int64_t*)out
;
111 af_msg(AF_MSG_ERROR
,"[channels] Unsupported number of bytes/sample: %i"
112 " please report this error on the MPlayer mailing list. \n",bps
);
116 // Make sure the routes are sane
117 static int check_routes(af_channels_t
* s
, int nin
, int nout
)
120 if((s
->nr
< 1) || (s
->nr
> AF_NCH
)){
121 af_msg(AF_MSG_ERROR
,"[channels] The number of routing pairs must be"
122 " between 1 and %i. Current value is %i\n",AF_NCH
,s
->nr
);
126 for(i
=0;i
<s
->nr
;i
++){
127 if((s
->route
[i
][FR
] >= nin
) || (s
->route
[i
][TO
] >= nout
)){
128 af_msg(AF_MSG_ERROR
,"[channels] Invalid routing in pair nr. %i.\n", i
);
135 // Initialization and runtime control
136 static int control(struct af_instance_s
* af
, int cmd
, void* arg
)
138 af_channels_t
* s
= af
->setup
;
140 case AF_CONTROL_REINIT
:
142 // Set default channel assignment
145 // Make sure this filter isn't redundant
146 if(af
->data
->nch
== ((af_data_t
*)arg
)->nch
)
149 // If mono: fake stereo
150 if(((af_data_t
*)arg
)->nch
== 1){
151 s
->nr
= min(af
->data
->nch
,2);
152 for(i
=0;i
<s
->nr
;i
++){
158 s
->nr
= min(af
->data
->nch
, ((af_data_t
*)arg
)->nch
);
159 for(i
=0;i
<s
->nr
;i
++){
166 af
->data
->rate
= ((af_data_t
*)arg
)->rate
;
167 af
->data
->format
= ((af_data_t
*)arg
)->format
;
168 af
->data
->bps
= ((af_data_t
*)arg
)->bps
;
169 af
->mul
= (double)af
->data
->nch
/ ((af_data_t
*)arg
)->nch
;
170 return check_routes(s
,((af_data_t
*)arg
)->nch
,af
->data
->nch
);
171 case AF_CONTROL_COMMAND_LINE
:{
174 // Check number of channels and number of routing pairs
175 sscanf(arg
, "%i:%i%n", &nch
, &s
->nr
, &n
);
177 // If router scan commandline for routing pairs
179 char* cp
= &((char*)arg
)[n
];
182 if((s
->nr
< 1) || (s
->nr
> AF_NCH
)){
183 af_msg(AF_MSG_ERROR
,"[channels] The number of routing pairs must be"
184 " between 1 and %i. Current value is %i\n",AF_NCH
,s
->nr
);
187 // Scan for pairs on commandline
188 while((*cp
== ':') && (ch
< s
->nr
)){
189 sscanf(cp
, ":%i:%i%n" ,&s
->route
[ch
][FR
], &s
->route
[ch
][TO
], &n
);
190 af_msg(AF_MSG_VERBOSE
,"[channels] Routing from channel %i to"
191 " channel %i\n",s
->route
[ch
][FR
],s
->route
[ch
][TO
]);
197 if(AF_OK
!= af
->control(af
,AF_CONTROL_CHANNELS
| AF_CONTROL_SET
,&nch
))
201 case AF_CONTROL_CHANNELS
| AF_CONTROL_SET
:
202 // Reinit must be called after this function has been called
205 if(((int*)arg
)[0] <= 0 || ((int*)arg
)[0] > AF_NCH
){
206 af_msg(AF_MSG_ERROR
,"[channels] The number of output channels must be"
207 " between 1 and %i. Current value is %i\n",AF_NCH
,((int*)arg
)[0]);
211 af
->data
->nch
=((int*)arg
)[0];
213 af_msg(AF_MSG_VERBOSE
,"[channels] Changing number of channels"
214 " to %i\n",af
->data
->nch
);
216 case AF_CONTROL_CHANNELS
| AF_CONTROL_GET
:
217 *(int*)arg
= af
->data
->nch
;
219 case AF_CONTROL_CHANNELS_ROUTING
| AF_CONTROL_SET
:{
220 int ch
= ((af_control_ext_t
*)arg
)->ch
;
221 int* route
= ((af_control_ext_t
*)arg
)->arg
;
222 s
->route
[ch
][FR
] = route
[FR
];
223 s
->route
[ch
][TO
] = route
[TO
];
226 case AF_CONTROL_CHANNELS_ROUTING
| AF_CONTROL_GET
:{
227 int ch
= ((af_control_ext_t
*)arg
)->ch
;
228 int* route
= ((af_control_ext_t
*)arg
)->arg
;
229 route
[FR
] = s
->route
[ch
][FR
];
230 route
[TO
] = s
->route
[ch
][TO
];
233 case AF_CONTROL_CHANNELS_NR
| AF_CONTROL_SET
:
236 case AF_CONTROL_CHANNELS_NR
| AF_CONTROL_GET
:
239 case AF_CONTROL_CHANNELS_ROUTER
| AF_CONTROL_SET
:
240 s
->router
= *(int*)arg
;
242 case AF_CONTROL_CHANNELS_ROUTER
| AF_CONTROL_GET
:
243 *(int*)arg
= s
->router
;
250 static void uninit(struct af_instance_s
* af
)
254 free(af
->data
->audio
);
258 // Filter data through filter
259 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
261 af_data_t
* c
= data
; // Current working data
262 af_data_t
* l
= af
->data
; // Local data
263 af_channels_t
* s
= af
->setup
;
266 if(AF_OK
!= RESIZE_LOCAL_BUFFER(af
,data
))
269 // Reset unused channels
270 memset(l
->audio
,0,c
->len
/ c
->nch
* l
->nch
);
272 if(AF_OK
== check_routes(s
,c
->nch
,l
->nch
))
274 copy(c
->audio
,l
->audio
,c
->nch
,s
->route
[i
][FR
],
275 l
->nch
,s
->route
[i
][TO
],c
->len
,c
->bps
);
279 c
->len
= c
->len
/ c
->nch
* l
->nch
;
285 // Allocate memory and set function pointers
286 static int af_open(af_instance_t
* af
){
291 af
->data
=calloc(1,sizeof(af_data_t
));
292 af
->setup
=calloc(1,sizeof(af_channels_t
));
293 if((af
->data
== NULL
) || (af
->setup
== NULL
))
298 // Description of this filter
299 af_info_t af_info_channels
= {
300 "Insert or remove channels",