Mercurial > mplayer.hg
annotate libaf/af_format.c @ 23974:30677153df21
Set lavc_context->channels before opening the codec, it is sufficient to
select the desired number of codecs for ffdca and does not break other codecs
like ffvorbis that do not (re)set the channel number during decode.
author | reimar |
---|---|
date | Wed, 01 Aug 2007 23:36:40 +0000 |
parents | a124f3abc1ec |
children | 186626edd969 |
rev | line source |
---|---|
7568 | 1 /* This audio output filter changes the format of a data block. Valid |
2 formats are: AFMT_U8, AFMT_S8, AFMT_S16_LE, AFMT_S16_BE | |
3 AFMT_U16_LE, AFMT_U16_BE, AFMT_S32_LE and AFMT_S32_BE. | |
4 */ | |
5 | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
6 // Must be defined before any libc headers are included! |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
7 #define _ISOC9X_SOURCE |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
8 |
7568 | 9 #include <stdio.h> |
10 #include <stdlib.h> | |
11 #include <string.h> | |
12 #include <inttypes.h> | |
13 #include <limits.h> | |
14 | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
15 // Integer to float conversion through lrintf() |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
16 #ifdef HAVE_LRINTF |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
17 #include <math.h> |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
18 long int lrintf(float); |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
19 #else |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
20 #define lrintf(x) ((int)(x)) |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
21 #endif |
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
22 |
21353
a965ca17debc
reordering of #include to avoid clash with math.h and quicktime/*.h, patch by Crhis Roccati<roccati@pobox.com>
nplourde
parents:
16982
diff
changeset
|
23 #include "af.h" |
21372 | 24 #include "libavutil/common.h" |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
25 #include "mpbswap.h" |
21353
a965ca17debc
reordering of #include to avoid clash with math.h and quicktime/*.h, patch by Crhis Roccati<roccati@pobox.com>
nplourde
parents:
16982
diff
changeset
|
26 #include "libvo/fastmemcpy.h" |
a965ca17debc
reordering of #include to avoid clash with math.h and quicktime/*.h, patch by Crhis Roccati<roccati@pobox.com>
nplourde
parents:
16982
diff
changeset
|
27 |
8167 | 28 /* Functions used by play to convert the input audio to the correct |
29 format */ | |
7568 | 30 |
8167 | 31 /* The below includes retrives functions for converting to and from |
32 ulaw and alaw */ | |
33 #include "af_format_ulaw.c" | |
34 #include "af_format_alaw.c" | |
7568 | 35 |
8167 | 36 // Switch endianess |
37 static void endian(void* in, void* out, int len, int bps); | |
16664 | 38 // From singed to unsigned and the other way |
39 static void si2us(void* data, int len, int bps); | |
8167 | 40 // Change the number of bits per sample |
41 static void change_bps(void* in, void* out, int len, int inbps, int outbps); | |
42 // From float to int signed | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
43 static void float2int(float* in, void* out, int len, int bps); |
8167 | 44 // From signed int to float |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
45 static void int2float(void* in, float* out, int len, int bps); |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
46 |
14272 | 47 static af_data_t* play(struct af_instance_s* af, af_data_t* data); |
48 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data); | |
49 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data); | |
50 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data); | |
51 | |
8607 | 52 // Helper functions to check sanity for input arguments |
53 | |
54 // Sanity check for bytes per sample | |
13989
dcb6b4a33aaa
declare check_format and check_bps static, they are used nowhere else.
reimar
parents:
12486
diff
changeset
|
55 static int check_bps(int bps) |
8607 | 56 { |
12478 | 57 if(bps != 4 && bps != 3 && bps != 2 && bps != 1){ |
8607 | 58 af_msg(AF_MSG_ERROR,"[format] The number of bytes per sample" |
12478 | 59 " must be 1, 2, 3 or 4. Current value is %i \n",bps); |
8607 | 60 return AF_ERROR; |
61 } | |
62 return AF_OK; | |
63 } | |
64 | |
65 // Check for unsupported formats | |
13989
dcb6b4a33aaa
declare check_format and check_bps static, they are used nowhere else.
reimar
parents:
12486
diff
changeset
|
66 static int check_format(int format) |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
67 { |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
68 char buf[256]; |
8607 | 69 switch(format & AF_FORMAT_SPECIAL_MASK){ |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
70 case(AF_FORMAT_IMA_ADPCM): |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
71 case(AF_FORMAT_MPEG2): |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
72 case(AF_FORMAT_AC3): |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
73 af_msg(AF_MSG_ERROR,"[format] Sample format %s not yet supported \n", |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
74 af_fmt2str(format,buf,256)); |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
75 return AF_ERROR; |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
76 } |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
77 return AF_OK; |
8607 | 78 } |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
79 |
7568 | 80 // Initialization and runtime control |
81 static int control(struct af_instance_s* af, int cmd, void* arg) | |
82 { | |
83 switch(cmd){ | |
8167 | 84 case AF_CONTROL_REINIT:{ |
85 char buf1[256]; | |
86 char buf2[256]; | |
14272 | 87 af_data_t *data = arg; |
88 | |
7568 | 89 // Make sure this filter isn't redundant |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
90 if(af->data->format == data->format && |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
91 af->data->bps == data->bps) |
7568 | 92 return AF_DETACH; |
8607 | 93 |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
94 // Check for errors in configuraton |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
95 if((AF_OK != check_bps(data->bps)) || |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
96 (AF_OK != check_format(data->format)) || |
8607 | 97 (AF_OK != check_bps(af->data->bps)) || |
98 (AF_OK != check_format(af->data->format))) | |
8167 | 99 return AF_ERROR; |
100 | |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
101 af_msg(AF_MSG_VERBOSE,"[format] Changing sample format from %s to %s\n", |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
102 af_fmt2str(data->format,buf1,256), |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
103 af_fmt2str(af->data->format,buf2,256)); |
7568 | 104 |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
105 af->data->rate = data->rate; |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
106 af->data->nch = data->nch; |
7568 | 107 af->mul.n = af->data->bps; |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
108 af->mul.d = data->bps; |
14433
95bb94a930a3
always cancel down fractions (frac_t) to avoid overflows and playback
reimar
parents:
14399
diff
changeset
|
109 af_frac_cancel(&af->mul); |
14272 | 110 |
111 af->play = play; // set default | |
112 | |
113 // look whether only endianess differences are there | |
114 if ((af->data->format & ~AF_FORMAT_END_MASK) == | |
115 (data->format & ~AF_FORMAT_END_MASK)) | |
116 { | |
117 af_msg(AF_MSG_VERBOSE,"[format] Accelerated endianess conversion only\n"); | |
118 af->play = play_swapendian; | |
119 } | |
120 if ((data->format == AF_FORMAT_FLOAT_NE) && | |
121 (af->data->format == AF_FORMAT_S16_NE)) | |
122 { | |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
123 af_msg(AF_MSG_VERBOSE,"[format] Accelerated %s to %s conversion\n", |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
124 af_fmt2str(data->format,buf1,256), |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
125 af_fmt2str(af->data->format,buf2,256)); |
14272 | 126 af->play = play_float_s16; |
127 } | |
128 if ((data->format == AF_FORMAT_S16_NE) && | |
129 (af->data->format == AF_FORMAT_FLOAT_NE)) | |
130 { | |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
131 af_msg(AF_MSG_VERBOSE,"[format] Accelerated %s to %s conversion\n", |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
132 af_fmt2str(data->format,buf1,256), |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
133 af_fmt2str(af->data->format,buf2,256)); |
14272 | 134 af->play = play_s16_float; |
135 } | |
7568 | 136 return AF_OK; |
8167 | 137 } |
7998
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
138 case AF_CONTROL_COMMAND_LINE:{ |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
139 int format = af_str2fmt_short(arg); |
15311 | 140 if (format == -1) { |
141 af_msg(AF_MSG_ERROR, "[format] %s is not a valid format\n", (char *)arg); | |
142 return AF_ERROR; | |
143 } | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
144 if(AF_OK != af->control(af,AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET,&format)) |
8607 | 145 return AF_ERROR; |
146 return AF_OK; | |
8167 | 147 } |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
148 case AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET:{ |
8607 | 149 // Check for errors in configuraton |
150 if(AF_OK != check_format(*(int*)arg)) | |
151 return AF_ERROR; | |
152 | |
153 af->data->format = *(int*)arg; | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
154 af->data->bps = af_fmt2bits(af->data->format)/8; |
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
155 |
7568 | 156 return AF_OK; |
157 } | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
158 } |
7568 | 159 return AF_UNKNOWN; |
160 } | |
161 | |
162 // Deallocate memory | |
163 static void uninit(struct af_instance_s* af) | |
164 { | |
22179 | 165 if (af->data) |
166 free(af->data->audio); | |
167 free(af->data); | |
12386 | 168 af->setup = 0; |
7568 | 169 } |
170 | |
14272 | 171 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data) |
172 { | |
173 af_data_t* l = af->data; // Local data | |
174 af_data_t* c = data; // Current working data | |
175 int len = c->len/c->bps; // Lenght in samples of current audio block | |
176 | |
177 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
178 return NULL; | |
179 | |
180 endian(c->audio,l->audio,len,c->bps); | |
181 | |
182 c->audio = l->audio; | |
183 c->format = l->format; | |
184 | |
185 return c; | |
186 } | |
187 | |
188 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data) | |
189 { | |
190 af_data_t* l = af->data; // Local data | |
191 af_data_t* c = data; // Current working data | |
192 int len = c->len/4; // Lenght in samples of current audio block | |
193 | |
194 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
195 return NULL; | |
196 | |
197 float2int(c->audio, l->audio, len, 2); | |
198 | |
199 c->audio = l->audio; | |
200 c->len = len*2; | |
201 c->bps = 2; | |
202 c->format = l->format; | |
203 | |
204 return c; | |
205 } | |
206 | |
207 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data) | |
208 { | |
209 af_data_t* l = af->data; // Local data | |
210 af_data_t* c = data; // Current working data | |
211 int len = c->len/2; // Lenght in samples of current audio block | |
212 | |
213 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
214 return NULL; | |
215 | |
216 int2float(c->audio, l->audio, len, 2); | |
217 | |
218 c->audio = l->audio; | |
219 c->len = len*4; | |
220 c->bps = 4; | |
221 c->format = l->format; | |
222 | |
223 return c; | |
224 } | |
225 | |
7568 | 226 // Filter data through filter |
227 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
228 { | |
8167 | 229 af_data_t* l = af->data; // Local data |
230 af_data_t* c = data; // Current working data | |
231 int len = c->len/c->bps; // Lenght in samples of current audio block | |
7568 | 232 |
233 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
234 return NULL; | |
235 | |
8167 | 236 // Change to cpu native endian format |
237 if((c->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) | |
238 endian(c->audio,c->audio,len,c->bps); | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
239 |
8167 | 240 // Conversion table |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
241 if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_MU_LAW) { |
8167 | 242 from_ulaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
243 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
244 to_ulaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
245 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
16664 | 246 si2us(l->audio,len,l->bps); |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
247 } else if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_A_LAW) { |
8167 | 248 from_alaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
249 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
250 to_alaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
251 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
16664 | 252 si2us(l->audio,len,l->bps); |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
253 } else if((c->format & AF_FORMAT_POINT_MASK) == AF_FORMAT_F) { |
8167 | 254 switch(l->format&AF_FORMAT_SPECIAL_MASK){ |
255 case(AF_FORMAT_MU_LAW): | |
256 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
257 break; | |
258 case(AF_FORMAT_A_LAW): | |
259 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
7568 | 260 break; |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
261 default: |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
262 float2int(c->audio, l->audio, len, l->bps); |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
263 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) |
16664 | 264 si2us(l->audio,len,l->bps); |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
265 break; |
8167 | 266 } |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
267 } else { |
8167 | 268 // Input must be int |
269 | |
270 // Change signed/unsigned | |
271 if((c->format&AF_FORMAT_SIGN_MASK) != (l->format&AF_FORMAT_SIGN_MASK)){ | |
16664 | 272 si2us(c->audio,len,c->bps); |
8167 | 273 } |
274 // Convert to special formats | |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
275 switch(l->format&(AF_FORMAT_SPECIAL_MASK|AF_FORMAT_POINT_MASK)){ |
8167 | 276 case(AF_FORMAT_MU_LAW): |
277 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
278 break; | |
279 case(AF_FORMAT_A_LAW): | |
280 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
281 break; | |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
282 case(AF_FORMAT_F): |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
283 int2float(c->audio, l->audio, len, c->bps); |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
284 break; |
8167 | 285 default: |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
286 // Change the number of bits |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
287 if(c->bps != l->bps) |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
288 change_bps(c->audio,l->audio,len,c->bps,l->bps); |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
289 else |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
22748
diff
changeset
|
290 fast_memcpy(l->audio,c->audio,len*c->bps); |
7568 | 291 break; |
292 } | |
293 } | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
294 |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
295 // Switch from cpu native endian to the correct endianess |
8167 | 296 if((l->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) |
297 endian(l->audio,l->audio,len,l->bps); | |
7568 | 298 |
299 // Set output data | |
300 c->audio = l->audio; | |
8167 | 301 c->len = len*l->bps; |
7568 | 302 c->bps = l->bps; |
303 c->format = l->format; | |
304 return c; | |
305 } | |
306 | |
307 // Allocate memory and set function pointers | |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
22179
diff
changeset
|
308 static int af_open(af_instance_t* af){ |
7568 | 309 af->control=control; |
310 af->uninit=uninit; | |
311 af->play=play; | |
312 af->mul.n=1; | |
313 af->mul.d=1; | |
314 af->data=calloc(1,sizeof(af_data_t)); | |
315 if(af->data == NULL) | |
316 return AF_ERROR; | |
317 return AF_OK; | |
318 } | |
319 | |
320 // Description of this filter | |
321 af_info_t af_info_format = { | |
322 "Sample format conversion", | |
323 "format", | |
324 "Anders", | |
325 "", | |
7615 | 326 AF_FLAGS_REENTRANT, |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
22179
diff
changeset
|
327 af_open |
7568 | 328 }; |
8167 | 329 |
12478 | 330 static inline uint32_t load24bit(void* data, int pos) { |
331 #if WORDS_BIGENDIAN | |
332 return (((uint32_t)((uint8_t*)data)[3*pos])<<24) | | |
333 (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) | | |
334 (((uint32_t)((uint8_t*)data)[3*pos+2])<<8); | |
335 #else | |
336 return (((uint32_t)((uint8_t*)data)[3*pos])<<8) | | |
337 (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) | | |
338 (((uint32_t)((uint8_t*)data)[3*pos+2])<<24); | |
339 #endif | |
340 } | |
341 | |
342 static inline void store24bit(void* data, int pos, uint32_t expanded_value) { | |
343 #if WORDS_BIGENDIAN | |
344 ((uint8_t*)data)[3*pos]=expanded_value>>24; | |
345 ((uint8_t*)data)[3*pos+1]=expanded_value>>16; | |
346 ((uint8_t*)data)[3*pos+2]=expanded_value>>8; | |
347 #else | |
348 ((uint8_t*)data)[3*pos]=expanded_value>>8; | |
349 ((uint8_t*)data)[3*pos+1]=expanded_value>>16; | |
350 ((uint8_t*)data)[3*pos+2]=expanded_value>>24; | |
351 #endif | |
352 } | |
353 | |
8167 | 354 // Function implementations used by play |
355 static void endian(void* in, void* out, int len, int bps) | |
356 { | |
357 register int i; | |
358 switch(bps){ | |
359 case(2):{ | |
360 for(i=0;i<len;i++){ | |
12486 | 361 ((uint16_t*)out)[i]=bswap_16(((uint16_t*)in)[i]); |
8167 | 362 } |
363 break; | |
364 } | |
12478 | 365 case(3):{ |
366 register uint8_t s; | |
367 for(i=0;i<len;i++){ | |
368 s=((uint8_t*)in)[3*i]; | |
369 ((uint8_t*)out)[3*i]=((uint8_t*)in)[3*i+2]; | |
12481
dbbc25ea6403
fix endian conversion for (curently unused) case where in buffer != out buffer
reimar
parents:
12478
diff
changeset
|
370 if (in != out) |
dbbc25ea6403
fix endian conversion for (curently unused) case where in buffer != out buffer
reimar
parents:
12478
diff
changeset
|
371 ((uint8_t*)out)[3*i+1]=((uint8_t*)in)[3*i+1]; |
12478 | 372 ((uint8_t*)out)[3*i+2]=s; |
373 } | |
374 break; | |
375 } | |
8167 | 376 case(4):{ |
377 for(i=0;i<len;i++){ | |
12486 | 378 ((uint32_t*)out)[i]=bswap_32(((uint32_t*)in)[i]); |
8167 | 379 } |
380 break; | |
381 } | |
382 } | |
383 } | |
384 | |
16664 | 385 static void si2us(void* data, int len, int bps) |
8167 | 386 { |
16664 | 387 register long i = -(len * bps); |
388 register uint8_t *p = &((uint8_t *)data)[len * bps]; | |
389 #if AF_FORMAT_NE == AF_FORMAT_LE | |
390 p += bps - 1; | |
391 #endif | |
392 if (len <= 0) return; | |
393 do { | |
394 p[i] ^= 0x80; | |
395 } while (i += bps); | |
8167 | 396 } |
397 | |
398 static void change_bps(void* in, void* out, int len, int inbps, int outbps) | |
399 { | |
400 register int i; | |
401 switch(inbps){ | |
402 case(1): | |
403 switch(outbps){ | |
404 case(2): | |
405 for(i=0;i<len;i++) | |
406 ((uint16_t*)out)[i]=((uint16_t)((uint8_t*)in)[i])<<8; | |
407 break; | |
12478 | 408 case(3): |
409 for(i=0;i<len;i++) | |
410 store24bit(out, i, ((uint32_t)((uint8_t*)in)[i])<<24); | |
411 break; | |
8167 | 412 case(4): |
413 for(i=0;i<len;i++) | |
414 ((uint32_t*)out)[i]=((uint32_t)((uint8_t*)in)[i])<<24; | |
415 break; | |
416 } | |
417 break; | |
418 case(2): | |
419 switch(outbps){ | |
420 case(1): | |
421 for(i=0;i<len;i++) | |
422 ((uint8_t*)out)[i]=(uint8_t)((((uint16_t*)in)[i])>>8); | |
423 break; | |
12478 | 424 case(3): |
425 for(i=0;i<len;i++) | |
426 store24bit(out, i, ((uint32_t)((uint16_t*)in)[i])<<16); | |
427 break; | |
8167 | 428 case(4): |
429 for(i=0;i<len;i++) | |
430 ((uint32_t*)out)[i]=((uint32_t)((uint16_t*)in)[i])<<16; | |
431 break; | |
432 } | |
433 break; | |
12478 | 434 case(3): |
435 switch(outbps){ | |
436 case(1): | |
437 for(i=0;i<len;i++) | |
438 ((uint8_t*)out)[i]=(uint8_t)(load24bit(in, i)>>24); | |
439 break; | |
440 case(2): | |
441 for(i=0;i<len;i++) | |
442 ((uint16_t*)out)[i]=(uint16_t)(load24bit(in, i)>>16); | |
443 break; | |
444 case(4): | |
445 for(i=0;i<len;i++) | |
446 ((uint32_t*)out)[i]=(uint32_t)load24bit(in, i); | |
447 break; | |
448 } | |
449 break; | |
8167 | 450 case(4): |
451 switch(outbps){ | |
452 case(1): | |
453 for(i=0;i<len;i++) | |
454 ((uint8_t*)out)[i]=(uint8_t)((((uint32_t*)in)[i])>>24); | |
455 break; | |
456 case(2): | |
457 for(i=0;i<len;i++) | |
458 ((uint16_t*)out)[i]=(uint16_t)((((uint32_t*)in)[i])>>16); | |
459 break; | |
12478 | 460 case(3): |
461 for(i=0;i<len;i++) | |
462 store24bit(out, i, ((uint32_t*)in)[i]); | |
463 break; | |
8167 | 464 } |
465 break; | |
466 } | |
467 } | |
468 | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
469 static void float2int(float* in, void* out, int len, int bps) |
8167 | 470 { |
471 register int i; | |
472 switch(bps){ | |
473 case(1): | |
474 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
475 ((int8_t*)out)[i] = lrintf(127.0 * in[i]); |
8167 | 476 break; |
477 case(2): | |
478 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
479 ((int16_t*)out)[i] = lrintf(32767.0 * in[i]); |
8167 | 480 break; |
12478 | 481 case(3): |
482 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
483 store24bit(out, i, lrintf(2147483647.0 * in[i])); |
12478 | 484 break; |
8167 | 485 case(4): |
486 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
487 ((int32_t*)out)[i] = lrintf(2147483647.0 * in[i]); |
8167 | 488 break; |
489 } | |
490 } | |
491 | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
492 static void int2float(void* in, float* out, int len, int bps) |
8167 | 493 { |
494 register int i; | |
495 switch(bps){ | |
496 case(1): | |
497 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
498 out[i]=(1.0/128.0)*((int8_t*)in)[i]; |
8167 | 499 break; |
500 case(2): | |
501 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
502 out[i]=(1.0/32768.0)*((int16_t*)in)[i]; |
8167 | 503 break; |
12478 | 504 case(3): |
505 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
506 out[i]=(1.0/2147483648.0)*((int32_t)load24bit(in, i)); |
12478 | 507 break; |
8167 | 508 case(4): |
509 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
510 out[i]=(1.0/2147483648.0)*((int32_t*)in)[i]; |
8167 | 511 break; |
512 } | |
513 } |