Mercurial > mplayer.hg
annotate libaf/af_channels.c @ 9504:cae70d37f337
10l found by Joey Parrish <joey@nicewarrior.org>
author | alex |
---|---|
date | Tue, 25 Feb 2003 16:50:52 +0000 |
parents | 906f7a2dc085 |
children | 8631b43c9d82 |
rev | line source |
---|---|
7568 | 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. | |
4 */ | |
5 #include <stdio.h> | |
6 #include <stdlib.h> | |
7 #include <string.h> | |
7570 | 8 #include <unistd.h> |
7975 | 9 #include <inttypes.h> |
7568 | 10 |
11 #include "af.h" | |
12 | |
8607 | 13 #define FR 0 |
14 #define TO 1 | |
15 | |
16 typedef struct af_channels_s{ | |
17 int route[AF_NCH][2]; | |
18 int nr; | |
19 int router; | |
20 }af_channels_t; | |
21 | |
7568 | 22 // Local function for copying data |
8711
906f7a2dc085
sig 11 fix in reinit and resample + spelling error fixes
anders
parents:
8607
diff
changeset
|
23 static void copy(void* in, void* out, int ins, int inos,int outs, int outos, int len, int bps) |
7568 | 24 { |
25 switch(bps){ | |
26 case 1:{ | |
27 int8_t* tin = (int8_t*)in; | |
28 int8_t* tout = (int8_t*)out; | |
29 tin += inos; | |
30 tout += outos; | |
31 len = len/ins; | |
32 while(len--){ | |
33 *tout=*tin; | |
34 tin +=ins; | |
35 tout+=outs; | |
36 } | |
37 break; | |
38 } | |
39 case 2:{ | |
40 int16_t* tin = (int16_t*)in; | |
41 int16_t* tout = (int16_t*)out; | |
42 tin += inos; | |
43 tout += outos; | |
44 len = len/(2*ins); | |
45 while(len--){ | |
46 *tout=*tin; | |
47 tin +=ins; | |
48 tout+=outs; | |
49 } | |
50 break; | |
51 } | |
52 case 4:{ | |
53 int32_t* tin = (int32_t*)in; | |
54 int32_t* tout = (int32_t*)out; | |
55 tin += inos; | |
56 tout += outos; | |
57 len = len/(4*ins); | |
58 while(len--){ | |
59 *tout=*tin; | |
60 tin +=ins; | |
61 tout+=outs; | |
62 } | |
63 break; | |
64 } | |
65 case 8:{ | |
66 int64_t* tin = (int64_t*)in; | |
67 int64_t* tout = (int64_t*)out; | |
68 tin += inos; | |
69 tout += outos; | |
70 len = len/(8*ins); | |
71 while(len--){ | |
72 *tout=*tin; | |
73 tin +=ins; | |
74 tout+=outs; | |
75 } | |
76 break; | |
77 } | |
78 default: | |
8607 | 79 af_msg(AF_MSG_ERROR,"[channels] Unsupported number of bytes/sample: %i" |
80 " please report this error on the MPlayer mailing list. \n",bps); | |
7568 | 81 } |
82 } | |
83 | |
8607 | 84 // Make sure the routes are sane |
85 static int check_routes(af_channels_t* s, int nin, int nout) | |
86 { | |
87 int i; | |
88 if((s->nr < 1) || (s->nr > AF_NCH)){ | |
8711
906f7a2dc085
sig 11 fix in reinit and resample + spelling error fixes
anders
parents:
8607
diff
changeset
|
89 af_msg(AF_MSG_ERROR,"[channels] The number of routing pairs must be" |
8607 | 90 " between 1 and %i. Current value is %i\n",AF_NCH,s->nr); |
91 return AF_ERROR; | |
92 } | |
93 | |
94 for(i=0;i<s->nr;i++){ | |
95 if((s->route[i][FR] >= nin) || (s->route[i][TO] >= nout)){ | |
96 af_msg(AF_MSG_ERROR,"[channels] Invalid routing in pair nr. %i.\n", i); | |
97 return AF_ERROR; | |
98 } | |
99 } | |
100 return AF_OK; | |
101 } | |
102 | |
7568 | 103 // Initialization and runtime control |
104 static int control(struct af_instance_s* af, int cmd, void* arg) | |
105 { | |
8607 | 106 af_channels_t* s = af->setup; |
7568 | 107 switch(cmd){ |
108 case AF_CONTROL_REINIT: | |
8607 | 109 |
110 // Set default channel assignment | |
111 if(!s->router){ | |
112 int i; | |
113 // Make sure this filter isn't redundant | |
114 if(af->data->nch == ((af_data_t*)arg)->nch) | |
115 return AF_DETACH; | |
116 | |
117 // If mono: fake stereo | |
118 if(((af_data_t*)arg)->nch == 1){ | |
119 s->nr = min(af->data->nch,2); | |
120 for(i=0;i<s->nr;i++){ | |
121 s->route[i][FR] = 0; | |
122 s->route[i][TO] = i; | |
123 } | |
124 } | |
125 else{ | |
126 s->nr = min(af->data->nch, ((af_data_t*)arg)->nch); | |
127 for(i=0;i<s->nr;i++){ | |
128 s->route[i][FR] = i; | |
129 s->route[i][TO] = i; | |
130 } | |
131 } | |
132 } | |
7568 | 133 |
134 af->data->rate = ((af_data_t*)arg)->rate; | |
135 af->data->format = ((af_data_t*)arg)->format; | |
136 af->data->bps = ((af_data_t*)arg)->bps; | |
137 af->mul.n = af->data->nch; | |
138 af->mul.d = ((af_data_t*)arg)->nch; | |
8607 | 139 return check_routes(s,((af_data_t*)arg)->nch,af->data->nch); |
7998
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
140 case AF_CONTROL_COMMAND_LINE:{ |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
141 int nch = 0; |
8607 | 142 int n = 0; |
143 // Check number of channels and number of routing pairs | |
144 sscanf(arg, "%i:%i%n", &nch, &s->nr, &n); | |
145 | |
146 // If router scan commandline for routing pairs | |
147 if(s->nr){ | |
148 char* cp = &((char*)arg)[n]; | |
149 int ch = 0; | |
150 // Sanity check | |
151 if((s->nr < 1) || (s->nr > AF_NCH)){ | |
8711
906f7a2dc085
sig 11 fix in reinit and resample + spelling error fixes
anders
parents:
8607
diff
changeset
|
152 af_msg(AF_MSG_ERROR,"[channels] The number of routing pairs must be" |
8607 | 153 " between 1 and %i. Current value is %i\n",AF_NCH,s->nr); |
154 } | |
155 s->router = 1; | |
156 // Scan for pairs on commandline | |
157 while((*cp == ':') && (ch < s->nr)){ | |
158 sscanf(cp, ":%i:%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n); | |
8711
906f7a2dc085
sig 11 fix in reinit and resample + spelling error fixes
anders
parents:
8607
diff
changeset
|
159 af_msg(AF_MSG_VERBOSE,"[channels] Routing from channel %i to" |
8607 | 160 " channel %i\n",s->route[ch][FR],s->route[ch][TO]); |
161 cp = &cp[n]; | |
162 ch++; | |
163 } | |
164 } | |
165 | |
166 if(AF_OK != af->control(af,AF_CONTROL_CHANNELS | AF_CONTROL_SET ,&nch)) | |
167 return AF_ERROR; | |
168 return AF_OK; | |
169 } | |
170 case AF_CONTROL_CHANNELS | AF_CONTROL_SET: | |
7568 | 171 // Reinit must be called after this function has been called |
172 | |
173 // Sanity check | |
174 if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > 6){ | |
8607 | 175 af_msg(AF_MSG_ERROR,"[channels] The number of output channels must be" |
176 " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]); | |
7568 | 177 return AF_ERROR; |
178 } | |
179 | |
180 af->data->nch=((int*)arg)[0]; | |
8607 | 181 if(!s->router) |
182 af_msg(AF_MSG_VERBOSE,"[channels] Changing number of channels" | |
183 " to %i\n",af->data->nch); | |
184 return AF_OK; | |
185 case AF_CONTROL_CHANNELS | AF_CONTROL_GET: | |
186 *(int*)arg = af->data->nch; | |
187 return AF_OK; | |
188 case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_SET:{ | |
189 int ch = ((af_control_ext_t*)arg)->ch; | |
190 int* route = ((af_control_ext_t*)arg)->arg; | |
191 s->route[ch][FR] = route[FR]; | |
192 s->route[ch][TO] = route[TO]; | |
193 return AF_OK; | |
194 } | |
195 case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_GET:{ | |
196 int ch = ((af_control_ext_t*)arg)->ch; | |
197 int* route = ((af_control_ext_t*)arg)->arg; | |
198 route[FR] = s->route[ch][FR]; | |
199 route[TO] = s->route[ch][TO]; | |
200 return AF_OK; | |
201 } | |
202 case AF_CONTROL_CHANNELS_NR | AF_CONTROL_SET: | |
203 s->nr = *(int*)arg; | |
204 return AF_OK; | |
205 case AF_CONTROL_CHANNELS_NR | AF_CONTROL_GET: | |
206 *(int*)arg = s->nr; | |
207 return AF_OK; | |
208 case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_SET: | |
209 s->router = *(int*)arg; | |
210 return AF_OK; | |
211 case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_GET: | |
212 *(int*)arg = s->router; | |
7568 | 213 return AF_OK; |
214 } | |
215 return AF_UNKNOWN; | |
216 } | |
217 | |
218 // Deallocate memory | |
219 static void uninit(struct af_instance_s* af) | |
220 { | |
8607 | 221 if(af->setup) |
222 free(af->setup); | |
7568 | 223 if(af->data) |
224 free(af->data); | |
225 } | |
226 | |
227 // Filter data through filter | |
228 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
229 { | |
8607 | 230 af_data_t* c = data; // Current working data |
231 af_data_t* l = af->data; // Local data | |
232 af_channels_t* s = af->setup; | |
233 int i; | |
234 | |
7568 | 235 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) |
236 return NULL; | |
237 | |
8607 | 238 // Reset unused channels |
239 memset(l->audio,0,(c->len*af->mul.n)/af->mul.d); | |
7568 | 240 |
8607 | 241 if(AF_OK == check_routes(s,c->nch,l->nch)) |
242 for(i=0;i<s->nr;i++) | |
243 copy(c->audio,l->audio,c->nch,s->route[i][FR], | |
244 l->nch,s->route[i][TO],c->len,c->bps); | |
7568 | 245 |
246 // Set output data | |
247 c->audio = l->audio; | |
7590 | 248 c->len = (c->len*af->mul.n)/af->mul.d; |
7568 | 249 c->nch = l->nch; |
250 | |
251 return c; | |
252 } | |
253 | |
254 // Allocate memory and set function pointers | |
255 static int open(af_instance_t* af){ | |
256 af->control=control; | |
257 af->uninit=uninit; | |
258 af->play=play; | |
259 af->mul.n=1; | |
260 af->mul.d=1; | |
261 af->data=calloc(1,sizeof(af_data_t)); | |
8607 | 262 af->setup=calloc(1,sizeof(af_channels_t)); |
263 if((af->data == NULL) || (af->setup == NULL)) | |
7568 | 264 return AF_ERROR; |
265 return AF_OK; | |
266 } | |
267 | |
268 // Description of this filter | |
269 af_info_t af_info_channels = { | |
270 "Insert or remove channels", | |
271 "channels", | |
272 "Anders", | |
273 "", | |
7615 | 274 AF_FLAGS_REENTRANT, |
7568 | 275 open |
276 }; |