Mercurial > mplayer.hg
annotate libaf/af_format.c @ 17279:600d0b740940
"Currently mplayer looks for only one MP3 frame sync. The attached
patch makes it to look for two consecutive valid MP3 frame headers,
reducing the probability of false positives, which causes Bug 380.
Funny that the fix is so simple. Seems that someone has forgotten to
initialize MP3_resync correctly.
Also this is the recommended way to sync MP3 frames. See
http://www.dv.co.yu/mpgscript/mpeghdr.htm. "
Original thread:
Date: Dec 31, 2005 10:15 AM
Subject: [MPlayer-dev-eng] [PATCH] Try twice when searching for MP3 frame header, fixes Bug 380
author | gpoirier |
---|---|
date | Sat, 31 Dec 2005 18:56:35 +0000 |
parents | a9da2db9eb16 |
children | a965ca17debc |
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 <unistd.h> | |
13 #include <inttypes.h> | |
14 #include <limits.h> | |
15 | |
16 #include "af.h" | |
16982 | 17 #include "bswap.h" |
18 #include "libvo/fastmemcpy.h" | |
7568 | 19 |
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
|
20 // 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
|
21 #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
|
22 #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
|
23 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
|
24 #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
|
25 #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
|
26 #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
|
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 { | |
165 if(af->data) | |
166 free(af->data); | |
12386 | 167 af->setup = 0; |
7568 | 168 } |
169 | |
14272 | 170 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data) |
171 { | |
172 af_data_t* l = af->data; // Local data | |
173 af_data_t* c = data; // Current working data | |
174 int len = c->len/c->bps; // Lenght in samples of current audio block | |
175 | |
176 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
177 return NULL; | |
178 | |
179 endian(c->audio,l->audio,len,c->bps); | |
180 | |
181 c->audio = l->audio; | |
182 c->format = l->format; | |
183 | |
184 return c; | |
185 } | |
186 | |
187 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data) | |
188 { | |
189 af_data_t* l = af->data; // Local data | |
190 af_data_t* c = data; // Current working data | |
191 int len = c->len/4; // Lenght in samples of current audio block | |
192 | |
193 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
194 return NULL; | |
195 | |
196 float2int(c->audio, l->audio, len, 2); | |
197 | |
198 c->audio = l->audio; | |
199 c->len = len*2; | |
200 c->bps = 2; | |
201 c->format = l->format; | |
202 | |
203 return c; | |
204 } | |
205 | |
206 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data) | |
207 { | |
208 af_data_t* l = af->data; // Local data | |
209 af_data_t* c = data; // Current working data | |
210 int len = c->len/2; // Lenght in samples of current audio block | |
211 | |
212 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
213 return NULL; | |
214 | |
215 int2float(c->audio, l->audio, len, 2); | |
216 | |
217 c->audio = l->audio; | |
218 c->len = len*4; | |
219 c->bps = 4; | |
220 c->format = l->format; | |
221 | |
222 return c; | |
223 } | |
224 | |
7568 | 225 // Filter data through filter |
226 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
227 { | |
8167 | 228 af_data_t* l = af->data; // Local data |
229 af_data_t* c = data; // Current working data | |
230 int len = c->len/c->bps; // Lenght in samples of current audio block | |
7568 | 231 |
232 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
233 return NULL; | |
234 | |
8167 | 235 // Change to cpu native endian format |
236 if((c->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) | |
237 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
|
238 |
8167 | 239 // Conversion table |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
240 if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_MU_LAW) { |
8167 | 241 from_ulaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
242 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
243 to_ulaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
244 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
16664 | 245 si2us(l->audio,len,l->bps); |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
246 } else if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_A_LAW) { |
8167 | 247 from_alaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
248 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
249 to_alaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
250 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
16664 | 251 si2us(l->audio,len,l->bps); |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
252 } else if((c->format & AF_FORMAT_POINT_MASK) == AF_FORMAT_F) { |
8167 | 253 switch(l->format&AF_FORMAT_SPECIAL_MASK){ |
254 case(AF_FORMAT_MU_LAW): | |
255 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
256 break; | |
257 case(AF_FORMAT_A_LAW): | |
258 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
7568 | 259 break; |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
260 default: |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
261 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
|
262 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) |
16664 | 263 si2us(l->audio,len,l->bps); |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
264 break; |
8167 | 265 } |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
266 } else { |
8167 | 267 // Input must be int |
268 | |
269 // Change signed/unsigned | |
270 if((c->format&AF_FORMAT_SIGN_MASK) != (l->format&AF_FORMAT_SIGN_MASK)){ | |
16664 | 271 si2us(c->audio,len,c->bps); |
8167 | 272 } |
273 // Convert to special formats | |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
274 switch(l->format&(AF_FORMAT_SPECIAL_MASK|AF_FORMAT_POINT_MASK)){ |
8167 | 275 case(AF_FORMAT_MU_LAW): |
276 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
277 break; | |
278 case(AF_FORMAT_A_LAW): | |
279 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
280 break; | |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
281 case(AF_FORMAT_F): |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
282 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
|
283 break; |
8167 | 284 default: |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
285 // Change the number of bits |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
286 if(c->bps != l->bps) |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
287 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
|
288 else |
8185 | 289 memcpy(l->audio,c->audio,len*c->bps); |
7568 | 290 break; |
291 } | |
292 } | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
293 |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
294 // Switch from cpu native endian to the correct endianess |
8167 | 295 if((l->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) |
296 endian(l->audio,l->audio,len,l->bps); | |
7568 | 297 |
298 // Set output data | |
299 c->audio = l->audio; | |
8167 | 300 c->len = len*l->bps; |
7568 | 301 c->bps = l->bps; |
302 c->format = l->format; | |
303 return c; | |
304 } | |
305 | |
306 // Allocate memory and set function pointers | |
307 static int open(af_instance_t* af){ | |
308 af->control=control; | |
309 af->uninit=uninit; | |
310 af->play=play; | |
311 af->mul.n=1; | |
312 af->mul.d=1; | |
313 af->data=calloc(1,sizeof(af_data_t)); | |
314 if(af->data == NULL) | |
315 return AF_ERROR; | |
316 return AF_OK; | |
317 } | |
318 | |
319 // Description of this filter | |
320 af_info_t af_info_format = { | |
321 "Sample format conversion", | |
322 "format", | |
323 "Anders", | |
324 "", | |
7615 | 325 AF_FLAGS_REENTRANT, |
7568 | 326 open |
327 }; | |
8167 | 328 |
12478 | 329 static inline uint32_t load24bit(void* data, int pos) { |
330 #if WORDS_BIGENDIAN | |
331 return (((uint32_t)((uint8_t*)data)[3*pos])<<24) | | |
332 (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) | | |
333 (((uint32_t)((uint8_t*)data)[3*pos+2])<<8); | |
334 #else | |
335 return (((uint32_t)((uint8_t*)data)[3*pos])<<8) | | |
336 (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) | | |
337 (((uint32_t)((uint8_t*)data)[3*pos+2])<<24); | |
338 #endif | |
339 } | |
340 | |
341 static inline void store24bit(void* data, int pos, uint32_t expanded_value) { | |
342 #if WORDS_BIGENDIAN | |
343 ((uint8_t*)data)[3*pos]=expanded_value>>24; | |
344 ((uint8_t*)data)[3*pos+1]=expanded_value>>16; | |
345 ((uint8_t*)data)[3*pos+2]=expanded_value>>8; | |
346 #else | |
347 ((uint8_t*)data)[3*pos]=expanded_value>>8; | |
348 ((uint8_t*)data)[3*pos+1]=expanded_value>>16; | |
349 ((uint8_t*)data)[3*pos+2]=expanded_value>>24; | |
350 #endif | |
351 } | |
352 | |
8167 | 353 // Function implementations used by play |
354 static void endian(void* in, void* out, int len, int bps) | |
355 { | |
356 register int i; | |
357 switch(bps){ | |
358 case(2):{ | |
359 for(i=0;i<len;i++){ | |
12486 | 360 ((uint16_t*)out)[i]=bswap_16(((uint16_t*)in)[i]); |
8167 | 361 } |
362 break; | |
363 } | |
12478 | 364 case(3):{ |
365 register uint8_t s; | |
366 for(i=0;i<len;i++){ | |
367 s=((uint8_t*)in)[3*i]; | |
368 ((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
|
369 if (in != out) |
dbbc25ea6403
fix endian conversion for (curently unused) case where in buffer != out buffer
reimar
parents:
12478
diff
changeset
|
370 ((uint8_t*)out)[3*i+1]=((uint8_t*)in)[3*i+1]; |
12478 | 371 ((uint8_t*)out)[3*i+2]=s; |
372 } | |
373 break; | |
374 } | |
8167 | 375 case(4):{ |
376 for(i=0;i<len;i++){ | |
12486 | 377 ((uint32_t*)out)[i]=bswap_32(((uint32_t*)in)[i]); |
8167 | 378 } |
379 break; | |
380 } | |
381 } | |
382 } | |
383 | |
16664 | 384 static void si2us(void* data, int len, int bps) |
8167 | 385 { |
16664 | 386 register long i = -(len * bps); |
387 register uint8_t *p = &((uint8_t *)data)[len * bps]; | |
388 #if AF_FORMAT_NE == AF_FORMAT_LE | |
389 p += bps - 1; | |
390 #endif | |
391 if (len <= 0) return; | |
392 do { | |
393 p[i] ^= 0x80; | |
394 } while (i += bps); | |
8167 | 395 } |
396 | |
397 static void change_bps(void* in, void* out, int len, int inbps, int outbps) | |
398 { | |
399 register int i; | |
400 switch(inbps){ | |
401 case(1): | |
402 switch(outbps){ | |
403 case(2): | |
404 for(i=0;i<len;i++) | |
405 ((uint16_t*)out)[i]=((uint16_t)((uint8_t*)in)[i])<<8; | |
406 break; | |
12478 | 407 case(3): |
408 for(i=0;i<len;i++) | |
409 store24bit(out, i, ((uint32_t)((uint8_t*)in)[i])<<24); | |
410 break; | |
8167 | 411 case(4): |
412 for(i=0;i<len;i++) | |
413 ((uint32_t*)out)[i]=((uint32_t)((uint8_t*)in)[i])<<24; | |
414 break; | |
415 } | |
416 break; | |
417 case(2): | |
418 switch(outbps){ | |
419 case(1): | |
420 for(i=0;i<len;i++) | |
421 ((uint8_t*)out)[i]=(uint8_t)((((uint16_t*)in)[i])>>8); | |
422 break; | |
12478 | 423 case(3): |
424 for(i=0;i<len;i++) | |
425 store24bit(out, i, ((uint32_t)((uint16_t*)in)[i])<<16); | |
426 break; | |
8167 | 427 case(4): |
428 for(i=0;i<len;i++) | |
429 ((uint32_t*)out)[i]=((uint32_t)((uint16_t*)in)[i])<<16; | |
430 break; | |
431 } | |
432 break; | |
12478 | 433 case(3): |
434 switch(outbps){ | |
435 case(1): | |
436 for(i=0;i<len;i++) | |
437 ((uint8_t*)out)[i]=(uint8_t)(load24bit(in, i)>>24); | |
438 break; | |
439 case(2): | |
440 for(i=0;i<len;i++) | |
441 ((uint16_t*)out)[i]=(uint16_t)(load24bit(in, i)>>16); | |
442 break; | |
443 case(4): | |
444 for(i=0;i<len;i++) | |
445 ((uint32_t*)out)[i]=(uint32_t)load24bit(in, i); | |
446 break; | |
447 } | |
448 break; | |
8167 | 449 case(4): |
450 switch(outbps){ | |
451 case(1): | |
452 for(i=0;i<len;i++) | |
453 ((uint8_t*)out)[i]=(uint8_t)((((uint32_t*)in)[i])>>24); | |
454 break; | |
455 case(2): | |
456 for(i=0;i<len;i++) | |
457 ((uint16_t*)out)[i]=(uint16_t)((((uint32_t*)in)[i])>>16); | |
458 break; | |
12478 | 459 case(3): |
460 for(i=0;i<len;i++) | |
461 store24bit(out, i, ((uint32_t*)in)[i]); | |
462 break; | |
8167 | 463 } |
464 break; | |
465 } | |
466 } | |
467 | |
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
|
468 static void float2int(float* in, void* out, int len, int bps) |
8167 | 469 { |
470 register int i; | |
471 switch(bps){ | |
472 case(1): | |
473 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
|
474 ((int8_t*)out)[i] = lrintf(127.0 * in[i]); |
8167 | 475 break; |
476 case(2): | |
477 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
|
478 ((int16_t*)out)[i] = lrintf(32767.0 * in[i]); |
8167 | 479 break; |
12478 | 480 case(3): |
481 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
|
482 store24bit(out, i, lrintf(2147483647.0 * in[i])); |
12478 | 483 break; |
8167 | 484 case(4): |
485 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
|
486 ((int32_t*)out)[i] = lrintf(2147483647.0 * in[i]); |
8167 | 487 break; |
488 } | |
489 } | |
490 | |
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
|
491 static void int2float(void* in, float* out, int len, int bps) |
8167 | 492 { |
493 register int i; | |
494 switch(bps){ | |
495 case(1): | |
496 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
|
497 out[i]=(1.0/128.0)*((int8_t*)in)[i]; |
8167 | 498 break; |
499 case(2): | |
500 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
|
501 out[i]=(1.0/32768.0)*((int16_t*)in)[i]; |
8167 | 502 break; |
12478 | 503 case(3): |
504 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
|
505 out[i]=(1.0/2147483648.0)*((int32_t)load24bit(in, i)); |
12478 | 506 break; |
8167 | 507 case(4): |
508 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
|
509 out[i]=(1.0/2147483648.0)*((int32_t*)in)[i]; |
8167 | 510 break; |
511 } | |
512 } |