]> iEval git - fdkaac.git/blob - src/pcm_sint16_converter.c
smart padding for better gapless playback
[fdkaac.git] / src / pcm_sint16_converter.c
1 #if HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <stdlib.h>
5 #include <string.h>
6 #if HAVE_STDINT_H
7 # include <stdint.h>
8 #endif
9 #include "pcm_reader.h"
10
11 typedef struct pcm_sint16_converter_t {
12 pcm_reader_vtbl_t *vtbl;
13 pcm_reader_t *src;
14 pcm_sample_description_t format;
15 void *pivot;
16 unsigned capacity;
17 } pcm_sint16_converter_t;
18
19 static inline pcm_reader_t *get_source(pcm_reader_t *reader)
20 {
21 return ((pcm_sint16_converter_t *)reader)->src;
22 }
23
24 static const
25 pcm_sample_description_t *get_format(pcm_reader_t *reader)
26 {
27 return &((pcm_sint16_converter_t *)reader)->format;
28 }
29
30 static int64_t get_length(pcm_reader_t *reader)
31 {
32 return pcm_get_length(get_source(reader));
33 }
34
35 static int64_t get_position(pcm_reader_t *reader)
36 {
37 return pcm_get_position(get_source(reader));
38 }
39
40 static int read_frames(pcm_reader_t *reader, void *buffer, unsigned nframes)
41 {
42 pcm_sint16_converter_t *self = (pcm_sint16_converter_t *)reader;
43 const pcm_sample_description_t *sfmt = pcm_get_format(self->src);
44 unsigned bytes = nframes * sfmt->bytes_per_frame;
45
46 if (self->capacity < bytes) {
47 void *p = realloc(self->pivot, bytes);
48 if (!p) return -1;
49 self->pivot = p;
50 self->capacity = bytes;
51 }
52 nframes = pcm_read_frames(self->src, self->pivot, nframes);
53 if (pcm_convert_to_native_sint16(sfmt, self->pivot, nframes, buffer) < 0)
54 return -1;
55 return nframes;
56 }
57
58 static void teardown(pcm_reader_t **reader)
59 {
60 pcm_sint16_converter_t *self = (pcm_sint16_converter_t *)*reader;
61 pcm_teardown(&self->src);
62 free(self->pivot);
63 free(self);
64 *reader = 0;
65 }
66
67 static pcm_reader_vtbl_t my_vtable = {
68 get_format, get_length, get_position, read_frames, teardown
69 };
70
71 pcm_reader_t *pcm_open_sint16_converter(pcm_reader_t *reader)
72 {
73 pcm_sint16_converter_t *self = 0;
74 pcm_sample_description_t *fmt;
75
76 if ((self = calloc(1, sizeof(pcm_sint16_converter_t))) == 0)
77 return 0;
78 self->src = reader;
79 self->vtbl = &my_vtable;
80 memcpy(&self->format, pcm_get_format(reader), sizeof(self->format));
81 fmt = &self->format;
82 #if WORDS_BIGENDIAN
83 fmt->sample_type = PCM_TYPE_SINT_BE;
84 #else
85 fmt->sample_type = PCM_TYPE_SINT;
86 #endif
87 fmt->bits_per_channel = 16;
88 fmt->bytes_per_frame = 2 * fmt->channels_per_frame;
89 return (pcm_reader_t *)self;
90 }
This page took 0.048697 seconds and 4 git commands to generate.