summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c') (more/less context) (show whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c536
1 files changed, 536 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c b/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c
new file mode 100644
index 0000000..e2d3912
--- a/dev/null
+++ b/core/multimedia/opieplayer/libmpeg3/audio/mpeg3audio.c
@@ -0,0 +1,536 @@
1#include "../libmpeg3.h"
2#include "../mpeg3protos.h"
3#include "mpeg3audio.h"
4#include "tables.h"
5
6#include <math.h>
7#include <stdlib.h>
8
9mpeg3audio_t* mpeg3audio_allocate_struct(mpeg3_t *file, mpeg3_atrack_t *track)
10{
11 mpeg3audio_t *audio = (mpeg3audio_t*)calloc(1, sizeof(mpeg3audio_t));
12 audio->file = file;
13 audio->track = track;
14 audio->astream = mpeg3bits_new_stream(file, track->demuxer);
15 audio->outscale = 1;
16 audio->bsbuf = audio->bsspace[1];
17 audio->init = 1;
18 audio->bo = 1;
19 audio->channels = 1;
20 return audio;
21}
22
23
24int mpeg3audio_delete_struct(mpeg3audio_t *audio)
25{
26 mpeg3bits_delete_stream(audio->astream);
27 if(audio->pcm_sample) free(audio->pcm_sample);
28 free(audio);
29 return 0;
30}
31
32int mpeg3audio_replace_buffer(mpeg3audio_t *audio, long new_allocation)
33{
34 long i;
35
36 audio->pcm_sample = (mpeg3_real_t*)realloc( audio->pcm_sample, sizeof(mpeg3_real_t) * new_allocation * audio->channels );
37 audio->pcm_allocated = new_allocation;
38/*
39 // Isn't this exactly the same as what the ANSI C function call realloc does,
40 // or did I miss C Programming 101 ?
41
42 if(!audio->pcm_sample)
43 {
44 audio->pcm_sample = (mpeg3_real_t*)malloc(sizeof(mpeg3_real_t) * new_allocation * audio->channels);
45 audio->pcm_allocated = new_allocation;
46 }
47 else
48 {
49 mpeg3_real_t *new_samples = (mpeg3_real_t*)malloc(sizeof(mpeg3_real_t) * new_allocation * audio->channels);
50 for(i = 0; i < audio->pcm_allocated * audio->channels; i++)
51 {
52 new_samples[i] = audio->pcm_sample[i];
53 }
54 free(audio->pcm_sample);
55 audio->pcm_sample = new_samples;
56 audio->pcm_allocated = new_allocation;
57 }
58*/
59 return 0;
60}
61
62int mpeg3audio_read_frame(mpeg3audio_t *audio)
63{
64 int result = 0;
65 result = mpeg3audio_read_header(audio);
66
67 if(!result)
68 {
69 switch(audio->format)
70 {
71 case AUDIO_AC3:
72 result = mpeg3audio_do_ac3(audio);
73 break;
74
75 case AUDIO_MPEG:
76 switch(audio->layer)
77 {
78 case 1:
79 break;
80
81 case 2:
82 result = mpeg3audio_dolayer2(audio);
83 break;
84
85 case 3:
86 result = mpeg3audio_dolayer3(audio);
87 break;
88
89 default:
90 result = 1;
91 break;
92 }
93 break;
94
95 case AUDIO_PCM:
96 result = mpeg3audio_do_pcm(audio);
97 break;
98 }
99 }
100
101 if(!result)
102 {
103/* Byte align the stream */
104 mpeg3bits_byte_align(audio->astream);
105 }
106 return result;
107}
108
109/* Get the length but also initialize the frame sizes. */
110int mpeg3audio_get_length(mpeg3audio_t *audio, mpeg3_atrack_t *track)
111{
112 long result = 0;
113 long framesize1 = 0, total1 = 0;
114 long framesize2 = 0, total2 = 0;
115 long total_framesize = 0, total_frames = 0;
116 long byte_limit = 131072; /* Total bytes to gather information from */
117 long total_bytes = 0;
118 long major_framesize; /* Bigger framesize + header */
119 long minor_framesize; /* Smaller framesize + header */
120 long major_total;
121 long minor_total;
122 mpeg3_t *file = audio->file;
123
124/* Get the frame sizes */
125 mpeg3bits_seek_start(audio->astream);
126 audio->pcm_point = 0;
127 result = mpeg3audio_read_frame(audio); /* Stores the framesize */
128 audio->samples_per_frame = audio->pcm_point / audio->channels;
129
130 switch(audio->format)
131 {
132 case AUDIO_AC3:
133 audio->avg_framesize = audio->framesize;
134 break;
135
136 case AUDIO_MPEG:
137 framesize1 = audio->framesize;
138 total_bytes += audio->framesize;
139 total1 = 1;
140
141 while(!result && total_bytes < byte_limit)
142 {
143 audio->pcm_point = 0;
144 result = mpeg3audio_read_frame(audio);
145 total_bytes += audio->framesize;
146 if(audio->framesize != framesize1)
147 {
148 framesize2 = audio->framesize;
149 total2 = 1;
150 break;
151 }
152 else
153 {
154 total1++;
155 }
156 }
157
158 while(!result && total_bytes < byte_limit)
159 {
160 audio->pcm_point = 0;
161 result = mpeg3audio_read_frame(audio);
162 total_bytes += audio->framesize;
163 if(audio->framesize != framesize2)
164 {
165 break;
166 }
167 else
168 {
169 total2++;
170 }
171 }
172
173 audio->pcm_point = 0;
174 result = mpeg3audio_read_frame(audio);
175 if(audio->framesize != framesize1 && audio->framesize != framesize2)
176 {
177/* Variable bit rate. Get the average frame size. */
178 while(!result && total_bytes < byte_limit)
179 {
180 audio->pcm_point = 0;
181 result = mpeg3audio_read_frame(audio);
182 total_bytes += audio->framesize;
183 if(!result)
184 {
185 total_framesize += audio->framesize;
186 total_frames++;
187 }
188 }
189 audio->avg_framesize = 4 + (total_framesize + framesize1 + framesize2) / (total_frames + total1 + total2);
190 }
191 else
192 {
193 major_framesize = framesize2 > framesize1 ? framesize2 : framesize1;
194 major_total = framesize2 > framesize1 ? total2 : total1;
195 minor_framesize = framesize2 > framesize1 ? framesize1 : framesize2;
196 minor_total = framesize2 > framesize1 ? total1 : total2;
197/* Add the headers to the framesizes */
198 audio->avg_framesize = 4 + (major_framesize * major_total + minor_framesize * minor_total) / (major_total + minor_total);
199 }
200 break;
201
202 case AUDIO_PCM:
203 break;
204 }
205
206/* Estimate the total samples */
207 if(file->is_audio_stream)
208 {
209/* From the raw file */
210 result = (long)((float)mpeg3demuxer_total_bytes(audio->astream->demuxer) / audio->avg_framesize * audio->samples_per_frame);
211 }
212 else
213 {
214/* Gross approximation from a multiplexed file. */
215 result = (long)(mpeg3demux_length(audio->astream->demuxer) * track->sample_rate);
216 /* result = (long)((mpeg3_real_t)mpeg3_video_frames(file, 0) / mpeg3_frame_rate(file, 0) * track->sample_rate); */
217/* We would scan the multiplexed packets here for the right timecode if only */
218/* they had meaningful timecode. */
219 }
220
221 audio->pcm_point = 0;
222 mpeg3bits_seek_start(audio->astream);
223 mpeg3audio_reset_synths(audio);
224 return result;
225}
226
227int mpeg3audio_seek(mpeg3audio_t *audio, long position)
228{
229 int result = 0;
230 mpeg3_t *file = audio->file;
231 mpeg3_atrack_t *track = audio->track;
232 long frame_number;
233 long byte_position;
234 double time_position;
235
236/* Sample seek wasn't requested */
237 if(audio->sample_seek < 0)
238 {
239 audio->pcm_position = position;
240 audio->pcm_size = 0;
241 return 0;
242 }
243
244/* Can't slide buffer. Seek instead. */
245 if(!file->is_audio_stream)
246 {
247/* Seek in a multiplexed stream using the multiplexer. */
248 time_position = (double)position / track->sample_rate;
249 result |= mpeg3bits_seek_time(audio->astream, time_position);
250 audio->pcm_position = (long)mpeg3bits_packet_time(audio->astream) * track->sample_rate;
251/*printf("wanted %f got %f\n", time_position, mpeg3bits_packet_time(audio->astream)); */
252 }
253 else
254 {
255/* Seek in an elemental stream. This algorithm achieves sample accuracy on fixed bitrates. */
256/* Forget about variable bitrates or program streams. */
257 frame_number = position / audio->samples_per_frame;
258 byte_position = (long)(audio->avg_framesize * frame_number);
259 audio->pcm_position = frame_number * audio->samples_per_frame;
260
261 if(byte_position < audio->avg_framesize * 2)
262 {
263 result |= mpeg3bits_seek_start(audio->astream);
264 audio->pcm_position = 0;
265 }
266 else
267 {
268 result |= mpeg3bits_seek_byte(audio->astream, byte_position);
269 }
270 }
271
272/* Arm the backstep buffer for layer 3 if not at the beginning already. */
273 if(byte_position >= audio->avg_framesize * 2 && audio->layer == 3 && !result)
274 {
275 result |= mpeg3audio_prev_header(audio);
276 result |= mpeg3audio_read_layer3_frame(audio);
277 }
278
279/* Reset the tables. */
280 mpeg3audio_reset_synths(audio);
281 audio->pcm_size = 0;
282 audio->pcm_point = 0;
283 return result;
284}
285
286/* ================================================================ */
287/* ENTRY POINTS */
288/* ================================================================ */
289
290
291
292
293mpeg3audio_t* mpeg3audio_new(mpeg3_t *file, mpeg3_atrack_t *track, int format)
294{
295 mpeg3audio_t *audio = mpeg3audio_allocate_struct(file, track);
296 int result = 0;
297
298/* Init tables */
299 mpeg3audio_new_decode_tables(audio);
300 audio->percentage_seek = -1;
301 audio->sample_seek = -1;
302 audio->format = format;
303
304/* Determine the format of the stream */
305 if(format == AUDIO_UNKNOWN)
306 {
307 if(((mpeg3bits_showbits(audio->astream, 32) & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE)
308 audio->format = AUDIO_AC3;
309 else
310 audio->format = AUDIO_MPEG;
311 }
312
313/* get channel count */
314 result = mpeg3audio_read_header(audio);
315
316/* Set up the sample buffer */
317 mpeg3audio_replace_buffer(audio, 262144);
318
319/* Copy information to the mpeg struct */
320 if(!result)
321 {
322 track->channels = audio->channels;
323
324 switch(audio->format)
325 {
326 case AUDIO_AC3:
327 track->sample_rate = mpeg3_ac3_samplerates[audio->sampling_frequency_code];
328 break;
329
330 case AUDIO_MPEG:
331 track->sample_rate = mpeg3_freqs[audio->sampling_frequency_code];
332 break;
333
334 case AUDIO_PCM:
335 track->sample_rate = 48000;
336 break;
337 }
338
339 track->total_samples = mpeg3audio_get_length(audio, track);
340 result |= mpeg3bits_seek_start(audio->astream);
341 }
342 else
343 {
344 mpeg3audio_delete_struct(audio);
345 audio = 0;
346 }
347
348 return audio;
349}
350
351int mpeg3audio_delete(mpeg3audio_t *audio)
352{
353 mpeg3audio_delete_struct(audio);
354 return 0;
355}
356
357int mpeg3audio_seek_percentage(mpeg3audio_t *audio, double percentage)
358{
359 audio->percentage_seek = percentage;
360 return 0;
361}
362
363int mpeg3audio_seek_sample(mpeg3audio_t *audio, long sample)
364{
365 audio->sample_seek = sample;
366 return 0;
367}
368
369/* Read raw frames for concatenation purposes */
370int mpeg3audio_read_raw(mpeg3audio_t *audio, unsigned char *output, long *size, long max_size)
371{
372 int result = 0;
373 int i;
374 *size = 0;
375
376 switch(audio->format)
377 {
378 case AUDIO_AC3:
379/* Just write the AC3 stream */
380 if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize))
381 return 1;
382 *size = audio->framesize;
383 break;
384
385 case AUDIO_MPEG:
386/* Fix the mpeg stream */
387 result = mpeg3audio_read_header(audio);
388 if(!result)
389 {
390 if(max_size < 4) return 1;
391 *output++ = (audio->newhead & 0xff000000) >> 24;
392 *output++ = (audio->newhead & 0xff0000) >> 16;
393 *output++ = (audio->newhead & 0xff00) >> 8;
394 *output++ = (audio->newhead & 0xff);
395 *size += 4;
396
397 if(max_size < 4 + audio->framesize) return 1;
398 if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize))
399 return 1;
400
401 *size += audio->framesize;
402 }
403 break;
404
405 case AUDIO_PCM:
406 if(mpeg3bits_read_buffer(audio->astream, output, audio->framesize))
407 return 1;
408 *size = audio->framesize;
409 break;
410 }
411 return result;
412}
413
414/* Channel is 0 to channels - 1 */
415int mpeg3audio_decode_audio(mpeg3audio_t *audio,
416 mpeg3_real_t *output_f,
417 short *output_i, int sampleSpacing,
418 int channel,
419 long start_position,
420 long len)
421{
422 long allocation_needed = len + MPEG3AUDIO_PADDING;
423 long i, j, result = 0;
424 mpeg3_t *file = audio->file;
425 mpeg3_atrack_t *atrack = audio->track;
426 long attempts;
427
428/* Create new buffer */
429 if(audio->pcm_allocated < allocation_needed)
430 {
431 mpeg3audio_replace_buffer(audio, allocation_needed);
432 }
433
434/* There was a percentage seek */
435 if(audio->percentage_seek >= 0)
436 {
437 mpeg3bits_seek_percentage(audio->astream, audio->percentage_seek);
438/* Force the pcm buffer to be reread. */
439 audio->pcm_position = start_position;
440 audio->pcm_size = 0;
441 audio->percentage_seek = -1;
442 }
443 else
444 {
445/* Entire output is in buffer so don't do anything. */
446 if(start_position >= audio->pcm_position && start_position < audio->pcm_position + audio->pcm_size &&
447 start_position + len <= audio->pcm_size)
448 {
449 ;
450 }
451 else
452/* Output starts in buffer but ends later so slide it back. */
453 if(start_position <= audio->pcm_position + audio->pcm_size &&
454 start_position >= audio->pcm_position)
455 {
456 for(i = 0, j = (start_position - audio->pcm_position) * audio->channels;
457 j < audio->pcm_size * audio->channels;
458 i++, j++)
459 {
460 audio->pcm_sample[i] = audio->pcm_sample[j];
461 }
462
463 audio->pcm_point = i;
464 audio->pcm_size -= start_position - audio->pcm_position;
465 audio->pcm_position = start_position;
466 }
467 else
468 {
469/* Output is outside buffer completely. */
470 result = mpeg3audio_seek(audio, start_position);
471 audio->sample_seek = -1;
472/* Check sanity */
473 if(start_position < audio->pcm_position) audio->pcm_position = start_position;
474 }
475 audio->sample_seek = -1;
476 }
477
478/* Read packets until the buffer is full. */
479 if(!result)
480 {
481 attempts = 0;
482 result = 1;
483 while(attempts < 6 &&
484 !mpeg3bits_eof(audio->astream) &&
485 audio->pcm_size + audio->pcm_position < start_position + len)
486 {
487 result = mpeg3audio_read_frame(audio);
488 if(result) attempts++;
489 audio->pcm_size = audio->pcm_point / audio->channels;
490 }
491 }
492
493
494
495/* Copy the buffer to the output */
496 if(output_f)
497 {
498 for(i = 0, j = (start_position - audio->pcm_position) * audio->channels + channel;
499 i < len && j < audio->pcm_size * audio->channels;
500 i++, j += audio->channels)
501 {
502 output_f[i] = audio->pcm_sample[j];
503 }
504 for( ; i < len; i++)
505 {
506 output_f[i] = 0;
507 }
508 }
509 else
510 if(output_i)
511 {
512 int sample;
513 for(i = 0, j = (start_position - audio->pcm_position) * audio->channels + channel;
514 i < (len*(sampleSpacing+1)) && j < audio->pcm_size * audio->channels;
515 i++, j += audio->channels)
516 {
517 sample = (int)(audio->pcm_sample[j] * 32767);
518 if(sample > 32767) sample = 32767;
519 else
520 if(sample < -32768) sample = -32768;
521
522 output_i[i] = sample;
523 i += sampleSpacing;
524 }
525 for( ; i < (len*(sampleSpacing+1)); i++)
526 {
527 output_i[i] = 0;
528 i += sampleSpacing;
529 }
530 }
531
532 if(audio->pcm_point > 0)
533 return 0;
534 else
535 return result;
536}