2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
13 #include "pcm_reader.h"
15 typedef struct pcm_sint16_converter_t
{
16 pcm_reader_vtbl_t
*vtbl
;
18 pcm_sample_description_t format
;
21 } pcm_sint16_converter_t
;
23 static inline pcm_reader_t
*get_source(pcm_reader_t
*reader
)
25 return ((pcm_sint16_converter_t
*)reader
)->src
;
29 pcm_sample_description_t
*get_format(pcm_reader_t
*reader
)
31 return &((pcm_sint16_converter_t
*)reader
)->format
;
34 static int64_t get_length(pcm_reader_t
*reader
)
36 return pcm_get_length(get_source(reader
));
39 static int64_t get_position(pcm_reader_t
*reader
)
41 return pcm_get_position(get_source(reader
));
44 static int read_frames(pcm_reader_t
*reader
, void *buffer
, unsigned nframes
)
47 pcm_sint16_converter_t
*self
= (pcm_sint16_converter_t
*)reader
;
48 const pcm_sample_description_t
*sfmt
= pcm_get_format(self
->src
);
49 unsigned bytes
= nframes
* sfmt
->bytes_per_frame
;
50 if (self
->capacity
< bytes
) {
51 void *p
= realloc(self
->pivot
, bytes
);
54 self
->capacity
= bytes
;
56 nframes
= pcm_read_frames(self
->src
, self
->pivot
, nframes
);
57 count
= nframes
* sfmt
->channels_per_frame
;
58 if (PCM_IS_FLOAT(sfmt
)) {
59 float *ip
= self
->pivot
;
61 for (i
= 0; i
< count
; ++i
)
62 op
[i
] = pcm_clip(ip
[i
] * 32768.0, -32768.0, 32767.0);
64 int32_t *ip
= self
->pivot
;
66 if (sfmt
->bits_per_channel
<= 16) {
67 for (i
= 0; i
< count
; ++i
)
70 for (i
= 0; i
< count
; ++i
) {
71 int n
= ((ip
[i
] >> 15) + 1) >> 1;
72 op
[i
] = (n
== 0x8000) ? 0x7fff : n
;
79 static void teardown(pcm_reader_t
**reader
)
81 pcm_sint16_converter_t
*self
= (pcm_sint16_converter_t
*)*reader
;
82 pcm_teardown(&self
->src
);
88 static pcm_reader_vtbl_t my_vtable
= {
89 get_format
, get_length
, get_position
, read_frames
, teardown
92 pcm_reader_t
*pcm_open_sint16_converter(pcm_reader_t
*reader
)
94 pcm_sint16_converter_t
*self
= 0;
95 pcm_sample_description_t
*fmt
;
97 if ((self
= calloc(1, sizeof(pcm_sint16_converter_t
))) == 0)
100 self
->vtbl
= &my_vtable
;
101 memcpy(&self
->format
, pcm_get_format(reader
), sizeof(self
->format
));
103 fmt
->bits_per_channel
= 16;
104 fmt
->sample_type
= PCM_TYPE_SINT
;
105 fmt
->bytes_per_frame
= 2 * fmt
->channels_per_frame
;
106 return (pcm_reader_t
*)self
;