Mercurial > mplayer.hg
annotate libaf/af_format.c @ 34312:d2a41814c879
Fix OSD time and e.g. frame number displayed with osd_fractions
getting out of sync by using the same source for both.
Patch by Roger Pack [rogerdpack2 gmail com].
author | reimar |
---|---|
date | Mon, 05 Dec 2011 18:27:40 +0000 |
parents | a93891202051 |
children | c2b5fda66143 |
rev | line source |
---|---|
28229
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
1 /* |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
2 * This audio filter changes the format of a data block. Valid |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
3 * formats are: AFMT_U8, AFMT_S8, AFMT_S16_LE, AFMT_S16_BE |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
4 * AFMT_U16_LE, AFMT_U16_BE, AFMT_S32_LE and AFMT_S32_BE. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
5 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
6 * This file is part of MPlayer. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
7 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
8 * MPlayer is free software; you can redistribute it and/or modify |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
11 * (at your option) any later version. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
12 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
13 * MPlayer is distributed in the hope that it will be useful, |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
16 * GNU General Public License for more details. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
17 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
18 * You should have received a copy of the GNU General Public License along |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
19 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
21 */ |
7568 | 22 |
23 #include <stdio.h> | |
24 #include <stdlib.h> | |
25 #include <string.h> | |
26 #include <inttypes.h> | |
27 #include <limits.h> | |
28337
34b7297904ac
Drop HAVE_LRINTF check, lrintf is used without checking in other places.
diego
parents:
28333
diff
changeset
|
28 #include <math.h> |
7568 | 29 |
28333
0ec2ac66f064
Fix build: Add required header and adjust preprocessor check.
diego
parents:
28238
diff
changeset
|
30 #include "config.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
|
31 #include "af.h" |
34174
a93891202051
Add missing mp_msg.h #includes, remove some unnecessary ones.
diego
parents:
33736
diff
changeset
|
32 #include "mp_msg.h" |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
33 #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
|
34 #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
|
35 |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
36 #include "libavutil/avutil.h" |
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
37 |
8167 | 38 /* Functions used by play to convert the input audio to the correct |
39 format */ | |
7568 | 40 |
24561 | 41 /* The below includes retrieves functions for converting to and from |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
42 ulaw and alaw */ |
28238
1bf9023840f9
Rename libaf/af_format_alaw.c --> libaf/af_format_alaw.h and
diego
parents:
28236
diff
changeset
|
43 #include "af_format_ulaw.h" |
1bf9023840f9
Rename libaf/af_format_alaw.c --> libaf/af_format_alaw.h and
diego
parents:
28236
diff
changeset
|
44 #include "af_format_alaw.h" |
7568 | 45 |
24561 | 46 // Switch endianness |
8167 | 47 static void endian(void* in, void* out, int len, int bps); |
24561 | 48 // From signed to unsigned and the other way |
16664 | 49 static void si2us(void* data, int len, int bps); |
8167 | 50 // Change the number of bits per sample |
51 static void change_bps(void* in, void* out, int len, int inbps, int outbps); | |
52 // 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
|
53 static void float2int(float* in, void* out, int len, int bps); |
8167 | 54 // 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
|
55 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
|
56 |
14272 | 57 static af_data_t* play(struct af_instance_s* af, af_data_t* data); |
58 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data); | |
59 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data); | |
60 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data); | |
61 | |
8607 | 62 // Helper functions to check sanity for input arguments |
63 | |
64 // 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
|
65 static int check_bps(int bps) |
8607 | 66 { |
12478 | 67 if(bps != 4 && bps != 3 && bps != 2 && bps != 1){ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
68 mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] The number of bytes per sample" |
12478 | 69 " must be 1, 2, 3 or 4. Current value is %i \n",bps); |
8607 | 70 return AF_ERROR; |
71 } | |
72 return AF_OK; | |
73 } | |
74 | |
75 // Check for unsupported formats | |
13989
dcb6b4a33aaa
declare check_format and check_bps static, they are used nowhere else.
reimar
parents:
12486
diff
changeset
|
76 static int check_format(int format) |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
77 { |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
78 char buf[256]; |
8607 | 79 switch(format & AF_FORMAT_SPECIAL_MASK){ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
80 case(AF_FORMAT_IMA_ADPCM): |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
81 case(AF_FORMAT_MPEG2): |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
82 case(AF_FORMAT_AC3): |
29049 | 83 mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] Sample format %s not yet supported \n", |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
84 af_fmt2str(format,buf,256)); |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
85 return AF_ERROR; |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
86 } |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
87 return AF_OK; |
8607 | 88 } |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
89 |
7568 | 90 // Initialization and runtime control |
91 static int control(struct af_instance_s* af, int cmd, void* arg) | |
92 { | |
93 switch(cmd){ | |
8167 | 94 case AF_CONTROL_REINIT:{ |
95 char buf1[256]; | |
96 char buf2[256]; | |
14272 | 97 af_data_t *data = arg; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
98 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
99 // Make sure this filter isn't redundant |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
100 if(af->data->format == data->format && |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
101 af->data->bps == data->bps) |
7568 | 102 return AF_DETACH; |
8607 | 103 |
30241
02b9c1a452e1
Add support for distinguishing between little- and big-endian SPDIF AC3
reimar
parents:
29401
diff
changeset
|
104 // Allow trivial AC3-endianness conversion |
02b9c1a452e1
Add support for distinguishing between little- and big-endian SPDIF AC3
reimar
parents:
29401
diff
changeset
|
105 if (!AF_FORMAT_IS_AC3(af->data->format) || !AF_FORMAT_IS_AC3(data->format)) |
24521 | 106 // Check for errors in configuration |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
107 if((AF_OK != check_bps(data->bps)) || |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
108 (AF_OK != check_format(data->format)) || |
8607 | 109 (AF_OK != check_bps(af->data->bps)) || |
110 (AF_OK != check_format(af->data->format))) | |
8167 | 111 return AF_ERROR; |
112 | |
29049 | 113 mp_msg(MSGT_AFILTER, MSGL_V, "[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
|
114 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
|
115 af_fmt2str(af->data->format,buf2,256)); |
7568 | 116 |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
117 af->data->rate = data->rate; |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
118 af->data->nch = data->nch; |
24888 | 119 af->mul = (double)af->data->bps / data->bps; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
120 |
14272 | 121 af->play = play; // set default |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
122 |
24561 | 123 // look whether only endianness differences are there |
14272 | 124 if ((af->data->format & ~AF_FORMAT_END_MASK) == |
125 (data->format & ~AF_FORMAT_END_MASK)) | |
126 { | |
29049 | 127 mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated endianness conversion only\n"); |
14272 | 128 af->play = play_swapendian; |
129 } | |
130 if ((data->format == AF_FORMAT_FLOAT_NE) && | |
131 (af->data->format == AF_FORMAT_S16_NE)) | |
132 { | |
29049 | 133 mp_msg(MSGT_AFILTER, MSGL_V, "[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_float_s16; |
137 } | |
138 if ((data->format == AF_FORMAT_S16_NE) && | |
139 (af->data->format == AF_FORMAT_FLOAT_NE)) | |
140 { | |
29049 | 141 mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated %s to %s conversion\n", |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
142 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
|
143 af_fmt2str(af->data->format,buf2,256)); |
14272 | 144 af->play = play_s16_float; |
145 } | |
7568 | 146 return AF_OK; |
8167 | 147 } |
7998
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
148 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
|
149 int format = af_str2fmt_short(arg); |
15311 | 150 if (format == -1) { |
29049 | 151 mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] %s is not a valid format\n", (char *)arg); |
15311 | 152 return AF_ERROR; |
153 } | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
154 if(AF_OK != af->control(af,AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET,&format)) |
8607 | 155 return AF_ERROR; |
156 return AF_OK; | |
8167 | 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 case AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET:{ |
24561 | 159 // Check for errors in configuration |
30241
02b9c1a452e1
Add support for distinguishing between little- and big-endian SPDIF AC3
reimar
parents:
29401
diff
changeset
|
160 if(!AF_FORMAT_IS_AC3(*(int*)arg) && AF_OK != check_format(*(int*)arg)) |
8607 | 161 return AF_ERROR; |
162 | |
163 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
|
164 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
|
165 |
7568 | 166 return AF_OK; |
167 } | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
168 } |
7568 | 169 return AF_UNKNOWN; |
170 } | |
171 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
172 // Deallocate memory |
7568 | 173 static void uninit(struct af_instance_s* af) |
174 { | |
22179 | 175 if (af->data) |
176 free(af->data->audio); | |
177 free(af->data); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
178 af->setup = 0; |
7568 | 179 } |
180 | |
14272 | 181 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data) |
182 { | |
183 af_data_t* l = af->data; // Local data | |
184 af_data_t* c = data; // Current working data | |
24561 | 185 int len = c->len/c->bps; // Length in samples of current audio block |
14272 | 186 |
187 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
188 return NULL; | |
189 | |
190 endian(c->audio,l->audio,len,c->bps); | |
191 | |
192 c->audio = l->audio; | |
193 c->format = l->format; | |
194 | |
195 return c; | |
196 } | |
197 | |
198 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data) | |
199 { | |
200 af_data_t* l = af->data; // Local data | |
201 af_data_t* c = data; // Current working data | |
24561 | 202 int len = c->len/4; // Length in samples of current audio block |
14272 | 203 |
204 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
205 return NULL; | |
206 | |
207 float2int(c->audio, l->audio, len, 2); | |
208 | |
209 c->audio = l->audio; | |
210 c->len = len*2; | |
211 c->bps = 2; | |
212 c->format = l->format; | |
213 | |
214 return c; | |
215 } | |
216 | |
217 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data) | |
218 { | |
219 af_data_t* l = af->data; // Local data | |
220 af_data_t* c = data; // Current working data | |
24561 | 221 int len = c->len/2; // Length in samples of current audio block |
14272 | 222 |
223 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
224 return NULL; | |
225 | |
226 int2float(c->audio, l->audio, len, 2); | |
227 | |
228 c->audio = l->audio; | |
229 c->len = len*4; | |
230 c->bps = 4; | |
231 c->format = l->format; | |
232 | |
233 return c; | |
234 } | |
235 | |
7568 | 236 // Filter data through filter |
237 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
238 { | |
8167 | 239 af_data_t* l = af->data; // Local data |
240 af_data_t* c = data; // Current working data | |
24561 | 241 int len = c->len/c->bps; // Length in samples of current audio block |
7568 | 242 |
243 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
244 return NULL; | |
245 | |
8167 | 246 // Change to cpu native endian format |
247 if((c->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) | |
248 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
|
249 |
8167 | 250 // Conversion table |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
251 if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_MU_LAW) { |
8167 | 252 from_ulaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
253 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
254 to_ulaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
255 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
16664 | 256 si2us(l->audio,len,l->bps); |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
257 } else if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_A_LAW) { |
8167 | 258 from_alaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
259 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
260 to_alaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
261 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
16664 | 262 si2us(l->audio,len,l->bps); |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
263 } else if((c->format & AF_FORMAT_POINT_MASK) == AF_FORMAT_F) { |
8167 | 264 switch(l->format&AF_FORMAT_SPECIAL_MASK){ |
265 case(AF_FORMAT_MU_LAW): | |
266 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
267 break; | |
268 case(AF_FORMAT_A_LAW): | |
269 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
7568 | 270 break; |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
271 default: |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
272 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
|
273 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) |
16664 | 274 si2us(l->audio,len,l->bps); |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
275 break; |
8167 | 276 } |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
277 } else { |
8167 | 278 // Input must be int |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
279 |
8167 | 280 // Change signed/unsigned |
281 if((c->format&AF_FORMAT_SIGN_MASK) != (l->format&AF_FORMAT_SIGN_MASK)){ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
282 si2us(c->audio,len,c->bps); |
8167 | 283 } |
284 // Convert to special formats | |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
285 switch(l->format&(AF_FORMAT_SPECIAL_MASK|AF_FORMAT_POINT_MASK)){ |
8167 | 286 case(AF_FORMAT_MU_LAW): |
287 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
288 break; | |
289 case(AF_FORMAT_A_LAW): | |
290 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
291 break; | |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
292 case(AF_FORMAT_F): |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
293 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
|
294 break; |
8167 | 295 default: |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
296 // Change the number of bits |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
297 if(c->bps != l->bps) |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
298 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
|
299 else |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
22748
diff
changeset
|
300 fast_memcpy(l->audio,c->audio,len*c->bps); |
7568 | 301 break; |
302 } | |
303 } | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
304 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
305 // Switch from cpu native endian to the correct endianness |
8167 | 306 if((l->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) |
307 endian(l->audio,l->audio,len,l->bps); | |
7568 | 308 |
309 // Set output data | |
310 c->audio = l->audio; | |
8167 | 311 c->len = len*l->bps; |
7568 | 312 c->bps = l->bps; |
313 c->format = l->format; | |
314 return c; | |
315 } | |
316 | |
317 // 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
|
318 static int af_open(af_instance_t* af){ |
7568 | 319 af->control=control; |
320 af->uninit=uninit; | |
321 af->play=play; | |
24888 | 322 af->mul=1; |
7568 | 323 af->data=calloc(1,sizeof(af_data_t)); |
324 if(af->data == NULL) | |
325 return AF_ERROR; | |
326 return AF_OK; | |
327 } | |
328 | |
329 // Description of this filter | |
330 af_info_t af_info_format = { | |
331 "Sample format conversion", | |
332 "format", | |
333 "Anders", | |
334 "", | |
7615 | 335 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
|
336 af_open |
7568 | 337 }; |
8167 | 338 |
12478 | 339 static inline uint32_t load24bit(void* data, int pos) { |
29401
f01023c524c3
Replace WORDS_BIGENDIAN by HAVE_BIGENDIAN in all internal code.
diego
parents:
29263
diff
changeset
|
340 #if HAVE_BIGENDIAN |
12478 | 341 return (((uint32_t)((uint8_t*)data)[3*pos])<<24) | |
342 (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) | | |
343 (((uint32_t)((uint8_t*)data)[3*pos+2])<<8); | |
344 #else | |
345 return (((uint32_t)((uint8_t*)data)[3*pos])<<8) | | |
346 (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) | | |
347 (((uint32_t)((uint8_t*)data)[3*pos+2])<<24); | |
348 #endif | |
349 } | |
350 | |
351 static inline void store24bit(void* data, int pos, uint32_t expanded_value) { | |
29401
f01023c524c3
Replace WORDS_BIGENDIAN by HAVE_BIGENDIAN in all internal code.
diego
parents:
29263
diff
changeset
|
352 #if HAVE_BIGENDIAN |
12478 | 353 ((uint8_t*)data)[3*pos]=expanded_value>>24; |
354 ((uint8_t*)data)[3*pos+1]=expanded_value>>16; | |
355 ((uint8_t*)data)[3*pos+2]=expanded_value>>8; | |
356 #else | |
357 ((uint8_t*)data)[3*pos]=expanded_value>>8; | |
358 ((uint8_t*)data)[3*pos+1]=expanded_value>>16; | |
359 ((uint8_t*)data)[3*pos+2]=expanded_value>>24; | |
360 #endif | |
361 } | |
362 | |
8167 | 363 // Function implementations used by play |
364 static void endian(void* in, void* out, int len, int bps) | |
365 { | |
366 register int i; | |
367 switch(bps){ | |
368 case(2):{ | |
369 for(i=0;i<len;i++){ | |
12486 | 370 ((uint16_t*)out)[i]=bswap_16(((uint16_t*)in)[i]); |
8167 | 371 } |
372 break; | |
373 } | |
12478 | 374 case(3):{ |
375 register uint8_t s; | |
376 for(i=0;i<len;i++){ | |
377 s=((uint8_t*)in)[3*i]; | |
378 ((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
|
379 if (in != out) |
dbbc25ea6403
fix endian conversion for (curently unused) case where in buffer != out buffer
reimar
parents:
12478
diff
changeset
|
380 ((uint8_t*)out)[3*i+1]=((uint8_t*)in)[3*i+1]; |
12478 | 381 ((uint8_t*)out)[3*i+2]=s; |
382 } | |
383 break; | |
384 } | |
8167 | 385 case(4):{ |
386 for(i=0;i<len;i++){ | |
12486 | 387 ((uint32_t*)out)[i]=bswap_32(((uint32_t*)in)[i]); |
8167 | 388 } |
389 break; | |
390 } | |
391 } | |
392 } | |
393 | |
16664 | 394 static void si2us(void* data, int len, int bps) |
8167 | 395 { |
16664 | 396 register long i = -(len * bps); |
397 register uint8_t *p = &((uint8_t *)data)[len * bps]; | |
398 #if AF_FORMAT_NE == AF_FORMAT_LE | |
399 p += bps - 1; | |
400 #endif | |
401 if (len <= 0) return; | |
402 do { | |
403 p[i] ^= 0x80; | |
404 } while (i += bps); | |
8167 | 405 } |
406 | |
407 static void change_bps(void* in, void* out, int len, int inbps, int outbps) | |
408 { | |
409 register int i; | |
410 switch(inbps){ | |
411 case(1): | |
412 switch(outbps){ | |
413 case(2): | |
414 for(i=0;i<len;i++) | |
415 ((uint16_t*)out)[i]=((uint16_t)((uint8_t*)in)[i])<<8; | |
416 break; | |
12478 | 417 case(3): |
418 for(i=0;i<len;i++) | |
419 store24bit(out, i, ((uint32_t)((uint8_t*)in)[i])<<24); | |
420 break; | |
8167 | 421 case(4): |
422 for(i=0;i<len;i++) | |
423 ((uint32_t*)out)[i]=((uint32_t)((uint8_t*)in)[i])<<24; | |
424 break; | |
425 } | |
426 break; | |
427 case(2): | |
428 switch(outbps){ | |
429 case(1): | |
430 for(i=0;i<len;i++) | |
431 ((uint8_t*)out)[i]=(uint8_t)((((uint16_t*)in)[i])>>8); | |
432 break; | |
12478 | 433 case(3): |
434 for(i=0;i<len;i++) | |
435 store24bit(out, i, ((uint32_t)((uint16_t*)in)[i])<<16); | |
436 break; | |
8167 | 437 case(4): |
438 for(i=0;i<len;i++) | |
439 ((uint32_t*)out)[i]=((uint32_t)((uint16_t*)in)[i])<<16; | |
440 break; | |
441 } | |
442 break; | |
12478 | 443 case(3): |
444 switch(outbps){ | |
445 case(1): | |
446 for(i=0;i<len;i++) | |
447 ((uint8_t*)out)[i]=(uint8_t)(load24bit(in, i)>>24); | |
448 break; | |
449 case(2): | |
450 for(i=0;i<len;i++) | |
451 ((uint16_t*)out)[i]=(uint16_t)(load24bit(in, i)>>16); | |
452 break; | |
453 case(4): | |
454 for(i=0;i<len;i++) | |
455 ((uint32_t*)out)[i]=(uint32_t)load24bit(in, i); | |
456 break; | |
457 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
458 break; |
8167 | 459 case(4): |
460 switch(outbps){ | |
461 case(1): | |
462 for(i=0;i<len;i++) | |
463 ((uint8_t*)out)[i]=(uint8_t)((((uint32_t*)in)[i])>>24); | |
464 break; | |
465 case(2): | |
466 for(i=0;i<len;i++) | |
467 ((uint16_t*)out)[i]=(uint16_t)((((uint32_t*)in)[i])>>16); | |
468 break; | |
12478 | 469 case(3): |
470 for(i=0;i<len;i++) | |
471 store24bit(out, i, ((uint32_t*)in)[i]); | |
472 break; | |
8167 | 473 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
474 break; |
8167 | 475 } |
476 } | |
477 | |
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 static void float2int(float* in, void* out, int len, int bps) |
8167 | 479 { |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
480 float f; |
8167 | 481 register int i; |
482 switch(bps){ | |
483 case(1): | |
484 for(i=0;i<len;i++) | |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
485 ((int8_t *)out)[i] = av_clip_int8(lrintf(128.0 * in[i])); |
8167 | 486 break; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
487 case(2): |
8167 | 488 for(i=0;i<len;i++) |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
489 ((int16_t*)out)[i] = av_clip_int16(lrintf(32768.0 * in[i])); |
8167 | 490 break; |
12478 | 491 case(3): |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
492 for(i=0;i<len;i++){ |
33736
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
493 f = in[i] * 8388608; |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
494 store24bit(out, i, av_clip(lrintf(f), -1*(1<<23), (1<<23)-1) << 8); |
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
495 } |
12478 | 496 break; |
8167 | 497 case(4): |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
498 for(i=0;i<len;i++){ |
33736
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
499 f = in[i]; |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
500 if (f <= -1.0) |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
501 ((int32_t*)out)[i] = INT_MIN; |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
502 else |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
503 if (f >= 1.0)//no need to use corrected constant, rounding won't cause overflow |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
504 ((int32_t*)out)[i] = INT_MAX; |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
505 else |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
506 ((int32_t*)out)[i] = lrintf(f*2147483648.0); |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
507 |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
508 } |
8167 | 509 break; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
510 } |
8167 | 511 } |
512 | |
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
|
513 static void int2float(void* in, float* out, int len, int bps) |
8167 | 514 { |
515 register int i; | |
516 switch(bps){ | |
517 case(1): | |
518 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
|
519 out[i]=(1.0/128.0)*((int8_t*)in)[i]; |
8167 | 520 break; |
521 case(2): | |
522 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
|
523 out[i]=(1.0/32768.0)*((int16_t*)in)[i]; |
8167 | 524 break; |
12478 | 525 case(3): |
526 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
|
527 out[i]=(1.0/2147483648.0)*((int32_t)load24bit(in, i)); |
12478 | 528 break; |
8167 | 529 case(4): |
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/2147483648.0)*((int32_t*)in)[i]; |
8167 | 532 break; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
533 } |
8167 | 534 } |