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