Mercurial > mplayer.hg
annotate libaf/af_format.c @ 15205:19243f85e164
nico partially fixed the bug i reported; here's the rest of the fix.
basically demux_audio was mixing data in its header buffer in a bogus
manner, whereby it could sometimes "make up" valid mpeg headers where
no such header actually occurred in the file. it should be correct now.
btw these changes also fix the bug where mplayer reports huge initial
cpu usage for sound when playing mp3 files.
author | rfelker |
---|---|
date | Sun, 17 Apr 2005 17:17:52 +0000 |
parents | df515839c8a9 |
children | b00b16a1ef05 |
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" | |
12486 | 17 #include "../bswap.h" |
14272 | 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); | |
38 // From singed to unsigned | |
39 static void si2us(void* in, void* out, int len, int bps); | |
40 // From unsinged to signed | |
41 static void us2si(void* in, void* out, int len, int bps); | |
42 // Change the number of bits per sample | |
43 static void change_bps(void* in, void* out, int len, int inbps, int outbps); | |
44 // 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
|
45 static void float2int(float* in, void* out, int len, int bps); |
8167 | 46 // 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
|
47 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
|
48 |
14272 | 49 static af_data_t* play(struct af_instance_s* af, af_data_t* data); |
50 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data); | |
51 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data); | |
52 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data); | |
53 | |
8607 | 54 // Helper functions to check sanity for input arguments |
55 | |
56 // 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
|
57 static int check_bps(int bps) |
8607 | 58 { |
12478 | 59 if(bps != 4 && bps != 3 && bps != 2 && bps != 1){ |
8607 | 60 af_msg(AF_MSG_ERROR,"[format] The number of bytes per sample" |
12478 | 61 " must be 1, 2, 3 or 4. Current value is %i \n",bps); |
8607 | 62 return AF_ERROR; |
63 } | |
64 return AF_OK; | |
65 } | |
66 | |
67 // Check for unsupported formats | |
13989
dcb6b4a33aaa
declare check_format and check_bps static, they are used nowhere else.
reimar
parents:
12486
diff
changeset
|
68 static int check_format(int format) |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
69 { |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
70 char buf[256]; |
8607 | 71 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
|
72 case(AF_FORMAT_IMA_ADPCM): |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
73 case(AF_FORMAT_MPEG2): |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
74 case(AF_FORMAT_AC3): |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
75 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
|
76 af_fmt2str(format,buf,256)); |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
77 return AF_ERROR; |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
78 } |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
79 return AF_OK; |
8607 | 80 } |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
81 |
7568 | 82 // Initialization and runtime control |
83 static int control(struct af_instance_s* af, int cmd, void* arg) | |
84 { | |
85 switch(cmd){ | |
8167 | 86 case AF_CONTROL_REINIT:{ |
87 char buf1[256]; | |
88 char buf2[256]; | |
14272 | 89 af_data_t *data = arg; |
90 | |
7568 | 91 // Make sure this filter isn't redundant |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
92 if(af->data->format == data->format && |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
93 af->data->bps == data->bps) |
7568 | 94 return AF_DETACH; |
8607 | 95 |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
96 // Check for errors in configuraton |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
97 if((AF_OK != check_bps(data->bps)) || |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
98 (AF_OK != check_format(data->format)) || |
8607 | 99 (AF_OK != check_bps(af->data->bps)) || |
100 (AF_OK != check_format(af->data->format))) | |
8167 | 101 return AF_ERROR; |
102 | |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
103 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
|
104 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
|
105 af_fmt2str(af->data->format,buf2,256)); |
7568 | 106 |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
107 af->data->rate = data->rate; |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
108 af->data->nch = data->nch; |
7568 | 109 af->mul.n = af->data->bps; |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
110 af->mul.d = data->bps; |
14433
95bb94a930a3
always cancel down fractions (frac_t) to avoid overflows and playback
reimar
parents:
14399
diff
changeset
|
111 af_frac_cancel(&af->mul); |
14272 | 112 |
113 af->play = play; // set default | |
114 | |
115 // look whether only endianess differences are there | |
116 if ((af->data->format & ~AF_FORMAT_END_MASK) == | |
117 (data->format & ~AF_FORMAT_END_MASK)) | |
118 { | |
119 af_msg(AF_MSG_VERBOSE,"[format] Accelerated endianess conversion only\n"); | |
120 af->play = play_swapendian; | |
121 } | |
122 if ((data->format == AF_FORMAT_FLOAT_NE) && | |
123 (af->data->format == AF_FORMAT_S16_NE)) | |
124 { | |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
125 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
|
126 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
|
127 af_fmt2str(af->data->format,buf2,256)); |
14272 | 128 af->play = play_float_s16; |
129 } | |
130 if ((data->format == AF_FORMAT_S16_NE) && | |
131 (af->data->format == AF_FORMAT_FLOAT_NE)) | |
132 { | |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
133 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
|
134 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
|
135 af_fmt2str(af->data->format,buf2,256)); |
14272 | 136 af->play = play_s16_float; |
137 } | |
7568 | 138 return AF_OK; |
8167 | 139 } |
7998
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
140 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
|
141 int format = af_str2fmt_short(arg); |
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
142 if(AF_OK != af->control(af,AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET,&format)) |
8607 | 143 return AF_ERROR; |
144 return AF_OK; | |
8167 | 145 } |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
146 case AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET:{ |
8607 | 147 // Check for errors in configuraton |
148 if(AF_OK != check_format(*(int*)arg)) | |
149 return AF_ERROR; | |
150 | |
151 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
|
152 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
|
153 |
7568 | 154 return AF_OK; |
155 } | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
156 } |
7568 | 157 return AF_UNKNOWN; |
158 } | |
159 | |
160 // Deallocate memory | |
161 static void uninit(struct af_instance_s* af) | |
162 { | |
163 if(af->data) | |
164 free(af->data); | |
12386 | 165 af->setup = 0; |
7568 | 166 } |
167 | |
14272 | 168 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data) |
169 { | |
170 af_data_t* l = af->data; // Local data | |
171 af_data_t* c = data; // Current working data | |
172 int len = c->len/c->bps; // Lenght in samples of current audio block | |
173 | |
174 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
175 return NULL; | |
176 | |
177 endian(c->audio,l->audio,len,c->bps); | |
178 | |
179 c->audio = l->audio; | |
180 c->format = l->format; | |
181 | |
182 return c; | |
183 } | |
184 | |
185 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data) | |
186 { | |
187 af_data_t* l = af->data; // Local data | |
188 af_data_t* c = data; // Current working data | |
189 int len = c->len/4; // Lenght in samples of current audio block | |
190 | |
191 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
192 return NULL; | |
193 | |
194 float2int(c->audio, l->audio, len, 2); | |
195 | |
196 c->audio = l->audio; | |
197 c->len = len*2; | |
198 c->bps = 2; | |
199 c->format = l->format; | |
200 | |
201 return c; | |
202 } | |
203 | |
204 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data) | |
205 { | |
206 af_data_t* l = af->data; // Local data | |
207 af_data_t* c = data; // Current working data | |
208 int len = c->len/2; // Lenght in samples of current audio block | |
209 | |
210 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
211 return NULL; | |
212 | |
213 int2float(c->audio, l->audio, len, 2); | |
214 | |
215 c->audio = l->audio; | |
216 c->len = len*4; | |
217 c->bps = 4; | |
218 c->format = l->format; | |
219 | |
220 return c; | |
221 } | |
222 | |
7568 | 223 // Filter data through filter |
224 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
225 { | |
8167 | 226 af_data_t* l = af->data; // Local data |
227 af_data_t* c = data; // Current working data | |
228 int len = c->len/c->bps; // Lenght in samples of current audio block | |
7568 | 229 |
230 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
231 return NULL; | |
232 | |
8167 | 233 // Change to cpu native endian format |
234 if((c->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) | |
235 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
|
236 |
8167 | 237 // Conversion table |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
238 if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_MU_LAW) { |
8167 | 239 from_ulaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
240 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
241 to_ulaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
242 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
243 si2us(l->audio,l->audio,len,l->bps); | |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
244 } else if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_A_LAW) { |
8167 | 245 from_alaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
246 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
247 to_alaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
248 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
249 si2us(l->audio,l->audio,len,l->bps); | |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
250 } else if((c->format & AF_FORMAT_POINT_MASK) == AF_FORMAT_F) { |
8167 | 251 switch(l->format&AF_FORMAT_SPECIAL_MASK){ |
252 case(AF_FORMAT_MU_LAW): | |
253 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
254 break; | |
255 case(AF_FORMAT_A_LAW): | |
256 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
7568 | 257 break; |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
258 default: |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
259 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
|
260 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
261 si2us(l->audio,l->audio,len,l->bps); |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
262 break; |
8167 | 263 } |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
264 } else { |
8167 | 265 // Input must be int |
266 | |
267 // Change signed/unsigned | |
268 if((c->format&AF_FORMAT_SIGN_MASK) != (l->format&AF_FORMAT_SIGN_MASK)){ | |
269 if((c->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
270 us2si(c->audio,c->audio,len,c->bps); | |
271 else | |
272 si2us(c->audio,c->audio,len,c->bps); | |
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 |
8185 | 290 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 | |
308 static int open(af_instance_t* af){ | |
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, |
7568 | 327 open |
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 | |
385 static void si2us(void* in, void* out, int len, int bps) | |
386 { | |
387 register int i; | |
388 switch(bps){ | |
389 case(1): | |
390 for(i=0;i<len;i++) | |
391 ((uint8_t*)out)[i]=(uint8_t)(SCHAR_MAX+((int)((int8_t*)in)[i])); | |
392 break; | |
393 case(2): | |
394 for(i=0;i<len;i++) | |
395 ((uint16_t*)out)[i]=(uint16_t)(SHRT_MAX+((int)((int16_t*)in)[i])); | |
396 break; | |
12478 | 397 case(3): |
398 for(i=0;i<len;i++) | |
399 store24bit(out, i, (uint32_t)(INT_MAX+(int32_t)load24bit(in, i))); | |
400 break; | |
8167 | 401 case(4): |
402 for(i=0;i<len;i++) | |
403 ((uint32_t*)out)[i]=(uint32_t)(INT_MAX+((int32_t*)in)[i]); | |
404 break; | |
405 } | |
406 } | |
407 | |
408 static void us2si(void* in, void* out, int len, int bps) | |
409 { | |
410 register int i; | |
411 switch(bps){ | |
412 case(1): | |
413 for(i=0;i<len;i++) | |
414 ((int8_t*)out)[i]=(int8_t)(SCHAR_MIN+((int)((uint8_t*)in)[i])); | |
415 break; | |
416 case(2): | |
417 for(i=0;i<len;i++) | |
418 ((int16_t*)out)[i]=(int16_t)(SHRT_MIN+((int)((uint16_t*)in)[i])); | |
419 break; | |
12478 | 420 case(3): |
421 for(i=0;i<len;i++) | |
422 store24bit(out, i, (int32_t)(INT_MIN+(uint32_t)load24bit(in, i))); | |
423 break; | |
8167 | 424 case(4): |
425 for(i=0;i<len;i++) | |
426 ((int32_t*)out)[i]=(int32_t)(INT_MIN+((uint32_t*)in)[i]); | |
427 break; | |
428 } | |
429 } | |
430 | |
431 static void change_bps(void* in, void* out, int len, int inbps, int outbps) | |
432 { | |
433 register int i; | |
434 switch(inbps){ | |
435 case(1): | |
436 switch(outbps){ | |
437 case(2): | |
438 for(i=0;i<len;i++) | |
439 ((uint16_t*)out)[i]=((uint16_t)((uint8_t*)in)[i])<<8; | |
440 break; | |
12478 | 441 case(3): |
442 for(i=0;i<len;i++) | |
443 store24bit(out, i, ((uint32_t)((uint8_t*)in)[i])<<24); | |
444 break; | |
8167 | 445 case(4): |
446 for(i=0;i<len;i++) | |
447 ((uint32_t*)out)[i]=((uint32_t)((uint8_t*)in)[i])<<24; | |
448 break; | |
449 } | |
450 break; | |
451 case(2): | |
452 switch(outbps){ | |
453 case(1): | |
454 for(i=0;i<len;i++) | |
455 ((uint8_t*)out)[i]=(uint8_t)((((uint16_t*)in)[i])>>8); | |
456 break; | |
12478 | 457 case(3): |
458 for(i=0;i<len;i++) | |
459 store24bit(out, i, ((uint32_t)((uint16_t*)in)[i])<<16); | |
460 break; | |
8167 | 461 case(4): |
462 for(i=0;i<len;i++) | |
463 ((uint32_t*)out)[i]=((uint32_t)((uint16_t*)in)[i])<<16; | |
464 break; | |
465 } | |
466 break; | |
12478 | 467 case(3): |
468 switch(outbps){ | |
469 case(1): | |
470 for(i=0;i<len;i++) | |
471 ((uint8_t*)out)[i]=(uint8_t)(load24bit(in, i)>>24); | |
472 break; | |
473 case(2): | |
474 for(i=0;i<len;i++) | |
475 ((uint16_t*)out)[i]=(uint16_t)(load24bit(in, i)>>16); | |
476 break; | |
477 case(4): | |
478 for(i=0;i<len;i++) | |
479 ((uint32_t*)out)[i]=(uint32_t)load24bit(in, i); | |
480 break; | |
481 } | |
482 break; | |
8167 | 483 case(4): |
484 switch(outbps){ | |
485 case(1): | |
486 for(i=0;i<len;i++) | |
487 ((uint8_t*)out)[i]=(uint8_t)((((uint32_t*)in)[i])>>24); | |
488 break; | |
489 case(2): | |
490 for(i=0;i<len;i++) | |
491 ((uint16_t*)out)[i]=(uint16_t)((((uint32_t*)in)[i])>>16); | |
492 break; | |
12478 | 493 case(3): |
494 for(i=0;i<len;i++) | |
495 store24bit(out, i, ((uint32_t*)in)[i]); | |
496 break; | |
8167 | 497 } |
498 break; | |
499 } | |
500 } | |
501 | |
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 static void float2int(float* in, void* out, int len, int bps) |
8167 | 503 { |
504 register int i; | |
505 switch(bps){ | |
506 case(1): | |
507 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
|
508 ((int8_t*)out)[i] = lrintf(127.0 * in[i]); |
8167 | 509 break; |
510 case(2): | |
511 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
|
512 ((int16_t*)out)[i] = lrintf(32767.0 * in[i]); |
8167 | 513 break; |
12478 | 514 case(3): |
515 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
|
516 store24bit(out, i, lrintf(2147483647.0 * in[i])); |
12478 | 517 break; |
8167 | 518 case(4): |
519 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
|
520 ((int32_t*)out)[i] = lrintf(2147483647.0 * in[i]); |
8167 | 521 break; |
522 } | |
523 } | |
524 | |
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
|
525 static void int2float(void* in, float* out, int len, int bps) |
8167 | 526 { |
527 register int i; | |
528 switch(bps){ | |
529 case(1): | |
530 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
|
531 out[i]=(1.0/128.0)*((int8_t*)in)[i]; |
8167 | 532 break; |
533 case(2): | |
534 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
|
535 out[i]=(1.0/32768.0)*((int16_t*)in)[i]; |
8167 | 536 break; |
12478 | 537 case(3): |
538 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
|
539 out[i]=(1.0/2147483648.0)*((int32_t)load24bit(in, i)); |
12478 | 540 break; |
8167 | 541 case(4): |
542 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
|
543 out[i]=(1.0/2147483648.0)*((int32_t*)in)[i]; |
8167 | 544 break; |
545 } | |
546 } |