Mercurial > mplayer.hg
annotate libaf/af_channels.c @ 8154:3dd948f5d012
size optim
author | pontscho |
---|---|
date | Mon, 11 Nov 2002 18:31:13 +0000 |
parents | d48a06d07afb |
children | e8832e66babd |
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 "../config.h" | |
12 #include "../mp_msg.h" | |
13 | |
14 #include "af.h" | |
15 | |
16 // Local function for copying data | |
17 void copy(void* in, void* out, int ins, int inos,int outs, int outos, int len, int bps) | |
18 { | |
19 switch(bps){ | |
20 case 1:{ | |
21 int8_t* tin = (int8_t*)in; | |
22 int8_t* tout = (int8_t*)out; | |
23 tin += inos; | |
24 tout += outos; | |
25 len = len/ins; | |
26 while(len--){ | |
27 *tout=*tin; | |
28 tin +=ins; | |
29 tout+=outs; | |
30 } | |
31 break; | |
32 } | |
33 case 2:{ | |
34 int16_t* tin = (int16_t*)in; | |
35 int16_t* tout = (int16_t*)out; | |
36 tin += inos; | |
37 tout += outos; | |
38 len = len/(2*ins); | |
39 while(len--){ | |
40 *tout=*tin; | |
41 tin +=ins; | |
42 tout+=outs; | |
43 } | |
44 break; | |
45 } | |
46 case 4:{ | |
47 int32_t* tin = (int32_t*)in; | |
48 int32_t* tout = (int32_t*)out; | |
49 tin += inos; | |
50 tout += outos; | |
51 len = len/(4*ins); | |
52 while(len--){ | |
53 *tout=*tin; | |
54 tin +=ins; | |
55 tout+=outs; | |
56 } | |
57 break; | |
58 } | |
59 case 8:{ | |
60 int64_t* tin = (int64_t*)in; | |
61 int64_t* tout = (int64_t*)out; | |
62 tin += inos; | |
63 tout += outos; | |
64 len = len/(8*ins); | |
65 while(len--){ | |
66 *tout=*tin; | |
67 tin +=ins; | |
68 tout+=outs; | |
69 } | |
70 break; | |
71 } | |
72 default: | |
73 mp_msg(MSGT_AFILTER,MSGL_ERR,"[channels] Unsupported number of bytes/sample: %i please report this error on the MPlayer mailing list. \n",bps); | |
74 } | |
75 } | |
76 | |
77 // Initialization and runtime control | |
78 static int control(struct af_instance_s* af, int cmd, void* arg) | |
79 { | |
80 switch(cmd){ | |
81 case AF_CONTROL_REINIT: | |
82 // Make sure this filter isn't redundant | |
83 if(af->data->nch == ((af_data_t*)arg)->nch) | |
84 return AF_DETACH; | |
85 | |
86 af->data->rate = ((af_data_t*)arg)->rate; | |
87 af->data->format = ((af_data_t*)arg)->format; | |
88 af->data->bps = ((af_data_t*)arg)->bps; | |
89 af->mul.n = af->data->nch; | |
90 af->mul.d = ((af_data_t*)arg)->nch; | |
91 return AF_OK; | |
7998
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
92 case AF_CONTROL_COMMAND_LINE:{ |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
93 int nch = 0; |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
94 sscanf((char*)arg,"%i",&nch); |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
95 return af->control(af,AF_CONTROL_CHANNELS,&nch); |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
96 } |
7568 | 97 case AF_CONTROL_CHANNELS: |
98 // Reinit must be called after this function has been called | |
99 | |
100 // Sanity check | |
101 if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > 6){ | |
102 mp_msg(MSGT_AFILTER,MSGL_ERR,"[channels] The number of output channels must be between 1 and 6. Current value is%i \n",((int*)arg)[0]); | |
103 return AF_ERROR; | |
104 } | |
105 | |
106 af->data->nch=((int*)arg)[0]; | |
107 mp_msg(MSGT_AFILTER,MSGL_V,"[channels] Changing number of channels to %i\n",af->data->nch); | |
108 return AF_OK; | |
109 } | |
110 return AF_UNKNOWN; | |
111 } | |
112 | |
113 // Deallocate memory | |
114 static void uninit(struct af_instance_s* af) | |
115 { | |
116 if(af->data) | |
117 free(af->data); | |
118 } | |
119 | |
120 // Filter data through filter | |
121 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
122 { | |
123 af_data_t* c = data; // Current working data | |
124 af_data_t* l = af->data; // Local data | |
125 | |
126 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
127 return NULL; | |
128 | |
129 // Reset unused channels if nch in < nch out | |
130 if(af->mul.n > af->mul.d) | |
7590 | 131 memset(l->audio,0,(c->len*af->mul.n)/af->mul.d); |
7568 | 132 |
133 // Special case always output L & R | |
134 if(c->nch == 1){ | |
135 copy(c->audio,l->audio,1,0,l->nch,0,c->len,c->bps); | |
136 copy(c->audio,l->audio,1,0,l->nch,1,c->len,c->bps); | |
137 } | |
138 else{ | |
139 int i; | |
140 if(l->nch < c->nch){ | |
141 for(i=0;i<l->nch;i++) // Truncates R if l->nch == 1 not good need mixing | |
142 copy(c->audio,l->audio,c->nch,i,l->nch,i,c->len,c->bps); | |
143 } | |
144 else{ | |
145 for(i=0;i<c->nch;i++) | |
146 copy(c->audio,l->audio,c->nch,i,l->nch,i,c->len,c->bps); | |
147 } | |
148 } | |
149 | |
150 // Set output data | |
151 c->audio = l->audio; | |
7590 | 152 c->len = (c->len*af->mul.n)/af->mul.d; |
7568 | 153 c->nch = l->nch; |
154 | |
155 return c; | |
156 } | |
157 | |
158 // Allocate memory and set function pointers | |
159 static int open(af_instance_t* af){ | |
160 af->control=control; | |
161 af->uninit=uninit; | |
162 af->play=play; | |
163 af->mul.n=1; | |
164 af->mul.d=1; | |
165 af->data=calloc(1,sizeof(af_data_t)); | |
166 if(af->data == NULL) | |
167 return AF_ERROR; | |
168 return AF_OK; | |
169 } | |
170 | |
171 // Description of this filter | |
172 af_info_t af_info_channels = { | |
173 "Insert or remove channels", | |
174 "channels", | |
175 "Anders", | |
176 "", | |
7615 | 177 AF_FLAGS_REENTRANT, |
7568 | 178 open |
179 }; |