2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
13 #include "m4af_endian.h"
14 #include "pcm_reader.h"
17 inline float pcm_i2f(int32_t n
)
27 inline double pcm_i2d(int64_t n
)
37 inline int32_t pcm_s8_to_s32(int8_t n
)
42 inline int32_t pcm_u8_to_s32(uint8_t n
)
44 return (n
<< 24) ^ 0x80000000;
47 inline int32_t pcm_s16le_to_s32(int16_t n
)
49 return m4af_ltoh16(n
) << 16;
52 inline int32_t pcm_s16be_to_s32(int16_t n
)
54 return m4af_btoh16(n
) << 16;
57 inline int32_t pcm_u16le_to_s32(uint16_t n
)
59 return (m4af_ltoh16(n
) << 16) ^ 0x80000000;
62 inline int32_t pcm_u16be_to_s32(uint16_t n
)
64 return (m4af_btoh16(n
) << 16) ^ 0x80000000;
67 inline int32_t pcm_s24le_to_s32(uint8_t *p
)
69 return p
[0]<<8 | p
[1]<<16 | p
[2]<<24;
72 inline int32_t pcm_s24be_to_s32(uint8_t *p
)
74 return p
[0]<<24 | p
[1]<<16 | p
[2]<<8;
77 inline int32_t pcm_u24le_to_s32(uint8_t *p
)
79 return pcm_s24le_to_s32(p
) ^ 0x80000000;
82 inline int32_t pcm_u24be_to_s32(uint8_t *p
)
84 return pcm_s24be_to_s32(p
) ^ 0x80000000;
87 inline int32_t pcm_s32le_to_s32(int32_t n
)
89 return m4af_ltoh32(n
);
92 inline int32_t pcm_s32be_to_s32(int32_t n
)
94 return m4af_btoh32(n
);
97 inline int32_t pcm_u32le_to_s32(int32_t n
)
99 return m4af_ltoh32(n
) ^ 0x80000000;
102 inline int32_t pcm_u32be_to_s32(int32_t n
)
104 return m4af_btoh32(n
) ^ 0x80000000;
107 inline float pcm_f32le_to_f32(int32_t n
)
109 return pcm_i2f(m4af_ltoh32(n
));
112 inline float pcm_f32be_to_f32(int32_t n
)
114 return pcm_i2f(m4af_btoh32(n
));
117 inline float pcm_f64le_to_f32(int64_t n
)
119 return pcm_i2d(m4af_ltoh64(n
));
122 inline float pcm_f64be_to_f32(int64_t n
)
124 return pcm_i2d(m4af_btoh64(n
));
128 int pcm_convert_to_native(const pcm_sample_description_t
*format
,
129 const void *input
, uint32_t nframes
,
132 #define CONVERT(type, rtype, conv) \
135 type *ip = (type *)input; \
136 for (i = 0; i < count; ++i) { \
137 ((rtype *)result)[i] = conv(ip[i]); \
141 #define CONVERT_BYTES(rtype, conv) \
143 unsigned i, bytes_per_channel; \
144 uint8_t *ip = (uint8_t *)input; \
145 bytes_per_channel = PCM_BYTES_PER_CHANNEL(format); \
146 for (i = 0; i < count; ++i) { \
147 ((rtype *)result)[i] = conv(ip); \
148 ip += bytes_per_channel; \
152 uint32_t count
= nframes
* format
->channels_per_frame
;
155 switch (PCM_BYTES_PER_CHANNEL(format
) | format
->sample_type
<<4) {
156 case 1 | PCM_TYPE_SINT
<<4:
157 CONVERT(int8_t, int32_t, pcm_s8_to_s32
); break;
158 case 1 | PCM_TYPE_UINT
<<4:
159 CONVERT(uint8_t, int32_t, pcm_u8_to_s32
); break;
160 case 2 | PCM_TYPE_SINT
<<4:
161 CONVERT(int16_t, int32_t, pcm_s16le_to_s32
); break;
162 case 2 | PCM_TYPE_UINT
<<4:
163 CONVERT(uint16_t, int32_t, pcm_u16le_to_s32
); break;
164 case 2 | PCM_TYPE_SINT_BE
<<4:
165 CONVERT(int16_t, int32_t, pcm_s16be_to_s32
); break;
166 case 2 | PCM_TYPE_UINT_BE
<<4:
167 CONVERT(int16_t, int32_t, pcm_u16be_to_s32
); break;
168 case 3 | PCM_TYPE_SINT
<<4:
169 CONVERT_BYTES(int32_t, pcm_s24le_to_s32
); break;
170 case 3 | PCM_TYPE_UINT
<<4:
171 CONVERT_BYTES(int32_t, pcm_u24le_to_s32
); break;
172 case 3 | PCM_TYPE_SINT_BE
<<4:
173 CONVERT_BYTES(int32_t, pcm_s24be_to_s32
); break;
174 case 3 | PCM_TYPE_UINT_BE
<<4:
175 CONVERT_BYTES(int32_t, pcm_u24be_to_s32
); break;
176 case 4 | PCM_TYPE_SINT
<<4:
177 CONVERT(int32_t, int32_t, pcm_s32le_to_s32
); break;
178 case 4 | PCM_TYPE_UINT
<<4:
179 CONVERT(uint32_t, int32_t, pcm_u32le_to_s32
); break;
180 case 4 | PCM_TYPE_FLOAT
<<4:
181 CONVERT(int32_t, float, pcm_f32le_to_f32
); break;
182 case 4 | PCM_TYPE_SINT_BE
<<4:
183 CONVERT(int32_t, int32_t, pcm_s32be_to_s32
); break;
184 case 4 | PCM_TYPE_UINT_BE
<<4:
185 CONVERT(uint32_t, int32_t, pcm_u32be_to_s32
); break;
186 case 4 | PCM_TYPE_FLOAT_BE
<<4:
187 CONVERT(int32_t, float, pcm_f32be_to_f32
); break;
188 case 8 | PCM_TYPE_FLOAT
<<4:
189 CONVERT(int64_t, float, pcm_f64le_to_f32
); break;
190 case 8 | PCM_TYPE_FLOAT_BE
<<4:
191 CONVERT(int64_t, float, pcm_f64be_to_f32
); break;
198 typedef struct pcm_native_converter_t
{
199 pcm_reader_vtbl_t
*vtbl
;
201 pcm_sample_description_t format
;
204 } pcm_native_converter_t
;
206 static inline pcm_reader_t
*get_source(pcm_reader_t
*reader
)
208 return ((pcm_native_converter_t
*)reader
)->src
;
212 pcm_sample_description_t
*get_format(pcm_reader_t
*reader
)
214 return &((pcm_native_converter_t
*)reader
)->format
;
217 static int64_t get_length(pcm_reader_t
*reader
)
219 return pcm_get_length(get_source(reader
));
222 static int64_t get_position(pcm_reader_t
*reader
)
224 return pcm_get_position(get_source(reader
));
227 static int read_frames(pcm_reader_t
*reader
, void *buffer
, unsigned nframes
)
229 pcm_native_converter_t
*self
= (pcm_native_converter_t
*)reader
;
230 const pcm_sample_description_t
*sfmt
= pcm_get_format(self
->src
);
231 unsigned bytes
= nframes
* sfmt
->bytes_per_frame
;
233 if (self
->capacity
< bytes
) {
234 void *p
= realloc(self
->pivot
, bytes
);
237 self
->capacity
= bytes
;
239 nframes
= pcm_read_frames(self
->src
, self
->pivot
, nframes
);
240 if (pcm_convert_to_native(sfmt
, self
->pivot
, nframes
, buffer
) < 0)
245 static void teardown(pcm_reader_t
**reader
)
247 pcm_native_converter_t
*self
= (pcm_native_converter_t
*)*reader
;
248 pcm_teardown(&self
->src
);
254 static pcm_reader_vtbl_t my_vtable
= {
255 get_format
, get_length
, get_position
, read_frames
, teardown
258 pcm_reader_t
*pcm_open_native_converter(pcm_reader_t
*reader
)
260 pcm_native_converter_t
*self
= 0;
261 pcm_sample_description_t
*fmt
;
263 if ((self
= calloc(1, sizeof(pcm_native_converter_t
))) == 0)
266 self
->vtbl
= &my_vtable
;
267 memcpy(&self
->format
, pcm_get_format(reader
), sizeof(self
->format
));
269 fmt
->sample_type
= PCM_IS_FLOAT(fmt
) ? PCM_TYPE_FLOAT
: PCM_TYPE_SINT
;
270 fmt
->bytes_per_frame
= 4 * fmt
->channels_per_frame
;
271 return (pcm_reader_t
*)self
;