FS#6948 - Fix the broken 'follow playlist' feature
[Rockbox.git] / apps / codecs / alac.c
blobbedd2dd5819e1c744635da1e564fc3163d7fa99d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Dave Chapman
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "codeclib.h"
21 #include "libm4a/m4a.h"
22 #include "libalac/decomp.h"
24 CODEC_HEADER
26 int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR;
28 /* this is the codec entry point */
29 enum codec_status codec_main(void)
31 size_t n;
32 demux_res_t demux_res;
33 stream_t input_stream;
34 uint32_t samplesdone;
35 uint32_t elapsedtime;
36 uint32_t sample_duration;
37 uint32_t sample_byte_size;
38 int samplesdecoded;
39 unsigned int i;
40 unsigned char* buffer;
41 alac_file alac;
42 int retval;
44 /* Generic codec initialisation */
45 ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
46 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, 1024*128);
48 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
49 ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1);
51 next_track:
53 if (codec_init()) {
54 LOGF("ALAC: Error initialising codec\n");
55 retval = CODEC_ERROR;
56 goto exit;
59 while (!*ci->taginfo_ready && !ci->stop_codec)
60 ci->sleep(1);
62 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
63 codec_set_replaygain(ci->id3);
65 stream_create(&input_stream,ci);
67 /* if qtmovie_read returns successfully, the stream is up to
68 * the movie data, which can be used directly by the decoder */
69 if (!qtmovie_read(&input_stream, &demux_res)) {
70 LOGF("ALAC: Error initialising file\n");
71 retval = CODEC_ERROR;
72 goto done;
75 /* initialise the sound converter */
76 create_alac(demux_res.sound_sample_size, demux_res.num_channels,&alac);
77 alac_set_info(&alac, demux_res.codecdata);
79 i=0;
80 samplesdone=0;
81 /* The main decoding loop */
82 while (i < demux_res.num_sample_byte_sizes) {
83 ci->yield();
84 if (ci->stop_codec || ci->new_track) {
85 break;
88 /* Deal with any pending seek requests */
89 if (ci->seek_time) {
90 if (alac_seek(&demux_res, &input_stream,
91 ((ci->seek_time-1)/10) * (ci->id3->frequency/100),
92 &samplesdone, (int *)&i)) {
93 elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
94 ci->set_elapsed(elapsedtime);
96 ci->seek_complete();
99 /* Lookup the length (in samples and bytes) of block i */
100 if (!get_sample_info(&demux_res, i, &sample_duration,
101 &sample_byte_size)) {
102 LOGF("ALAC: Error in get_sample_info\n");
103 retval = CODEC_ERROR;
104 goto done;
107 /* Request the required number of bytes from the input buffer */
109 buffer=ci->request_buffer(&n,sample_byte_size);
110 if (n!=sample_byte_size) {
111 retval = CODEC_ERROR;
112 goto done;
115 /* Decode one block - returned samples will be host-endian */
116 ci->yield();
117 samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield);
119 /* Advance codec buffer n bytes */
120 ci->advance_buffer(n);
122 /* Output the audio */
123 ci->yield();
124 ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded);
126 /* Update the elapsed-time indicator */
127 samplesdone+=sample_duration;
128 elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
129 ci->set_elapsed(elapsedtime);
131 /* Keep track of current position - for resuming */
132 ci->set_offset(elapsedtime);
134 i++;
136 retval = CODEC_OK;
138 done:
139 LOGF("ALAC: Decoded %ld samples\n",samplesdone);
141 if (ci->request_next_track())
142 goto next_track;
144 exit:
145 return retval;