Rev 1905 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1905 | Rev 3960 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | frame: Heap of routines dealing with the core mpg123 data structure. |
2 | frame: Heap of routines dealing with the core mpg123 data structure. |
3 | 3 | ||
4 | copyright 2008-9 by the mpg123 project - free software under the terms of the LGPL 2.1 |
4 | copyright 2008-2010 by the mpg123 project - free software under the terms of the LGPL 2.1 |
5 | see COPYING and AUTHORS files in distribution or http://mpg123.org |
5 | see COPYING and AUTHORS files in distribution or http://mpg123.org |
6 | initially written by Thomas Orgis |
6 | initially written by Thomas Orgis |
7 | */ |
7 | */ |
8 | 8 | ||
9 | #include "mpg123lib_intern.h" |
9 | #include "mpg123lib_intern.h" |
10 | #include "getcpuflags.h" |
10 | #include "getcpuflags.h" |
11 | #include "debug.h" |
11 | #include "debug.h" |
12 | 12 | ||
13 | static void frame_fixed_reset(mpg123_handle *fr); |
13 | static void frame_fixed_reset(mpg123_handle *fr); |
14 | 14 | ||
15 | /* that's doubled in decode_ntom.c */ |
15 | /* that's doubled in decode_ntom.c */ |
16 | #define NTOM_MUL (32768) |
16 | #define NTOM_MUL (32768) |
- | 17 | ||
17 | #define aligned_pointer(p,type,alignment) \ |
18 | #define aligned_pointer(p, type, alignment) align_the_pointer(p, alignment) |
- | 19 | static void *align_the_pointer(void *base, unsigned int alignment) |
|
- | 20 | { |
|
- | 21 | /* |
|
- | 22 | Work in unsigned integer realm, explicitly. |
|
- | 23 | Tricking the compiler into integer operations like % by invoking base-NULL is dangerous: It results into ptrdiff_t, which gets negative on big addresses. Big screw up, that. |
|
- | 24 | I try to do it "properly" here: Casting only to uintptr_t and no artihmethic with void*. |
|
- | 25 | */ |
|
- | 26 | uintptr_t baseval = (uintptr_t)(char*)base; |
|
18 | (((char*)(p)-(char*)NULL) % (alignment)) \ |
27 | uintptr_t aoff = baseval % alignment; |
- | 28 | ||
- | 29 | debug3("align_the_pointer: pointer %p is off by %u from %u", |
|
- | 30 | base, (unsigned int)aoff, alignment); |
|
- | 31 | ||
19 | ? (type*)((char*)(p) + (alignment) - (((char*)(p)-(char*)NULL) % (alignment))) \ |
32 | if(aoff) return (char*)base+alignment-aoff; |
20 | : (type*)(p) |
33 | else return base; |
- | 34 | } |
|
- | 35 | ||
21 | void frame_default_pars(mpg123_pars *mp) |
36 | static void frame_default_pars(mpg123_pars *mp) |
22 | { |
37 | { |
23 | mp->outscale = 1.0; |
38 | mp->outscale = 1.0; |
24 | #ifdef GAPLESS |
- | |
25 | mp->flags = MPG123_GAPLESS; |
- | |
26 | #else |
- | |
27 | mp->flags = 0; |
39 | mp->flags = 0; |
- | 40 | #ifdef GAPLESS |
|
- | 41 | mp->flags |= MPG123_GAPLESS; |
|
28 | #endif |
42 | #endif |
- | 43 | mp->flags |= MPG123_AUTO_RESAMPLE; |
|
29 | #ifndef NO_NTOM |
44 | #ifndef NO_NTOM |
30 | mp->force_rate = 0; |
45 | mp->force_rate = 0; |
31 | #endif |
46 | #endif |
32 | mp->down_sample = 0; |
47 | mp->down_sample = 0; |
33 | mp->rva = 0; |
48 | mp->rva = 0; |
34 | mp->halfspeed = 0; |
49 | mp->halfspeed = 0; |
35 | mp->doublespeed = 0; |
50 | mp->doublespeed = 0; |
36 | mp->verbose = 0; |
51 | mp->verbose = 0; |
37 | #ifndef NO_ICY |
52 | #ifndef NO_ICY |
38 | mp->icy_interval = 0; |
53 | mp->icy_interval = 0; |
39 | #endif |
54 | #endif |
40 | #ifndef WIN32 |
- | |
41 | mp->timeout = 0; |
55 | mp->timeout = 0; |
42 | #endif |
- | |
43 | mp->resync_limit = 1024; |
56 | mp->resync_limit = 1024; |
44 | #ifdef FRAME_INDEX |
57 | #ifdef FRAME_INDEX |
45 | mp->index_size = INDEX_SIZE; |
58 | mp->index_size = INDEX_SIZE; |
46 | #endif |
59 | #endif |
47 | mp->preframes = 4; /* That's good for layer 3 ISO compliance bitstream. */ |
60 | mp->preframes = 4; /* That's good for layer 3 ISO compliance bitstream. */ |
48 | mpg123_fmt_all(mp); |
61 | mpg123_fmt_all(mp); |
- | 62 | /* Default of keeping some 4K buffers at hand, should cover the "usual" use case (using 16K pipe buffers as role model). */ |
|
- | 63 | #ifndef NO_FEEDER |
|
- | 64 | mp->feedpool = 5; |
|
- | 65 | mp->feedbuffer = 4096; |
|
- | 66 | #endif |
|
49 | } |
67 | } |
50 | 68 | ||
51 | void frame_init(mpg123_handle *fr) |
69 | void frame_init(mpg123_handle *fr) |
52 | { |
70 | { |
53 | frame_init_par(fr, NULL); |
71 | frame_init_par(fr, NULL); |
54 | } |
72 | } |
55 | 73 | ||
56 | void frame_init_par(mpg123_handle *fr, mpg123_pars *mp) |
74 | void frame_init_par(mpg123_handle *fr, mpg123_pars *mp) |
57 | { |
75 | { |
58 | fr->own_buffer = FALSE; |
76 | fr->own_buffer = TRUE; |
59 | fr->buffer.data = NULL; |
77 | fr->buffer.data = NULL; |
- | 78 | fr->buffer.rdata = NULL; |
|
- | 79 | fr->buffer.fill = 0; |
|
- | 80 | fr->buffer.size = 0; |
|
60 | fr->rawbuffs = NULL; |
81 | fr->rawbuffs = NULL; |
61 | fr->rawbuffss = 0; |
82 | fr->rawbuffss = 0; |
62 | fr->rawdecwin = NULL; |
83 | fr->rawdecwin = NULL; |
63 | fr->rawdecwins = 0; |
84 | fr->rawdecwins = 0; |
64 | #ifndef NO_8BIT |
85 | #ifndef NO_8BIT |
65 | fr->conv16to8_buf = NULL; |
86 | fr->conv16to8_buf = NULL; |
66 | #endif |
87 | #endif |
67 | #ifdef OPT_DITHER |
88 | #ifdef OPT_DITHER |
68 | fr->dithernoise = NULL; |
89 | fr->dithernoise = NULL; |
69 | #endif |
90 | #endif |
- | 91 | fr->layerscratch = NULL; |
|
70 | fr->xing_toc = NULL; |
92 | fr->xing_toc = NULL; |
71 | fr->cpu_opts.type = defdec(); |
93 | fr->cpu_opts.type = defdec(); |
72 | fr->cpu_opts.class = decclass(fr->cpu_opts.type); |
94 | fr->cpu_opts.class = decclass(fr->cpu_opts.type); |
73 | #ifndef NO_NTOM |
95 | #ifndef NO_NTOM |
74 | /* these two look unnecessary, check guarantee for synth_ntom_set_step (in control_generic, even)! */ |
96 | /* these two look unnecessary, check guarantee for synth_ntom_set_step (in control_generic, even)! */ |
75 | fr->ntom_val[0] = NTOM_MUL>>1; |
97 | fr->ntom_val[0] = NTOM_MUL>>1; |
76 | fr->ntom_val[1] = NTOM_MUL>>1; |
98 | fr->ntom_val[1] = NTOM_MUL>>1; |
77 | fr->ntom_step = NTOM_MUL; |
99 | fr->ntom_step = NTOM_MUL; |
78 | #endif |
100 | #endif |
79 | /* unnecessary: fr->buffer.size = fr->buffer.fill = 0; */ |
101 | /* unnecessary: fr->buffer.size = fr->buffer.fill = 0; */ |
80 | mpg123_reset_eq(fr); |
102 | mpg123_reset_eq(fr); |
81 | init_icy(&fr->icy); |
103 | init_icy(&fr->icy); |
82 | init_id3(fr); |
104 | init_id3(fr); |
83 | /* frame_outbuffer is missing... */ |
105 | /* frame_outbuffer is missing... */ |
84 | /* frame_buffers is missing... that one needs cpu opt setting! */ |
106 | /* frame_buffers is missing... that one needs cpu opt setting! */ |
85 | /* after these... frame_reset is needed before starting full decode */ |
107 | /* after these... frame_reset is needed before starting full decode */ |
86 | invalidate_format(&fr->af); |
108 | invalidate_format(&fr->af); |
87 | fr->rdat.r_read = NULL; |
109 | fr->rdat.r_read = NULL; |
88 | fr->rdat.r_lseek = NULL; |
110 | fr->rdat.r_lseek = NULL; |
- | 111 | fr->rdat.iohandle = NULL; |
|
- | 112 | fr->rdat.r_read_handle = NULL; |
|
- | 113 | fr->rdat.r_lseek_handle = NULL; |
|
- | 114 | fr->rdat.cleanup_handle = NULL; |
|
- | 115 | fr->wrapperdata = NULL; |
|
- | 116 | fr->wrapperclean = NULL; |
|
89 | fr->decoder_change = 1; |
117 | fr->decoder_change = 1; |
90 | fr->err = MPG123_OK; |
118 | fr->err = MPG123_OK; |
91 | if(mp == NULL) frame_default_pars(&fr->p); |
119 | if(mp == NULL) frame_default_pars(&fr->p); |
92 | else memcpy(&fr->p, mp, sizeof(struct mpg123_pars_struct)); |
120 | else memcpy(&fr->p, mp, sizeof(struct mpg123_pars_struct)); |
- | 121 | ||
- | 122 | #ifndef NO_FEEDER |
|
- | 123 | bc_prepare(&fr->rdat.buffer, fr->p.feedpool, fr->p.feedbuffer); |
|
- | 124 | #endif |
|
93 | 125 | ||
94 | fr->down_sample = 0; /* Initialize to silence harmless errors when debugging. */ |
126 | fr->down_sample = 0; /* Initialize to silence harmless errors when debugging. */ |
95 | frame_fixed_reset(fr); /* Reset only the fixed data, dynamic buffers are not there yet! */ |
127 | frame_fixed_reset(fr); /* Reset only the fixed data, dynamic buffers are not there yet! */ |
96 | fr->synth = NULL; |
128 | fr->synth = NULL; |
97 | fr->synth_mono = NULL; |
129 | fr->synth_mono = NULL; |
98 | fr->make_decode_tables = NULL; |
130 | fr->make_decode_tables = NULL; |
99 | #ifdef FRAME_INDEX |
131 | #ifdef FRAME_INDEX |
100 | fi_init(&fr->index); |
132 | fi_init(&fr->index); |
101 | frame_index_setup(fr); /* Apply the size setting. */ |
133 | frame_index_setup(fr); /* Apply the size setting. */ |
102 | #endif |
134 | #endif |
103 | } |
135 | } |
104 | 136 | ||
105 | #ifdef OPT_DITHER |
137 | #ifdef OPT_DITHER |
106 | /* Also, only allocate the memory for the table on demand. |
138 | /* Also, only allocate the memory for the table on demand. |
107 | In future, one could create special noise for different sampling frequencies(?). */ |
139 | In future, one could create special noise for different sampling frequencies(?). */ |
108 | int frame_dither_init(mpg123_handle *fr) |
140 | int frame_dither_init(mpg123_handle *fr) |
109 | { |
141 | { |
110 | /* run-time dither noise table generation */ |
142 | /* run-time dither noise table generation */ |
111 | if(fr->dithernoise == NULL) |
143 | if(fr->dithernoise == NULL) |
112 | { |
144 | { |
113 | fr->dithernoise = malloc(sizeof(float)*DITHERSIZE); |
145 | fr->dithernoise = malloc(sizeof(float)*DITHERSIZE); |
114 | if(fr->dithernoise == NULL) return 0; |
146 | if(fr->dithernoise == NULL) return 0; |
115 | 147 | ||
116 | dither_table_init(fr->dithernoise); |
148 | dither_table_init(fr->dithernoise); |
117 | } |
149 | } |
118 | return 1; |
150 | return 1; |
119 | } |
151 | } |
120 | #endif |
152 | #endif |
121 | 153 | ||
122 | mpg123_pars attribute_align_arg *mpg123_new_pars(int *error) |
154 | mpg123_pars attribute_align_arg *mpg123_new_pars(int *error) |
123 | { |
155 | { |
124 | mpg123_pars *mp = malloc(sizeof(struct mpg123_pars_struct)); |
156 | mpg123_pars *mp = malloc(sizeof(struct mpg123_pars_struct)); |
125 | if(mp != NULL){ frame_default_pars(mp); if(error != NULL) *error = MPG123_OK; } |
157 | if(mp != NULL){ frame_default_pars(mp); if(error != NULL) *error = MPG123_OK; } |
126 | else if(error != NULL) *error = MPG123_OUT_OF_MEM; |
158 | else if(error != NULL) *error = MPG123_OUT_OF_MEM; |
127 | return mp; |
159 | return mp; |
128 | } |
160 | } |
129 | 161 | ||
130 | void attribute_align_arg mpg123_delete_pars(mpg123_pars* mp) |
162 | void attribute_align_arg mpg123_delete_pars(mpg123_pars* mp) |
131 | { |
163 | { |
132 | if(mp != NULL) free(mp); |
164 | if(mp != NULL) free(mp); |
133 | } |
165 | } |
134 | 166 | ||
135 | int attribute_align_arg mpg123_reset_eq(mpg123_handle *mh) |
167 | int attribute_align_arg mpg123_reset_eq(mpg123_handle *mh) |
136 | { |
168 | { |
137 | int i; |
169 | int i; |
138 | mh->have_eq_settings = 0; |
170 | mh->have_eq_settings = 0; |
139 | for(i=0; i < 32; ++i) mh->equalizer[0][i] = mh->equalizer[1][i] = DOUBLE_TO_REAL(1.0); |
171 | for(i=0; i < 32; ++i) mh->equalizer[0][i] = mh->equalizer[1][i] = DOUBLE_TO_REAL(1.0); |
140 | 172 | ||
141 | return MPG123_OK; |
173 | return MPG123_OK; |
142 | } |
174 | } |
143 | 175 | ||
144 | int frame_outbuffer(mpg123_handle *fr) |
176 | int frame_outbuffer(mpg123_handle *fr) |
145 | { |
177 | { |
146 | size_t size = mpg123_safe_buffer()*AUDIOBUFSIZE; |
178 | size_t size = fr->outblock; |
147 | if(!fr->own_buffer) fr->buffer.data = NULL; |
179 | if(!fr->own_buffer) |
148 | if(fr->buffer.data != NULL && fr->buffer.size != size) |
- | |
149 | { |
180 | { |
- | 181 | if(fr->buffer.size < size) |
|
- | 182 | { |
|
- | 183 | fr->err = MPG123_BAD_BUFFER; |
|
- | 184 | if(NOQUIET) error2("have external buffer of size %"SIZE_P", need %"SIZE_P, (size_p)fr->buffer.size, size); |
|
- | 185 | ||
- | 186 | return MPG123_ERR; |
|
- | 187 | } |
|
- | 188 | } |
|
- | 189 | ||
- | 190 | debug1("need frame buffer of %"SIZE_P, (size_p)size); |
|
- | 191 | if(fr->buffer.rdata != NULL && fr->buffer.size != size) |
|
- | 192 | { |
|
150 | free(fr->buffer.data); |
193 | free(fr->buffer.rdata); |
151 | fr->buffer.data = NULL; |
194 | fr->buffer.rdata = NULL; |
152 | } |
195 | } |
153 | fr->buffer.size = size; |
196 | fr->buffer.size = size; |
- | 197 | fr->buffer.data = NULL; |
|
- | 198 | /* be generous: use 16 byte alignment */ |
|
154 | if(fr->buffer.data == NULL) fr->buffer.data = (unsigned char*) malloc(fr->buffer.size); |
199 | if(fr->buffer.rdata == NULL) fr->buffer.rdata = (unsigned char*) malloc(fr->buffer.size+15); |
155 | if(fr->buffer.data == NULL) |
200 | if(fr->buffer.rdata == NULL) |
156 | { |
201 | { |
157 | fr->err = MPG123_OUT_OF_MEM; |
202 | fr->err = MPG123_OUT_OF_MEM; |
158 | return -1; |
203 | return MPG123_ERR; |
159 | } |
204 | } |
- | 205 | fr->buffer.data = aligned_pointer(fr->buffer.rdata, unsigned char*, 16); |
|
160 | fr->own_buffer = TRUE; |
206 | fr->own_buffer = TRUE; |
161 | fr->buffer.fill = 0; |
207 | fr->buffer.fill = 0; |
162 | return 0; |
208 | return MPG123_OK; |
163 | } |
209 | } |
164 | 210 | ||
165 | int attribute_align_arg mpg123_replace_buffer(mpg123_handle *mh, unsigned char *data, size_t size) |
211 | int attribute_align_arg mpg123_replace_buffer(mpg123_handle *mh, unsigned char *data, size_t size) |
166 | { |
212 | { |
- | 213 | debug2("replace buffer with %p size %"SIZE_P, data, (size_p)size); |
|
167 | if(data == NULL || size < mpg123_safe_buffer()) |
214 | /* Will accept any size, the error comes later... */ |
- | 215 | if(data == NULL) |
|
168 | { |
216 | { |
169 | mh->err = MPG123_BAD_BUFFER; |
217 | mh->err = MPG123_BAD_BUFFER; |
170 | return MPG123_ERR; |
218 | return MPG123_ERR; |
171 | } |
219 | } |
172 | if(mh->own_buffer && mh->buffer.data != NULL) free(mh->buffer.data); |
220 | if(mh->buffer.rdata != NULL) free(mh->buffer.rdata); |
173 | mh->own_buffer = FALSE; |
221 | mh->own_buffer = FALSE; |
- | 222 | mh->buffer.rdata = NULL; |
|
174 | mh->buffer.data = data; |
223 | mh->buffer.data = data; |
175 | mh->buffer.size = size; |
224 | mh->buffer.size = size; |
176 | mh->buffer.fill = 0; |
225 | mh->buffer.fill = 0; |
177 | return MPG123_OK; |
226 | return MPG123_OK; |
178 | } |
227 | } |
179 | 228 | ||
180 | #ifdef FRAME_INDEX |
229 | #ifdef FRAME_INDEX |
181 | int frame_index_setup(mpg123_handle *fr) |
230 | int frame_index_setup(mpg123_handle *fr) |
182 | { |
231 | { |
183 | int ret = MPG123_ERR; |
232 | int ret = MPG123_ERR; |
184 | if(fr->p.index_size >= 0) |
233 | if(fr->p.index_size >= 0) |
185 | { /* Simple fixed index. */ |
234 | { /* Simple fixed index. */ |
186 | fr->index.grow_size = 0; |
235 | fr->index.grow_size = 0; |
187 | debug1("resizing index to %li", fr->p.index_size); |
236 | debug1("resizing index to %li", fr->p.index_size); |
188 | ret = fi_resize(&fr->index, (size_t)fr->p.index_size); |
237 | ret = fi_resize(&fr->index, (size_t)fr->p.index_size); |
189 | debug2("index resized... %lu at %p", (unsigned long)fr->index.size, (void*)fr->index.data); |
238 | debug2("index resized... %lu at %p", (unsigned long)fr->index.size, (void*)fr->index.data); |
190 | } |
239 | } |
191 | else |
240 | else |
192 | { /* A growing index. We give it a start, though. */ |
241 | { /* A growing index. We give it a start, though. */ |
193 | fr->index.grow_size = (size_t)(- fr->p.index_size); |
242 | fr->index.grow_size = (size_t)(- fr->p.index_size); |
194 | if(fr->index.size < fr->index.grow_size) |
243 | if(fr->index.size < fr->index.grow_size) |
195 | ret = fi_resize(&fr->index, fr->index.grow_size); |
244 | ret = fi_resize(&fr->index, fr->index.grow_size); |
196 | else |
245 | else |
197 | ret = MPG123_OK; /* We have minimal size already... and since growing is OK... */ |
246 | ret = MPG123_OK; /* We have minimal size already... and since growing is OK... */ |
198 | } |
247 | } |
199 | debug2("set up frame index of size %lu (ret=%i)", (unsigned long)fr->index.size, ret); |
248 | debug2("set up frame index of size %lu (ret=%i)", (unsigned long)fr->index.size, ret); |
200 | 249 | ||
201 | return ret; |
250 | return ret; |
202 | } |
251 | } |
203 | #endif |
252 | #endif |
204 | 253 | ||
205 | static void frame_decode_buffers_reset(mpg123_handle *fr) |
254 | static void frame_decode_buffers_reset(mpg123_handle *fr) |
206 | { |
255 | { |
207 | memset(fr->rawbuffs, 0, fr->rawbuffss); |
256 | memset(fr->rawbuffs, 0, fr->rawbuffss); |
208 | } |
257 | } |
209 | 258 | ||
210 | int frame_buffers(mpg123_handle *fr) |
259 | int frame_buffers(mpg123_handle *fr) |
211 | { |
260 | { |
212 | int buffssize = 0; |
261 | int buffssize = 0; |
213 | debug1("frame %p buffer", (void*)fr); |
262 | debug1("frame %p buffer", (void*)fr); |
214 | /* |
263 | /* |
215 | the used-to-be-static buffer of the synth functions, has some subtly different types/sizes |
264 | the used-to-be-static buffer of the synth functions, has some subtly different types/sizes |
216 | 265 | ||
217 | 2to1, 4to1, ntom, generic, i386: real[2][2][0x110] |
266 | 2to1, 4to1, ntom, generic, i386: real[2][2][0x110] |
218 | mmx, sse: short[2][2][0x110] |
267 | mmx, sse: short[2][2][0x110] |
219 | i586(_dither): 4352 bytes; int/long[2][2][0x110] |
268 | i586(_dither): 4352 bytes; int/long[2][2][0x110] |
220 | i486: int[2][2][17*FIR_BUFFER_SIZE] |
269 | i486: int[2][2][17*FIR_BUFFER_SIZE] |
221 | altivec: static real __attribute__ ((aligned (16))) buffs[4][4][0x110] |
270 | altivec: static real __attribute__ ((aligned (16))) buffs[4][4][0x110] |
222 | 271 | ||
223 | Huh, altivec looks like fun. Well, let it be large... then, the 16 byte alignment seems to be implicit on MacOSX malloc anyway. |
272 | Huh, altivec looks like fun. Well, let it be large... then, the 16 byte alignment seems to be implicit on MacOSX malloc anyway. |
224 | Let's make a reasonable attempt to allocate enough memory... |
273 | Let's make a reasonable attempt to allocate enough memory... |
225 | Keep in mind: biggest ones are i486 and altivec (mutually exclusive!), then follows i586 and normal real. |
274 | Keep in mind: biggest ones are i486 and altivec (mutually exclusive!), then follows i586 and normal real. |
226 | mmx/sse use short but also real for resampling. |
275 | mmx/sse use short but also real for resampling. |
227 | Thus, minimum is 2*2*0x110*sizeof(real). |
276 | Thus, minimum is 2*2*0x110*sizeof(real). |
228 | */ |
277 | */ |
229 | if(fr->cpu_opts.type == altivec) buffssize = 4*4*0x110*sizeof(real); |
278 | if(fr->cpu_opts.type == altivec) buffssize = 4*4*0x110*sizeof(real); |
230 | #ifdef OPT_I486 |
279 | #ifdef OPT_I486 |
231 | else if(fr->cpu_opts.type == ivier) buffssize = 2*2*17*FIR_BUFFER_SIZE*sizeof(int); |
280 | else if(fr->cpu_opts.type == ivier) buffssize = 2*2*17*FIR_BUFFER_SIZE*sizeof(int); |
232 | #endif |
281 | #endif |
233 | else if(fr->cpu_opts.type == ifuenf || fr->cpu_opts.type == ifuenf_dither || fr->cpu_opts.type == dreidnow) |
282 | else if(fr->cpu_opts.type == ifuenf || fr->cpu_opts.type == ifuenf_dither || fr->cpu_opts.type == dreidnow) |
234 | buffssize = 2*2*0x110*4; /* don't rely on type real, we need 4352 bytes */ |
283 | buffssize = 2*2*0x110*4; /* don't rely on type real, we need 4352 bytes */ |
235 | 284 | ||
236 | if(2*2*0x110*sizeof(real) > buffssize) |
285 | if(2*2*0x110*sizeof(real) > buffssize) |
237 | buffssize = 2*2*0x110*sizeof(real); |
286 | buffssize = 2*2*0x110*sizeof(real); |
238 | buffssize += 15; /* For 16-byte alignment (SSE likes that). */ |
287 | buffssize += 15; /* For 16-byte alignment (SSE likes that). */ |
239 | 288 | ||
240 | if(fr->rawbuffs != NULL && fr->rawbuffss != buffssize) |
289 | if(fr->rawbuffs != NULL && fr->rawbuffss != buffssize) |
241 | { |
290 | { |
242 | free(fr->rawbuffs); |
291 | free(fr->rawbuffs); |
243 | fr->rawbuffs = NULL; |
292 | fr->rawbuffs = NULL; |
244 | } |
293 | } |
245 | 294 | ||
246 | if(fr->rawbuffs == NULL) fr->rawbuffs = (unsigned char*) malloc(buffssize); |
295 | if(fr->rawbuffs == NULL) fr->rawbuffs = (unsigned char*) malloc(buffssize); |
247 | if(fr->rawbuffs == NULL) return -1; |
296 | if(fr->rawbuffs == NULL) return -1; |
248 | fr->rawbuffss = buffssize; |
297 | fr->rawbuffss = buffssize; |
249 | fr->short_buffs[0][0] = aligned_pointer(fr->rawbuffs,short,16); |
298 | fr->short_buffs[0][0] = aligned_pointer(fr->rawbuffs,short,16); |
250 | fr->short_buffs[0][1] = fr->short_buffs[0][0] + 0x110; |
299 | fr->short_buffs[0][1] = fr->short_buffs[0][0] + 0x110; |
251 | fr->short_buffs[1][0] = fr->short_buffs[0][1] + 0x110; |
300 | fr->short_buffs[1][0] = fr->short_buffs[0][1] + 0x110; |
252 | fr->short_buffs[1][1] = fr->short_buffs[1][0] + 0x110; |
301 | fr->short_buffs[1][1] = fr->short_buffs[1][0] + 0x110; |
253 | fr->real_buffs[0][0] = aligned_pointer(fr->rawbuffs,real,16); |
302 | fr->real_buffs[0][0] = aligned_pointer(fr->rawbuffs,real,16); |
254 | fr->real_buffs[0][1] = fr->real_buffs[0][0] + 0x110; |
303 | fr->real_buffs[0][1] = fr->real_buffs[0][0] + 0x110; |
255 | fr->real_buffs[1][0] = fr->real_buffs[0][1] + 0x110; |
304 | fr->real_buffs[1][0] = fr->real_buffs[0][1] + 0x110; |
256 | fr->real_buffs[1][1] = fr->real_buffs[1][0] + 0x110; |
305 | fr->real_buffs[1][1] = fr->real_buffs[1][0] + 0x110; |
257 | #ifdef OPT_I486 |
306 | #ifdef OPT_I486 |
258 | if(fr->cpu_opts.type == ivier) |
307 | if(fr->cpu_opts.type == ivier) |
259 | { |
308 | { |
260 | fr->int_buffs[0][0] = (int*) fr->rawbuffs; |
309 | fr->int_buffs[0][0] = (int*) fr->rawbuffs; |
261 | fr->int_buffs[0][1] = fr->int_buffs[0][0] + 17*FIR_BUFFER_SIZE; |
310 | fr->int_buffs[0][1] = fr->int_buffs[0][0] + 17*FIR_BUFFER_SIZE; |
262 | fr->int_buffs[1][0] = fr->int_buffs[0][1] + 17*FIR_BUFFER_SIZE; |
311 | fr->int_buffs[1][0] = fr->int_buffs[0][1] + 17*FIR_BUFFER_SIZE; |
263 | fr->int_buffs[1][1] = fr->int_buffs[1][0] + 17*FIR_BUFFER_SIZE; |
312 | fr->int_buffs[1][1] = fr->int_buffs[1][0] + 17*FIR_BUFFER_SIZE; |
264 | } |
313 | } |
265 | #endif |
314 | #endif |
266 | #ifdef OPT_ALTIVEC |
315 | #ifdef OPT_ALTIVEC |
267 | if(fr->cpu_opts.type == altivec) |
316 | if(fr->cpu_opts.type == altivec) |
268 | { |
317 | { |
269 | int i,j; |
318 | int i,j; |
270 | fr->areal_buffs[0][0] = (real*) fr->rawbuffs; |
319 | fr->areal_buffs[0][0] = (real*) fr->rawbuffs; |
271 | for(i=0; i<4; ++i) for(j=0; j<4; ++j) |
320 | for(i=0; i<4; ++i) for(j=0; j<4; ++j) |
272 | fr->areal_buffs[i][j] = fr->areal_buffs[0][0] + (i*4+j)*0x110; |
321 | fr->areal_buffs[i][j] = fr->areal_buffs[0][0] + (i*4+j)*0x110; |
273 | } |
322 | } |
274 | #endif |
323 | #endif |
275 | /* now the different decwins... all of the same size, actually */ |
324 | /* now the different decwins... all of the same size, actually */ |
276 | /* The MMX ones want 32byte alignment, which I'll try to ensure manually */ |
325 | /* The MMX ones want 32byte alignment, which I'll try to ensure manually */ |
277 | { |
326 | { |
278 | int decwin_size = (512+32)*sizeof(real); |
327 | int decwin_size = (512+32)*sizeof(real); |
279 | #ifdef OPT_MMXORSSE |
328 | #ifdef OPT_MMXORSSE |
280 | #ifdef OPT_MULTI |
329 | #ifdef OPT_MULTI |
281 | if(fr->cpu_opts.class == mmxsse) |
330 | if(fr->cpu_opts.class == mmxsse) |
282 | { |
331 | { |
283 | #endif |
332 | #endif |
284 | /* decwin_mmx will share, decwins will be appended ... sizeof(float)==4 */ |
333 | /* decwin_mmx will share, decwins will be appended ... sizeof(float)==4 */ |
285 | if(decwin_size < (512+32)*4) decwin_size = (512+32)*4; |
334 | if(decwin_size < (512+32)*4) decwin_size = (512+32)*4; |
286 | 335 | ||
287 | /* the second window + alignment zone -- we align for 32 bytes for SSE as |
336 | /* the second window + alignment zone -- we align for 32 bytes for SSE as |
288 | requirement, 64 byte for matching cache line size (that matters!) */ |
337 | requirement, 64 byte for matching cache line size (that matters!) */ |
289 | decwin_size += (512+32)*4 + 63; |
338 | decwin_size += (512+32)*4 + 63; |
290 | /* (512+32)*4/32 == 2176/32 == 68, so one decwin block retains alignment for 32 or 64 bytes */ |
339 | /* (512+32)*4/32 == 2176/32 == 68, so one decwin block retains alignment for 32 or 64 bytes */ |
291 | #ifdef OPT_MULTI |
340 | #ifdef OPT_MULTI |
292 | } |
341 | } |
293 | #endif |
342 | #endif |
294 | #endif |
343 | #endif |
295 | #if defined(OPT_ALTIVEC) || defined(OPT_ARM) |
344 | #if defined(OPT_ALTIVEC) || defined(OPT_ARM) |
- | 345 | /* sizeof(real) >= 4 ... yes, it could be 8, for example. |
|
296 | if(decwin_size < (512+32)*4) decwin_size = (512+32)*4; |
346 | We got it intialized to at least (512+32)*sizeof(real).*/ |
297 | decwin_size += 512*4; |
347 | decwin_size += 512*sizeof(real); |
298 | #endif |
348 | #endif |
299 | /* Hm, that's basically realloc() ... */ |
349 | /* Hm, that's basically realloc() ... */ |
300 | if(fr->rawdecwin != NULL && fr->rawdecwins != decwin_size) |
350 | if(fr->rawdecwin != NULL && fr->rawdecwins != decwin_size) |
301 | { |
351 | { |
302 | free(fr->rawdecwin); |
352 | free(fr->rawdecwin); |
303 | fr->rawdecwin = NULL; |
353 | fr->rawdecwin = NULL; |
304 | } |
354 | } |
305 | 355 | ||
306 | if(fr->rawdecwin == NULL) |
356 | if(fr->rawdecwin == NULL) |
307 | fr->rawdecwin = (unsigned char*) malloc(decwin_size); |
357 | fr->rawdecwin = (unsigned char*) malloc(decwin_size); |
308 | 358 | ||
309 | if(fr->rawdecwin == NULL) return -1; |
359 | if(fr->rawdecwin == NULL) return -1; |
310 | 360 | ||
311 | fr->rawdecwins = decwin_size; |
361 | fr->rawdecwins = decwin_size; |
312 | fr->decwin = (real*) fr->rawdecwin; |
362 | fr->decwin = (real*) fr->rawdecwin; |
313 | #ifdef OPT_MMXORSSE |
363 | #ifdef OPT_MMXORSSE |
314 | #ifdef OPT_MULTI |
364 | #ifdef OPT_MULTI |
315 | if(fr->cpu_opts.class == mmxsse) |
365 | if(fr->cpu_opts.class == mmxsse) |
316 | { |
366 | { |
317 | #endif |
367 | #endif |
318 | /* align decwin, assign that to decwin_mmx, append decwins */ |
368 | /* align decwin, assign that to decwin_mmx, append decwins */ |
319 | /* I need to add to decwin what is missing to the next full 64 byte -- also I want to make gcc -pedantic happy... */ |
369 | /* I need to add to decwin what is missing to the next full 64 byte -- also I want to make gcc -pedantic happy... */ |
320 | fr->decwin = aligned_pointer(fr->rawdecwin,real,64); |
370 | fr->decwin = aligned_pointer(fr->rawdecwin,real,64); |
321 | debug1("aligned decwin: %p", (void*)fr->decwin); |
371 | debug1("aligned decwin: %p", (void*)fr->decwin); |
322 | fr->decwin_mmx = (float*)fr->decwin; |
372 | fr->decwin_mmx = (float*)fr->decwin; |
323 | fr->decwins = fr->decwin_mmx+512+32; |
373 | fr->decwins = fr->decwin_mmx+512+32; |
324 | #ifdef OPT_MULTI |
374 | #ifdef OPT_MULTI |
325 | } |
375 | } |
326 | else debug("no decwins/decwin_mmx for that class"); |
376 | else debug("no decwins/decwin_mmx for that class"); |
327 | #endif |
377 | #endif |
328 | #endif |
378 | #endif |
329 | } |
379 | } |
- | 380 | ||
- | 381 | /* Layer scratch buffers are of compile-time fixed size, so allocate only once. */ |
|
- | 382 | if(fr->layerscratch == NULL) |
|
- | 383 | { |
|
- | 384 | /* Allocate specific layer1/2/3 buffers, so that we know they'll work for SSE. */ |
|
- | 385 | size_t scratchsize = 0; |
|
- | 386 | real *scratcher; |
|
- | 387 | #ifndef NO_LAYER1 |
|
- | 388 | scratchsize += sizeof(real) * 2 * SBLIMIT; |
|
- | 389 | #endif |
|
- | 390 | #ifndef NO_LAYER2 |
|
- | 391 | scratchsize += sizeof(real) * 2 * 4 * SBLIMIT; |
|
- | 392 | #endif |
|
- | 393 | #ifndef NO_LAYER3 |
|
- | 394 | scratchsize += sizeof(real) * 2 * SBLIMIT * SSLIMIT; /* hybrid_in */ |
|
- | 395 | scratchsize += sizeof(real) * 2 * SSLIMIT * SBLIMIT; /* hybrid_out */ |
|
- | 396 | #endif |
|
- | 397 | /* |
|
- | 398 | Now figure out correct alignment: |
|
- | 399 | We need 16 byte minimum, smallest unit of the blocks is 2*SBLIMIT*sizeof(real), which is 64*4=256. Let's do 64bytes as heuristic for cache line (as proven useful in buffs above). |
|
- | 400 | */ |
|
- | 401 | fr->layerscratch = malloc(scratchsize+63); |
|
- | 402 | if(fr->layerscratch == NULL) return -1; |
|
- | 403 | ||
- | 404 | /* Get aligned part of the memory, then divide it up. */ |
|
- | 405 | scratcher = aligned_pointer(fr->layerscratch,real,64); |
|
- | 406 | /* Those funky pointer casts silence compilers... |
|
- | 407 | One might change the code at hand to really just use 1D arrays, but in practice, that would not make a (positive) difference. */ |
|
- | 408 | #ifndef NO_LAYER1 |
|
- | 409 | fr->layer1.fraction = (real(*)[SBLIMIT])scratcher; |
|
- | 410 | scratcher += 2 * SBLIMIT; |
|
- | 411 | #endif |
|
- | 412 | #ifndef NO_LAYER2 |
|
- | 413 | fr->layer2.fraction = (real(*)[4][SBLIMIT])scratcher; |
|
- | 414 | scratcher += 2 * 4 * SBLIMIT; |
|
- | 415 | #endif |
|
- | 416 | #ifndef NO_LAYER3 |
|
- | 417 | fr->layer3.hybrid_in = (real(*)[SBLIMIT][SSLIMIT])scratcher; |
|
- | 418 | scratcher += 2 * SBLIMIT * SSLIMIT; |
|
- | 419 | fr->layer3.hybrid_out = (real(*)[SSLIMIT][SBLIMIT])scratcher; |
|
- | 420 | scratcher += 2 * SSLIMIT * SBLIMIT; |
|
- | 421 | #endif |
|
- | 422 | /* Note: These buffers don't need resetting here. */ |
|
- | 423 | } |
|
- | 424 | ||
330 | /* Only reset the buffers we created just now. */ |
425 | /* Only reset the buffers we created just now. */ |
331 | frame_decode_buffers_reset(fr); |
426 | frame_decode_buffers_reset(fr); |
332 | 427 | ||
333 | debug1("frame %p buffer done", (void*)fr); |
428 | debug1("frame %p buffer done", (void*)fr); |
334 | return 0; |
429 | return 0; |
335 | } |
430 | } |
336 | 431 | ||
337 | int frame_buffers_reset(mpg123_handle *fr) |
432 | int frame_buffers_reset(mpg123_handle *fr) |
338 | { |
433 | { |
339 | fr->buffer.fill = 0; /* hm, reset buffer fill... did we do a flush? */ |
434 | fr->buffer.fill = 0; /* hm, reset buffer fill... did we do a flush? */ |
340 | fr->bsnum = 0; |
435 | fr->bsnum = 0; |
341 | /* Wondering: could it be actually _wanted_ to retain buffer contents over different files? (special gapless / cut stuff) */ |
436 | /* Wondering: could it be actually _wanted_ to retain buffer contents over different files? (special gapless / cut stuff) */ |
342 | fr->bsbuf = fr->bsspace[1]; |
437 | fr->bsbuf = fr->bsspace[1]; |
343 | fr->bsbufold = fr->bsbuf; |
438 | fr->bsbufold = fr->bsbuf; |
344 | fr->bitreservoir = 0; /* Not entirely sure if this is the right place for that counter. */ |
439 | fr->bitreservoir = 0; |
345 | frame_decode_buffers_reset(fr); |
440 | frame_decode_buffers_reset(fr); |
346 | memset(fr->bsspace, 0, 2*(MAXFRAMESIZE+512)); |
441 | memset(fr->bsspace, 0, 2*(MAXFRAMESIZE+512)); |
347 | memset(fr->ssave, 0, 34); |
442 | memset(fr->ssave, 0, 34); |
348 | fr->hybrid_blc[0] = fr->hybrid_blc[1] = 0; |
443 | fr->hybrid_blc[0] = fr->hybrid_blc[1] = 0; |
349 | memset(fr->hybrid_block, 0, sizeof(real)*2*2*SBLIMIT*SSLIMIT); |
444 | memset(fr->hybrid_block, 0, sizeof(real)*2*2*SBLIMIT*SSLIMIT); |
350 | return 0; |
445 | return 0; |
351 | } |
446 | } |
352 | 447 | ||
353 | void frame_icy_reset(mpg123_handle* fr) |
448 | static void frame_icy_reset(mpg123_handle* fr) |
354 | { |
449 | { |
355 | #ifndef NO_ICY |
450 | #ifndef NO_ICY |
356 | if(fr->icy.data != NULL) free(fr->icy.data); |
451 | if(fr->icy.data != NULL) free(fr->icy.data); |
357 | fr->icy.data = NULL; |
452 | fr->icy.data = NULL; |
358 | fr->icy.interval = 0; |
453 | fr->icy.interval = 0; |
359 | fr->icy.next = 0; |
454 | fr->icy.next = 0; |
360 | #endif |
455 | #endif |
361 | } |
456 | } |
362 | 457 | ||
363 | void frame_free_toc(mpg123_handle *fr) |
458 | static void frame_free_toc(mpg123_handle *fr) |
364 | { |
459 | { |
365 | if(fr->xing_toc != NULL){ free(fr->xing_toc); fr->xing_toc = NULL; } |
460 | if(fr->xing_toc != NULL){ free(fr->xing_toc); fr->xing_toc = NULL; } |
366 | } |
461 | } |
367 | 462 | ||
368 | /* Just copy the Xing TOC over... */ |
463 | /* Just copy the Xing TOC over... */ |
369 | int frame_fill_toc(mpg123_handle *fr, unsigned char* in) |
464 | int frame_fill_toc(mpg123_handle *fr, unsigned char* in) |
370 | { |
465 | { |
371 | if(fr->xing_toc == NULL) fr->xing_toc = malloc(100); |
466 | if(fr->xing_toc == NULL) fr->xing_toc = malloc(100); |
372 | if(fr->xing_toc != NULL) |
467 | if(fr->xing_toc != NULL) |
373 | { |
468 | { |
374 | memcpy(fr->xing_toc, in, 100); |
469 | memcpy(fr->xing_toc, in, 100); |
375 | #ifdef DEBUG |
470 | #ifdef DEBUG |
376 | debug("Got a TOC! Showing the values..."); |
471 | debug("Got a TOC! Showing the values..."); |
377 | { |
472 | { |
378 | int i; |
473 | int i; |
379 | for(i=0; i<100; ++i) |
474 | for(i=0; i<100; ++i) |
380 | debug2("entry %i = %i", i, fr->xing_toc[i]); |
475 | debug2("entry %i = %i", i, fr->xing_toc[i]); |
381 | } |
476 | } |
382 | #endif |
477 | #endif |
383 | return TRUE; |
478 | return TRUE; |
384 | } |
479 | } |
385 | return FALSE; |
480 | return FALSE; |
386 | } |
481 | } |
387 | 482 | ||
388 | /* Prepare the handle for a new track. |
483 | /* Prepare the handle for a new track. |
389 | Reset variables, buffers... */ |
484 | Reset variables, buffers... */ |
390 | int frame_reset(mpg123_handle* fr) |
485 | int frame_reset(mpg123_handle* fr) |
391 | { |
486 | { |
392 | frame_buffers_reset(fr); |
487 | frame_buffers_reset(fr); |
393 | frame_fixed_reset(fr); |
488 | frame_fixed_reset(fr); |
394 | frame_free_toc(fr); |
489 | frame_free_toc(fr); |
395 | #ifdef FRAME_INDEX |
490 | #ifdef FRAME_INDEX |
396 | fi_reset(&fr->index); |
491 | fi_reset(&fr->index); |
397 | #endif |
492 | #endif |
398 | 493 | ||
399 | return 0; |
494 | return 0; |
400 | } |
495 | } |
401 | 496 | ||
402 | /* Reset everythign except dynamic memory. */ |
497 | /* Reset everythign except dynamic memory. */ |
403 | static void frame_fixed_reset(mpg123_handle *fr) |
498 | static void frame_fixed_reset(mpg123_handle *fr) |
404 | { |
499 | { |
405 | frame_icy_reset(fr); |
500 | frame_icy_reset(fr); |
406 | open_bad(fr); |
501 | open_bad(fr); |
407 | fr->to_decode = FALSE; |
502 | fr->to_decode = FALSE; |
408 | fr->to_ignore = FALSE; |
503 | fr->to_ignore = FALSE; |
409 | fr->metaflags = 0; |
504 | fr->metaflags = 0; |
410 | fr->outblock = mpg123_safe_buffer(); |
505 | fr->outblock = 0; /* This will be set before decoding! */ |
411 | fr->num = -1; |
506 | fr->num = -1; |
- | 507 | fr->input_offset = -1; |
|
412 | fr->playnum = -1; |
508 | fr->playnum = -1; |
413 | fr->accurate = TRUE; |
509 | fr->state_flags = FRAME_ACCURATE; |
414 | fr->silent_resync = 0; |
510 | fr->silent_resync = 0; |
415 | fr->audio_start = 0; |
511 | fr->audio_start = 0; |
416 | fr->clip = 0; |
512 | fr->clip = 0; |
417 | fr->oldhead = 0; |
513 | fr->oldhead = 0; |
418 | fr->firsthead = 0; |
514 | fr->firsthead = 0; |
419 | fr->vbr = MPG123_CBR; |
515 | fr->vbr = MPG123_CBR; |
420 | fr->abr_rate = 0; |
516 | fr->abr_rate = 0; |
421 | fr->track_frames = 0; |
517 | fr->track_frames = 0; |
422 | fr->track_samples = -1; |
518 | fr->track_samples = -1; |
423 | fr->framesize=0; |
519 | fr->framesize=0; |
424 | fr->mean_frames = 0; |
520 | fr->mean_frames = 0; |
425 | fr->mean_framesize = 0; |
521 | fr->mean_framesize = 0; |
426 | fr->freesize = 0; |
522 | fr->freesize = 0; |
427 | fr->lastscale = -1; |
523 | fr->lastscale = -1; |
428 | fr->rva.level[0] = -1; |
524 | fr->rva.level[0] = -1; |
429 | fr->rva.level[1] = -1; |
525 | fr->rva.level[1] = -1; |
430 | fr->rva.gain[0] = 0; |
526 | fr->rva.gain[0] = 0; |
431 | fr->rva.gain[1] = 0; |
527 | fr->rva.gain[1] = 0; |
432 | fr->rva.peak[0] = 0; |
528 | fr->rva.peak[0] = 0; |
433 | fr->rva.peak[1] = 0; |
529 | fr->rva.peak[1] = 0; |
434 | fr->fsizeold = 0; |
530 | fr->fsizeold = 0; |
435 | fr->firstframe = 0; |
531 | fr->firstframe = 0; |
436 | fr->ignoreframe = fr->firstframe-fr->p.preframes; |
532 | fr->ignoreframe = fr->firstframe-fr->p.preframes; |
437 | fr->lastframe = -1; |
533 | fr->lastframe = -1; |
438 | fr->fresh = 1; |
534 | fr->fresh = 1; |
439 | fr->new_format = 0; |
535 | fr->new_format = 0; |
440 | #ifdef GAPLESS |
536 | #ifdef GAPLESS |
441 | frame_gapless_init(fr,0,0); |
537 | frame_gapless_init(fr,-1,0,0); |
442 | fr->lastoff = 0; |
538 | fr->lastoff = 0; |
443 | fr->firstoff = 0; |
539 | fr->firstoff = 0; |
444 | #endif |
540 | #endif |
445 | #ifdef OPT_I486 |
541 | #ifdef OPT_I486 |
446 | fr->i486bo[0] = fr->i486bo[1] = FIR_SIZE-1; |
542 | fr->i486bo[0] = fr->i486bo[1] = FIR_SIZE-1; |
447 | #endif |
543 | #endif |
448 | fr->bo = 1; /* the usual bo */ |
544 | fr->bo = 1; /* the usual bo */ |
449 | #ifdef OPT_DITHER |
545 | #ifdef OPT_DITHER |
450 | fr->ditherindex = 0; |
546 | fr->ditherindex = 0; |
451 | #endif |
547 | #endif |
452 | reset_id3(fr); |
548 | reset_id3(fr); |
453 | reset_icy(&fr->icy); |
549 | reset_icy(&fr->icy); |
454 | /* ICY stuff should go into icy.c, eh? */ |
550 | /* ICY stuff should go into icy.c, eh? */ |
455 | #ifndef NO_ICY |
551 | #ifndef NO_ICY |
456 | fr->icy.interval = 0; |
552 | fr->icy.interval = 0; |
457 | fr->icy.next = 0; |
553 | fr->icy.next = 0; |
458 | #endif |
554 | #endif |
459 | fr->halfphase = 0; /* here or indeed only on first-time init? */ |
555 | fr->halfphase = 0; /* here or indeed only on first-time init? */ |
460 | fr->error_protection = 0; |
556 | fr->error_protection = 0; |
461 | fr->freeformat_framesize = -1; |
557 | fr->freeformat_framesize = -1; |
462 | } |
558 | } |
463 | 559 | ||
464 | void frame_free_buffers(mpg123_handle *fr) |
560 | static void frame_free_buffers(mpg123_handle *fr) |
465 | { |
561 | { |
466 | if(fr->rawbuffs != NULL) free(fr->rawbuffs); |
562 | if(fr->rawbuffs != NULL) free(fr->rawbuffs); |
467 | fr->rawbuffs = NULL; |
563 | fr->rawbuffs = NULL; |
468 | fr->rawbuffss = 0; |
564 | fr->rawbuffss = 0; |
469 | if(fr->rawdecwin != NULL) free(fr->rawdecwin); |
565 | if(fr->rawdecwin != NULL) free(fr->rawdecwin); |
470 | fr->rawdecwin = NULL; |
566 | fr->rawdecwin = NULL; |
471 | fr->rawdecwins = 0; |
567 | fr->rawdecwins = 0; |
472 | #ifndef NO_8BIT |
568 | #ifndef NO_8BIT |
473 | if(fr->conv16to8_buf != NULL) free(fr->conv16to8_buf); |
569 | if(fr->conv16to8_buf != NULL) free(fr->conv16to8_buf); |
474 | fr->conv16to8_buf = NULL; |
570 | fr->conv16to8_buf = NULL; |
475 | #endif |
571 | #endif |
- | 572 | if(fr->layerscratch != NULL) free(fr->layerscratch); |
|
476 | } |
573 | } |
477 | 574 | ||
478 | void frame_exit(mpg123_handle *fr) |
575 | void frame_exit(mpg123_handle *fr) |
479 | { |
576 | { |
480 | if(fr->own_buffer && fr->buffer.data != NULL) |
577 | if(fr->buffer.rdata != NULL) |
481 | { |
578 | { |
482 | debug1("freeing buffer at %p", (void*)fr->buffer.data); |
579 | debug1("freeing buffer at %p", (void*)fr->buffer.rdata); |
483 | free(fr->buffer.data); |
580 | free(fr->buffer.rdata); |
484 | } |
581 | } |
485 | fr->buffer.data = NULL; |
582 | fr->buffer.rdata = NULL; |
486 | frame_free_buffers(fr); |
583 | frame_free_buffers(fr); |
487 | frame_free_toc(fr); |
584 | frame_free_toc(fr); |
488 | #ifdef FRAME_INDEX |
585 | #ifdef FRAME_INDEX |
489 | fi_exit(&fr->index); |
586 | fi_exit(&fr->index); |
490 | #endif |
587 | #endif |
491 | #ifdef OPT_DITHER |
588 | #ifdef OPT_DITHER |
492 | if(fr->dithernoise != NULL) |
589 | if(fr->dithernoise != NULL) |
493 | { |
590 | { |
494 | free(fr->dithernoise); |
591 | free(fr->dithernoise); |
495 | fr->dithernoise = NULL; |
592 | fr->dithernoise = NULL; |
496 | } |
593 | } |
497 | #endif |
594 | #endif |
498 | exit_id3(fr); |
595 | exit_id3(fr); |
499 | clear_icy(&fr->icy); |
596 | clear_icy(&fr->icy); |
- | 597 | /* Clean up possible mess from LFS wrapper. */ |
|
- | 598 | if(fr->wrapperclean != NULL) |
|
- | 599 | { |
|
- | 600 | fr->wrapperclean(fr->wrapperdata); |
|
- | 601 | fr->wrapperdata = NULL; |
|
- | 602 | } |
|
- | 603 | #ifndef NO_FEEDER |
|
- | 604 | bc_cleanup(&fr->rdat.buffer); |
|
- | 605 | #endif |
|
500 | } |
606 | } |
501 | 607 | ||
502 | int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi) |
608 | int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi) |
503 | { |
609 | { |
504 | if(mh == NULL) return MPG123_ERR; |
610 | if(mh == NULL) return MPG123_ERR; |
505 | if(mi == NULL) |
611 | if(mi == NULL) |
506 | { |
612 | { |
507 | mh->err = MPG123_ERR_NULL; |
613 | mh->err = MPG123_ERR_NULL; |
508 | return MPG123_ERR; |
614 | return MPG123_ERR; |
509 | } |
615 | } |
510 | mi->version = mh->mpeg25 ? MPG123_2_5 : (mh->lsf ? MPG123_2_0 : MPG123_1_0); |
616 | mi->version = mh->mpeg25 ? MPG123_2_5 : (mh->lsf ? MPG123_2_0 : MPG123_1_0); |
511 | mi->layer = mh->lay; |
617 | mi->layer = mh->lay; |
512 | mi->rate = frame_freq(mh); |
618 | mi->rate = frame_freq(mh); |
513 | switch(mh->mode) |
619 | switch(mh->mode) |
514 | { |
620 | { |
515 | case 0: mi->mode = MPG123_M_STEREO; break; |
621 | case 0: mi->mode = MPG123_M_STEREO; break; |
516 | case 1: mi->mode = MPG123_M_JOINT; break; |
622 | case 1: mi->mode = MPG123_M_JOINT; break; |
517 | case 2: mi->mode = MPG123_M_DUAL; break; |
623 | case 2: mi->mode = MPG123_M_DUAL; break; |
518 | case 3: mi->mode = MPG123_M_MONO; break; |
624 | case 3: mi->mode = MPG123_M_MONO; break; |
519 | default: error("That mode cannot be!"); |
625 | default: error("That mode cannot be!"); |
520 | } |
626 | } |
521 | mi->mode_ext = mh->mode_ext; |
627 | mi->mode_ext = mh->mode_ext; |
522 | mi->framesize = mh->framesize+4; /* Include header. */ |
628 | mi->framesize = mh->framesize+4; /* Include header. */ |
523 | mi->flags = 0; |
629 | mi->flags = 0; |
524 | if(mh->error_protection) mi->flags |= MPG123_CRC; |
630 | if(mh->error_protection) mi->flags |= MPG123_CRC; |
525 | if(mh->copyright) mi->flags |= MPG123_COPYRIGHT; |
631 | if(mh->copyright) mi->flags |= MPG123_COPYRIGHT; |
526 | if(mh->extension) mi->flags |= MPG123_PRIVATE; |
632 | if(mh->extension) mi->flags |= MPG123_PRIVATE; |
527 | if(mh->original) mi->flags |= MPG123_ORIGINAL; |
633 | if(mh->original) mi->flags |= MPG123_ORIGINAL; |
528 | mi->emphasis = mh->emphasis; |
634 | mi->emphasis = mh->emphasis; |
529 | mi->bitrate = frame_bitrate(mh); |
635 | mi->bitrate = frame_bitrate(mh); |
530 | mi->abr_rate = mh->abr_rate; |
636 | mi->abr_rate = mh->abr_rate; |
531 | mi->vbr = mh->vbr; |
637 | mi->vbr = mh->vbr; |
532 | return MPG123_OK; |
638 | return MPG123_OK; |
533 | } |
639 | } |
- | 640 | ||
- | 641 | int attribute_align_arg mpg123_framedata(mpg123_handle *mh, unsigned long *header, unsigned char **bodydata, size_t *bodybytes) |
|
- | 642 | { |
|
- | 643 | if(mh == NULL) return MPG123_ERR; |
|
- | 644 | if(!mh->to_decode) return MPG123_ERR; |
|
- | 645 | ||
- | 646 | if(header != NULL) *header = mh->oldhead; |
|
- | 647 | if(bodydata != NULL) *bodydata = mh->bsbuf; |
|
- | 648 | if(bodybytes != NULL) *bodybytes = mh->framesize; |
|
- | 649 | ||
- | 650 | return MPG123_OK; |
|
534 | 651 | } |
|
535 | 652 | ||
536 | /* |
653 | /* |
537 | Fuzzy frame offset searching (guessing). |
654 | Fuzzy frame offset searching (guessing). |
538 | When we don't have an accurate position, we may use an inaccurate one. |
655 | When we don't have an accurate position, we may use an inaccurate one. |
539 | Possibilities: |
656 | Possibilities: |
540 | - use approximate positions from Xing TOC (not yet parsed) |
657 | - use approximate positions from Xing TOC (not yet parsed) |
541 | - guess wildly from mean framesize and offset of first frame / beginning of file. |
658 | - guess wildly from mean framesize and offset of first frame / beginning of file. |
542 | */ |
659 | */ |
543 | 660 | ||
544 | off_t frame_fuzzy_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) |
661 | static off_t frame_fuzzy_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) |
545 | { |
662 | { |
546 | /* Default is to go to the beginning. */ |
663 | /* Default is to go to the beginning. */ |
547 | off_t ret = fr->audio_start; |
664 | off_t ret = fr->audio_start; |
548 | *get_frame = 0; |
665 | *get_frame = 0; |
549 | 666 | ||
550 | /* But we try to find something better. */ |
667 | /* But we try to find something better. */ |
551 | /* Xing VBR TOC works with relative positions, both in terms of audio frames and stream bytes. |
668 | /* Xing VBR TOC works with relative positions, both in terms of audio frames and stream bytes. |
552 | Thus, it only works when whe know the length of things. |
669 | Thus, it only works when whe know the length of things. |
553 | Oh... I assume the offsets are relative to the _total_ file length. */ |
670 | Oh... I assume the offsets are relative to the _total_ file length. */ |
554 | if(fr->xing_toc != NULL && fr->track_frames > 0 && fr->rdat.filelen > 0) |
671 | if(fr->xing_toc != NULL && fr->track_frames > 0 && fr->rdat.filelen > 0) |
555 | { |
672 | { |
556 | /* One could round... */ |
673 | /* One could round... */ |
557 | int toc_entry = (int) ((double)want_frame*100./fr->track_frames); |
674 | int toc_entry = (int) ((double)want_frame*100./fr->track_frames); |
558 | /* It is an index in the 100-entry table. */ |
675 | /* It is an index in the 100-entry table. */ |
559 | if(toc_entry < 0) toc_entry = 0; |
676 | if(toc_entry < 0) toc_entry = 0; |
560 | if(toc_entry > 99) toc_entry = 99; |
677 | if(toc_entry > 99) toc_entry = 99; |
561 | 678 | ||
562 | /* Now estimate back what frame we get. */ |
679 | /* Now estimate back what frame we get. */ |
563 | *get_frame = (off_t) ((double)toc_entry/100. * fr->track_frames); |
680 | *get_frame = (off_t) ((double)toc_entry/100. * fr->track_frames); |
564 | fr->accurate = FALSE; |
681 | fr->state_flags &= ~FRAME_ACCURATE; |
565 | fr->silent_resync = 1; |
682 | fr->silent_resync = 1; |
566 | /* Question: Is the TOC for whole file size (with/without ID3) or the "real" audio data only? |
683 | /* Question: Is the TOC for whole file size (with/without ID3) or the "real" audio data only? |
567 | ID3v1 info could also matter. */ |
684 | ID3v1 info could also matter. */ |
568 | ret = (off_t) ((double)fr->xing_toc[toc_entry]/256.* fr->rdat.filelen); |
685 | ret = (off_t) ((double)fr->xing_toc[toc_entry]/256.* fr->rdat.filelen); |
569 | } |
686 | } |
570 | else if(fr->mean_framesize > 0) |
687 | else if(fr->mean_framesize > 0) |
571 | { /* Just guess with mean framesize (may be exact with CBR files). */ |
688 | { /* Just guess with mean framesize (may be exact with CBR files). */ |
572 | /* Query filelen here or not? */ |
689 | /* Query filelen here or not? */ |
573 | fr->accurate = FALSE; /* Fuzzy! */ |
690 | fr->state_flags &= ~FRAME_ACCURATE; /* Fuzzy! */ |
574 | fr->silent_resync = 1; |
691 | fr->silent_resync = 1; |
575 | *get_frame = want_frame; |
692 | *get_frame = want_frame; |
576 | ret = (off_t) (fr->audio_start+fr->mean_framesize*want_frame); |
693 | ret = (off_t) (fr->audio_start+fr->mean_framesize*want_frame); |
577 | } |
694 | } |
578 | debug5("fuzzy: want %li of %li, get %li at %li B of %li B", |
695 | debug5("fuzzy: want %li of %li, get %li at %li B of %li B", |
579 | (long)want_frame, (long)fr->track_frames, (long)*get_frame, (long)ret, (long)(fr->rdat.filelen-fr->audio_start)); |
696 | (long)want_frame, (long)fr->track_frames, (long)*get_frame, (long)ret, (long)(fr->rdat.filelen-fr->audio_start)); |
580 | return ret; |
697 | return ret; |
581 | } |
698 | } |
582 | 699 | ||
583 | /* |
700 | /* |
584 | find the best frame in index just before the wanted one, seek to there |
701 | find the best frame in index just before the wanted one, seek to there |
585 | then step to just before wanted one with read_frame |
702 | then step to just before wanted one with read_frame |
586 | do not care tabout the stuff that was in buffer but not played back |
703 | do not care tabout the stuff that was in buffer but not played back |
587 | everything that left the decoder is counted as played |
704 | everything that left the decoder is counted as played |
588 | 705 | ||
589 | Decide if you want low latency reaction and accurate timing info or stable long-time playback with buffer! |
706 | Decide if you want low latency reaction and accurate timing info or stable long-time playback with buffer! |
590 | */ |
707 | */ |
591 | 708 | ||
592 | off_t frame_index_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) |
709 | off_t frame_index_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) |
593 | { |
710 | { |
594 | /* default is file start if no index position */ |
711 | /* default is file start if no index position */ |
595 | off_t gopos = 0; |
712 | off_t gopos = 0; |
596 | *get_frame = 0; |
713 | *get_frame = 0; |
597 | #ifdef FRAME_INDEX |
714 | #ifdef FRAME_INDEX |
598 | /* Possibly use VBRI index, too? I'd need an example for this... */ |
715 | /* Possibly use VBRI index, too? I'd need an example for this... */ |
599 | if(fr->index.fill) |
716 | if(fr->index.fill) |
600 | { |
717 | { |
601 | /* find in index */ |
718 | /* find in index */ |
602 | size_t fi; |
719 | size_t fi; |
603 | /* at index fi there is frame step*fi... */ |
720 | /* at index fi there is frame step*fi... */ |
604 | fi = want_frame/fr->index.step; |
721 | fi = want_frame/fr->index.step; |
605 | if(fi >= fr->index.fill) /* If we are beyond the end of frame index...*/ |
722 | if(fi >= fr->index.fill) /* If we are beyond the end of frame index...*/ |
606 | { |
723 | { |
607 | /* When fuzzy seek is allowed, we have some limited tolerance for the frames we want to read rather then jump over. */ |
724 | /* When fuzzy seek is allowed, we have some limited tolerance for the frames we want to read rather then jump over. */ |
608 | if(fr->p.flags & MPG123_FUZZY && want_frame - (fr->index.fill-1)*fr->index.step > 10) |
725 | if(fr->p.flags & MPG123_FUZZY && want_frame - (fr->index.fill-1)*fr->index.step > 10) |
609 | { |
726 | { |
610 | gopos = frame_fuzzy_find(fr, want_frame, get_frame); |
727 | gopos = frame_fuzzy_find(fr, want_frame, get_frame); |
611 | if(gopos > fr->audio_start) return gopos; /* Only in that case, we have a useful guess. */ |
728 | if(gopos > fr->audio_start) return gopos; /* Only in that case, we have a useful guess. */ |
612 | /* Else... just continue, fuzzyness didn't help. */ |
729 | /* Else... just continue, fuzzyness didn't help. */ |
613 | } |
730 | } |
614 | /* Use the last available position, slowly advancing from that one. */ |
731 | /* Use the last available position, slowly advancing from that one. */ |
615 | fi = fr->index.fill - 1; |
732 | fi = fr->index.fill - 1; |
616 | } |
733 | } |
617 | /* We have index position, that yields frame and byte offsets. */ |
734 | /* We have index position, that yields frame and byte offsets. */ |
618 | *get_frame = fi*fr->index.step; |
735 | *get_frame = fi*fr->index.step; |
619 | gopos = fr->index.data[fi]; |
736 | gopos = fr->index.data[fi]; |
620 | fr->accurate = TRUE; /* When using the frame index, we are accurate. */ |
737 | fr->state_flags |= FRAME_ACCURATE; /* When using the frame index, we are accurate. */ |
621 | } |
738 | } |
622 | else |
739 | else |
623 | { |
740 | { |
624 | #endif |
741 | #endif |
625 | if(fr->p.flags & MPG123_FUZZY) |
742 | if(fr->p.flags & MPG123_FUZZY) |
626 | return frame_fuzzy_find(fr, want_frame, get_frame); |
743 | return frame_fuzzy_find(fr, want_frame, get_frame); |
627 | /* A bit hackish here... but we need to be fresh when looking for the first header again. */ |
744 | /* A bit hackish here... but we need to be fresh when looking for the first header again. */ |
628 | fr->firsthead = 0; |
745 | fr->firsthead = 0; |
629 | fr->oldhead = 0; |
746 | fr->oldhead = 0; |
630 | #ifdef FRAME_INDEX |
747 | #ifdef FRAME_INDEX |
631 | } |
748 | } |
632 | #endif |
749 | #endif |
633 | debug2("index: 0x%lx for frame %li", (unsigned long)gopos, (long) *get_frame); |
750 | debug2("index: 0x%lx for frame %li", (unsigned long)gopos, (long) *get_frame); |
634 | return gopos; |
751 | return gopos; |
635 | } |
752 | } |
636 | 753 | ||
637 | off_t frame_ins2outs(mpg123_handle *fr, off_t ins) |
754 | off_t frame_ins2outs(mpg123_handle *fr, off_t ins) |
638 | { |
755 | { |
639 | off_t outs = 0; |
756 | off_t outs = 0; |
640 | switch(fr->down_sample) |
757 | switch(fr->down_sample) |
641 | { |
758 | { |
642 | case 0: |
759 | case 0: |
643 | # ifndef NO_DOWNSAMPLE |
760 | # ifndef NO_DOWNSAMPLE |
644 | case 1: |
761 | case 1: |
645 | case 2: |
762 | case 2: |
646 | # endif |
763 | # endif |
647 | outs = ins>>fr->down_sample; |
764 | outs = ins>>fr->down_sample; |
648 | break; |
765 | break; |
649 | # ifndef NO_NTOM |
766 | # ifndef NO_NTOM |
650 | case 3: outs = ntom_ins2outs(fr, ins); break; |
767 | case 3: outs = ntom_ins2outs(fr, ins); break; |
651 | # endif |
768 | # endif |
652 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
769 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
653 | } |
770 | } |
654 | return outs; |
771 | return outs; |
655 | } |
772 | } |
656 | 773 | ||
657 | off_t frame_outs(mpg123_handle *fr, off_t num) |
774 | off_t frame_outs(mpg123_handle *fr, off_t num) |
658 | { |
775 | { |
659 | off_t outs = 0; |
776 | off_t outs = 0; |
660 | switch(fr->down_sample) |
777 | switch(fr->down_sample) |
661 | { |
778 | { |
662 | case 0: |
779 | case 0: |
663 | # ifndef NO_DOWNSAMPLE |
780 | # ifndef NO_DOWNSAMPLE |
664 | case 1: |
781 | case 1: |
665 | case 2: |
782 | case 2: |
666 | # endif |
783 | # endif |
667 | outs = (spf(fr)>>fr->down_sample)*num; |
784 | outs = (spf(fr)>>fr->down_sample)*num; |
668 | break; |
785 | break; |
669 | #ifndef NO_NTOM |
786 | #ifndef NO_NTOM |
670 | case 3: outs = ntom_frmouts(fr, num); break; |
787 | case 3: outs = ntom_frmouts(fr, num); break; |
671 | #endif |
788 | #endif |
672 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
789 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
673 | } |
790 | } |
674 | return outs; |
791 | return outs; |
675 | } |
792 | } |
- | 793 | ||
- | 794 | /* Compute the number of output samples we expect from this frame. |
|
- | 795 | This is either simple spf() or a tad more elaborate for ntom. */ |
|
- | 796 | off_t frame_expect_outsamples(mpg123_handle *fr) |
|
- | 797 | { |
|
- | 798 | off_t outs = 0; |
|
- | 799 | switch(fr->down_sample) |
|
- | 800 | { |
|
- | 801 | case 0: |
|
- | 802 | # ifndef NO_DOWNSAMPLE |
|
- | 803 | case 1: |
|
- | 804 | case 2: |
|
- | 805 | # endif |
|
- | 806 | outs = spf(fr)>>fr->down_sample; |
|
- | 807 | break; |
|
- | 808 | #ifndef NO_NTOM |
|
- | 809 | case 3: outs = ntom_frame_outsamples(fr); break; |
|
- | 810 | #endif |
|
- | 811 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
|
- | 812 | } |
|
- | 813 | return outs; |
|
- | 814 | } |
|
676 | 815 | ||
677 | off_t frame_offset(mpg123_handle *fr, off_t outs) |
816 | off_t frame_offset(mpg123_handle *fr, off_t outs) |
678 | { |
817 | { |
679 | off_t num = 0; |
818 | off_t num = 0; |
680 | switch(fr->down_sample) |
819 | switch(fr->down_sample) |
681 | { |
820 | { |
682 | case 0: |
821 | case 0: |
683 | # ifndef NO_DOWNSAMPLE |
822 | # ifndef NO_DOWNSAMPLE |
684 | case 1: |
823 | case 1: |
685 | case 2: |
824 | case 2: |
686 | # endif |
825 | # endif |
687 | num = outs/(spf(fr)>>fr->down_sample); |
826 | num = outs/(spf(fr)>>fr->down_sample); |
688 | break; |
827 | break; |
689 | #ifndef NO_NTOM |
828 | #ifndef NO_NTOM |
690 | case 3: num = ntom_frameoff(fr, outs); break; |
829 | case 3: num = ntom_frameoff(fr, outs); break; |
691 | #endif |
830 | #endif |
692 | default: error("Bad down_sample ... should not be possible!!"); |
831 | default: error("Bad down_sample ... should not be possible!!"); |
693 | } |
832 | } |
694 | return num; |
833 | return num; |
695 | } |
834 | } |
696 | 835 | ||
697 | #ifdef GAPLESS |
836 | #ifdef GAPLESS |
698 | /* input in _input_ samples */ |
837 | /* input in _input_ samples */ |
699 | void frame_gapless_init(mpg123_handle *fr, off_t b, off_t e) |
838 | void frame_gapless_init(mpg123_handle *fr, off_t framecount, off_t bskip, off_t eskip) |
- | 839 | { |
|
- | 840 | debug3("frame_gaples_init: given %"OFF_P" frames, skip %"OFF_P" and %"OFF_P, (off_p)framecount, (off_p)bskip, (off_p)eskip); |
|
- | 841 | fr->gapless_frames = framecount; |
|
- | 842 | if(fr->gapless_frames > 0) |
|
700 | { |
843 | { |
701 | fr->begin_s = b; |
844 | fr->begin_s = bskip+GAPLESS_DELAY; |
- | 845 | fr->end_s = framecount*spf(fr)-eskip+GAPLESS_DELAY; |
|
- | 846 | } |
|
702 | fr->end_s = e; |
847 | else fr->begin_s = fr->end_s = 0; |
703 | /* These will get proper values later, from above plus resampling info. */ |
848 | /* These will get proper values later, from above plus resampling info. */ |
704 | fr->begin_os = 0; |
849 | fr->begin_os = 0; |
705 | fr->end_os = 0; |
850 | fr->end_os = 0; |
- | 851 | fr->fullend_os = 0; |
|
706 | debug2("frame_gapless_init: from %lu to %lu samples", (long unsigned)fr->begin_s, (long unsigned)fr->end_s); |
852 | debug2("frame_gapless_init: from %"OFF_P" to %"OFF_P" samples", (off_p)fr->begin_s, (off_p)fr->end_s); |
707 | } |
853 | } |
708 | 854 | ||
709 | void frame_gapless_realinit(mpg123_handle *fr) |
855 | void frame_gapless_realinit(mpg123_handle *fr) |
710 | { |
856 | { |
711 | fr->begin_os = frame_ins2outs(fr, fr->begin_s); |
857 | fr->begin_os = frame_ins2outs(fr, fr->begin_s); |
712 | fr->end_os = frame_ins2outs(fr, fr->end_s); |
858 | fr->end_os = frame_ins2outs(fr, fr->end_s); |
- | 859 | fr->fullend_os = frame_ins2outs(fr, fr->gapless_frames*spf(fr)); |
|
713 | debug2("frame_gapless_realinit: from %lu to %lu samples", (long unsigned)fr->begin_os, (long unsigned)fr->end_os); |
860 | debug2("frame_gapless_realinit: from %"OFF_P" to %"OFF_P" samples", (off_p)fr->begin_os, (off_p)fr->end_os); |
714 | } |
861 | } |
715 | 862 | ||
716 | /* When we got a new sample count, update the gaplessness. */ |
863 | /* At least note when there is trouble... */ |
717 | void frame_gapless_update(mpg123_handle *fr, off_t total_samples) |
864 | void frame_gapless_update(mpg123_handle *fr, off_t total_samples) |
- | 865 | { |
|
- | 866 | off_t gapless_samples = fr->gapless_frames*spf(fr); |
|
- | 867 | debug2("gapless update with new sample count %"OFF_P" as opposed to known %"OFF_P, total_samples, gapless_samples); |
|
- | 868 | if(NOQUIET && total_samples != gapless_samples) |
|
- | 869 | fprintf(stderr, "\nWarning: Real sample count differs from given gapless sample count. Frankenstein stream?\n"); |
|
718 | { |
870 | |
719 | if(fr->end_s < 1) |
871 | if(gapless_samples > total_samples) |
- | 872 | { |
|
- | 873 | if(NOQUIET) error2("End sample count smaller than gapless end! (%"OFF_P" < %"OFF_P"). Disabling gapless mode from now on.", (off_p)total_samples, (off_p)fr->end_s); |
|
720 | { |
874 | /* This invalidates the current position... but what should I do? */ |
721 | fr->end_s = total_samples; |
875 | frame_gapless_init(fr, -1, 0, 0); |
722 | frame_gapless_realinit(fr); |
- | |
723 | } |
876 | frame_gapless_realinit(fr); |
724 | else if(fr->end_s > total_samples) |
- | |
725 | { |
- | |
726 | if(NOQUIET) error2("end sample count smaller than gapless end! (%"OFF_P" < %"OFF_P").", (off_p)total_samples, (off_p)fr->end_s); |
877 | fr->lastframe = -1; |
727 | fr->end_s = total_samples; |
878 | fr->lastoff = 0; |
728 | } |
879 | } |
729 | } |
880 | } |
730 | 881 | ||
731 | #endif |
882 | #endif |
732 | 883 | ||
733 | /* Compute the needed frame to ignore from, for getting accurate/consistent output for intended firstframe. */ |
884 | /* Compute the needed frame to ignore from, for getting accurate/consistent output for intended firstframe. */ |
734 | static off_t ignoreframe(mpg123_handle *fr) |
885 | static off_t ignoreframe(mpg123_handle *fr) |
735 | { |
886 | { |
736 | off_t preshift = fr->p.preframes; |
887 | off_t preshift = fr->p.preframes; |
737 | /* Layer 3 _really_ needs at least one frame before. */ |
888 | /* Layer 3 _really_ needs at least one frame before. */ |
738 | if(fr->lay==3 && preshift < 1) preshift = 1; |
889 | if(fr->lay==3 && preshift < 1) preshift = 1; |
739 | /* Layer 1 & 2 reall do not need more than 2. */ |
890 | /* Layer 1 & 2 reall do not need more than 2. */ |
740 | if(fr->lay!=3 && preshift > 2) preshift = 2; |
891 | if(fr->lay!=3 && preshift > 2) preshift = 2; |
741 | 892 | ||
742 | return fr->firstframe - preshift; |
893 | return fr->firstframe - preshift; |
743 | } |
894 | } |
744 | 895 | ||
745 | /* The frame seek... This is not simply the seek to fe*spf(fr) samples in output because we think of _input_ frames here. |
896 | /* The frame seek... This is not simply the seek to fe*spf(fr) samples in output because we think of _input_ frames here. |
746 | Seek to frame offset 1 may be just seek to 200 samples offset in output since the beginning of first frame is delay/padding. |
897 | Seek to frame offset 1 may be just seek to 200 samples offset in output since the beginning of first frame is delay/padding. |
747 | Hm, is that right? OK for the padding stuff, but actually, should the decoder delay be better totally hidden or not? |
898 | Hm, is that right? OK for the padding stuff, but actually, should the decoder delay be better totally hidden or not? |
748 | With gapless, even the whole frame position could be advanced further than requested (since Homey don't play dat). */ |
899 | With gapless, even the whole frame position could be advanced further than requested (since Homey don't play dat). */ |
749 | void frame_set_frameseek(mpg123_handle *fr, off_t fe) |
900 | void frame_set_frameseek(mpg123_handle *fr, off_t fe) |
750 | { |
901 | { |
751 | fr->firstframe = fe; |
902 | fr->firstframe = fe; |
752 | #ifdef GAPLESS |
903 | #ifdef GAPLESS |
753 | if(fr->p.flags & MPG123_GAPLESS) |
904 | if(fr->p.flags & MPG123_GAPLESS && fr->gapless_frames > 0) |
754 | { |
905 | { |
755 | /* Take care of the beginning... */ |
906 | /* Take care of the beginning... */ |
756 | off_t beg_f = frame_offset(fr, fr->begin_os); |
907 | off_t beg_f = frame_offset(fr, fr->begin_os); |
757 | if(fe <= beg_f) |
908 | if(fe <= beg_f) |
758 | { |
909 | { |
759 | fr->firstframe = beg_f; |
910 | fr->firstframe = beg_f; |
760 | fr->firstoff = fr->begin_os - frame_outs(fr, beg_f); |
911 | fr->firstoff = fr->begin_os - frame_outs(fr, beg_f); |
761 | } |
912 | } |
762 | else fr->firstoff = 0; |
913 | else fr->firstoff = 0; |
763 | /* The end is set once for a track at least, on the frame_set_frameseek called in get_next_frame() */ |
914 | /* The end is set once for a track at least, on the frame_set_frameseek called in get_next_frame() */ |
764 | if(fr->end_os > 0) |
915 | if(fr->end_os > 0) |
765 | { |
916 | { |
766 | fr->lastframe = frame_offset(fr,fr->end_os); |
917 | fr->lastframe = frame_offset(fr,fr->end_os); |
767 | fr->lastoff = fr->end_os - frame_outs(fr, fr->lastframe); |
918 | fr->lastoff = fr->end_os - frame_outs(fr, fr->lastframe); |
768 | } else fr->lastoff = 0; |
919 | } else {fr->lastframe = -1; fr->lastoff = 0; } |
769 | } else { fr->firstoff = fr->lastoff = 0; fr->lastframe = -1; } |
920 | } else { fr->firstoff = fr->lastoff = 0; fr->lastframe = -1; } |
770 | #endif |
921 | #endif |
771 | fr->ignoreframe = ignoreframe(fr); |
922 | fr->ignoreframe = ignoreframe(fr); |
772 | #ifdef GAPLESS |
923 | #ifdef GAPLESS |
773 | debug5("frame_set_frameseek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", |
924 | debug5("frame_set_frameseek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", |
774 | (long) fr->firstframe, (long) fr->firstoff, |
925 | (long) fr->firstframe, (long) fr->firstoff, |
775 | (long) fr->lastframe, (long) fr->lastoff, (long) fr->ignoreframe); |
926 | (long) fr->lastframe, (long) fr->lastoff, (long) fr->ignoreframe); |
776 | #else |
927 | #else |
777 | debug3("frame_set_frameseek: begin at %li frames, end at %li; ignore from %li", |
928 | debug3("frame_set_frameseek: begin at %li frames, end at %li; ignore from %li", |
778 | (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe); |
929 | (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe); |
779 | #endif |
930 | #endif |
780 | } |
931 | } |
781 | 932 | ||
782 | void frame_skip(mpg123_handle *fr) |
933 | void frame_skip(mpg123_handle *fr) |
783 | { |
934 | { |
784 | #ifndef NO_LAYER3 |
935 | #ifndef NO_LAYER3 |
785 | if(fr->lay == 3) set_pointer(fr, 512); |
936 | if(fr->lay == 3) set_pointer(fr, 512); |
786 | #endif |
937 | #endif |
787 | } |
938 | } |
788 | 939 | ||
789 | /* Sample accurate seek prepare for decoder. */ |
940 | /* Sample accurate seek prepare for decoder. */ |
790 | /* This gets unadjusted output samples and takes resampling into account */ |
941 | /* This gets unadjusted output samples and takes resampling into account */ |
791 | void frame_set_seek(mpg123_handle *fr, off_t sp) |
942 | void frame_set_seek(mpg123_handle *fr, off_t sp) |
792 | { |
943 | { |
793 | fr->firstframe = frame_offset(fr, sp); |
944 | fr->firstframe = frame_offset(fr, sp); |
- | 945 | debug1("frame_set_seek: from %"OFF_P, fr->num); |
|
794 | #ifndef NO_NTOM |
946 | #ifndef NO_NTOM |
795 | if(fr->down_sample == 3) ntom_set_ntom(fr, fr->firstframe); |
947 | if(fr->down_sample == 3) ntom_set_ntom(fr, fr->firstframe); |
796 | #endif |
948 | #endif |
797 | fr->ignoreframe = ignoreframe(fr); |
949 | fr->ignoreframe = ignoreframe(fr); |
798 | #ifdef GAPLESS /* The sample offset is used for non-gapless mode, too! */ |
950 | #ifdef GAPLESS /* The sample offset is used for non-gapless mode, too! */ |
799 | fr->firstoff = sp - frame_outs(fr, fr->firstframe); |
951 | fr->firstoff = sp - frame_outs(fr, fr->firstframe); |
800 | debug5("frame_set_seek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", |
952 | debug5("frame_set_seek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", |
801 | (long) fr->firstframe, (long) fr->firstoff, |
953 | (long) fr->firstframe, (long) fr->firstoff, |
802 | (long) fr->lastframe, (long) fr->lastoff, (long) fr->ignoreframe); |
954 | (long) fr->lastframe, (long) fr->lastoff, (long) fr->ignoreframe); |
803 | #else |
955 | #else |
804 | debug3("frame_set_seek: begin at %li frames, end at %li; ignore from %li", |
956 | debug3("frame_set_seek: begin at %li frames, end at %li; ignore from %li", |
805 | (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe); |
957 | (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe); |
806 | #endif |
958 | #endif |
807 | } |
959 | } |
808 | 960 | ||
809 | int attribute_align_arg mpg123_volume_change(mpg123_handle *mh, double change) |
961 | int attribute_align_arg mpg123_volume_change(mpg123_handle *mh, double change) |
810 | { |
962 | { |
811 | if(mh == NULL) return MPG123_ERR; |
963 | if(mh == NULL) return MPG123_ERR; |
812 | return mpg123_volume(mh, change + (double) mh->p.outscale); |
964 | return mpg123_volume(mh, change + (double) mh->p.outscale); |
813 | } |
965 | } |
814 | 966 | ||
815 | int attribute_align_arg mpg123_volume(mpg123_handle *mh, double vol) |
967 | int attribute_align_arg mpg123_volume(mpg123_handle *mh, double vol) |
816 | { |
968 | { |
817 | if(mh == NULL) return MPG123_ERR; |
969 | if(mh == NULL) return MPG123_ERR; |
818 | 970 | ||
819 | if(vol >= 0) mh->p.outscale = vol; |
971 | if(vol >= 0) mh->p.outscale = vol; |
820 | else mh->p.outscale = 0.; |
972 | else mh->p.outscale = 0.; |
821 | 973 | ||
822 | do_rva(mh); |
974 | do_rva(mh); |
823 | return MPG123_OK; |
975 | return MPG123_OK; |
824 | } |
976 | } |
825 | 977 | ||
826 | static int get_rva(mpg123_handle *fr, double *peak, double *gain) |
978 | static int get_rva(mpg123_handle *fr, double *peak, double *gain) |
827 | { |
979 | { |
828 | double p = -1; |
980 | double p = -1; |
829 | double g = 0; |
981 | double g = 0; |
830 | int ret = 0; |
982 | int ret = 0; |
831 | if(fr->p.rva) |
983 | if(fr->p.rva) |
832 | { |
984 | { |
833 | int rt = 0; |
985 | int rt = 0; |
834 | /* Should one assume a zero RVA as no RVA? */ |
986 | /* Should one assume a zero RVA as no RVA? */ |
835 | if(fr->p.rva == 2 && fr->rva.level[1] != -1) rt = 1; |
987 | if(fr->p.rva == 2 && fr->rva.level[1] != -1) rt = 1; |
836 | if(fr->rva.level[rt] != -1) |
988 | if(fr->rva.level[rt] != -1) |
837 | { |
989 | { |
838 | p = fr->rva.peak[rt]; |
990 | p = fr->rva.peak[rt]; |
839 | g = fr->rva.gain[rt]; |
991 | g = fr->rva.gain[rt]; |
840 | ret = 1; /* Success. */ |
992 | ret = 1; /* Success. */ |
841 | } |
993 | } |
842 | } |
994 | } |
843 | if(peak != NULL) *peak = p; |
995 | if(peak != NULL) *peak = p; |
844 | if(gain != NULL) *gain = g; |
996 | if(gain != NULL) *gain = g; |
845 | return ret; |
997 | return ret; |
846 | } |
998 | } |
847 | 999 | ||
848 | /* adjust the volume, taking both fr->outscale and rva values into account */ |
1000 | /* adjust the volume, taking both fr->outscale and rva values into account */ |
849 | void do_rva(mpg123_handle *fr) |
1001 | void do_rva(mpg123_handle *fr) |
850 | { |
1002 | { |
851 | double peak = 0; |
1003 | double peak = 0; |
852 | double gain = 0; |
1004 | double gain = 0; |
853 | double newscale; |
1005 | double newscale; |
854 | double rvafact = 1; |
1006 | double rvafact = 1; |
855 | if(get_rva(fr, &peak, &gain)) |
1007 | if(get_rva(fr, &peak, &gain)) |
856 | { |
1008 | { |
857 | if(NOQUIET && fr->p.verbose > 1) fprintf(stderr, "Note: doing RVA with gain %f\n", gain); |
1009 | if(NOQUIET && fr->p.verbose > 1) fprintf(stderr, "Note: doing RVA with gain %f\n", gain); |
858 | rvafact = pow(10,gain/20); |
1010 | rvafact = pow(10,gain/20); |
859 | } |
1011 | } |
860 | 1012 | ||
861 | newscale = fr->p.outscale*rvafact; |
1013 | newscale = fr->p.outscale*rvafact; |
862 | 1014 | ||
863 | /* if peak is unknown (== 0) this check won't hurt */ |
1015 | /* if peak is unknown (== 0) this check won't hurt */ |
864 | if((peak*newscale) > 1.0) |
1016 | if((peak*newscale) > 1.0) |
865 | { |
1017 | { |
866 | newscale = 1.0/peak; |
1018 | newscale = 1.0/peak; |
867 | warning2("limiting scale value to %f to prevent clipping with indicated peak factor of %f", newscale, peak); |
1019 | warning2("limiting scale value to %f to prevent clipping with indicated peak factor of %f", newscale, peak); |
868 | } |
1020 | } |
869 | /* first rva setting is forced with fr->lastscale < 0 */ |
1021 | /* first rva setting is forced with fr->lastscale < 0 */ |
870 | if(newscale != fr->lastscale || fr->decoder_change) |
1022 | if(newscale != fr->lastscale || fr->decoder_change) |
871 | { |
1023 | { |
872 | debug3("changing scale value from %f to %f (peak estimated to %f)", fr->lastscale != -1 ? fr->lastscale : fr->p.outscale, newscale, (double) (newscale*peak)); |
1024 | debug3("changing scale value from %f to %f (peak estimated to %f)", fr->lastscale != -1 ? fr->lastscale : fr->p.outscale, newscale, (double) (newscale*peak)); |
873 | fr->lastscale = newscale; |
1025 | fr->lastscale = newscale; |
874 | /* It may be too early, actually. */ |
1026 | /* It may be too early, actually. */ |
875 | if(fr->make_decode_tables != NULL) fr->make_decode_tables(fr); /* the actual work */ |
1027 | if(fr->make_decode_tables != NULL) fr->make_decode_tables(fr); /* the actual work */ |
876 | } |
1028 | } |
877 | } |
1029 | } |
878 | 1030 | ||
879 | 1031 | ||
880 | int attribute_align_arg mpg123_getvolume(mpg123_handle *mh, double *base, double *really, double *rva_db) |
1032 | int attribute_align_arg mpg123_getvolume(mpg123_handle *mh, double *base, double *really, double *rva_db) |
881 | { |
1033 | { |
882 | if(mh == NULL) return MPG123_ERR; |
1034 | if(mh == NULL) return MPG123_ERR; |
883 | if(base) *base = mh->p.outscale; |
1035 | if(base) *base = mh->p.outscale; |
884 | if(really) *really = mh->lastscale; |
1036 | if(really) *really = mh->lastscale; |
885 | get_rva(mh, NULL, rva_db); |
1037 | get_rva(mh, NULL, rva_db); |
886 | return MPG123_OK; |
1038 | return MPG123_OK; |
887 | }>=>>>>>100;>>>4;>4;>>>> |
1039 | } |
- | 1040 | ||
- | 1041 | off_t attribute_align_arg mpg123_framepos(mpg123_handle *mh) |
|
- | 1042 | { |
|
- | 1043 | if(mh == NULL) return MPG123_ERR; |
|
- | 1044 | ||
- | 1045 | return mh->input_offset; |
|
- | 1046 | }>=>>>>100;>>4;>4;>>>> |