FS#9728: Battery current measuring on the Video iPod
[kugel-rb.git] / apps / codecs / atrac3_rm.c
blob75c0d1581bac761ac93406147aeb479239eb8026
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * Copyright (C) 2009 Mohamed Tarek
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <string.h>
22 #include "logf.h"
23 #include "codeclib.h"
24 #include "inttypes.h"
25 #include "libatrac/atrac3.h"
27 CODEC_HEADER
29 RMContext rmctx;
30 RMPacket pkt;
31 ATRAC3Context q IBSS_ATTR;
33 static void init_rm(RMContext *rmctx)
35 memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
38 /* this is the codec entry point */
39 enum codec_status codec_main(void)
41 static size_t buff_size;
42 int datasize, res, consumed, i, time_offset;
43 uint8_t *bit_buffer;
44 uint16_t fs,sps,h;
45 uint32_t packet_count;
46 int scrambling_unit_size, num_units, elapsed = 0;
47 int playback_on = -1;
49 next_track:
50 if (codec_init()) {
51 DEBUGF("codec init failed\n");
52 return CODEC_ERROR;
54 while (!*ci->taginfo_ready && !ci->stop_codec)
55 ci->sleep(1);
57 codec_set_replaygain(ci->id3);
58 ci->memset(&rmctx,0,sizeof(RMContext));
59 ci->memset(&pkt,0,sizeof(RMPacket));
60 ci->memset(&q,0,sizeof(ATRAC3Context));
62 init_rm(&rmctx);
64 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
65 ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */
66 ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ?
67 STEREO_MONO : STEREO_NONINTERLEAVED);
69 packet_count = rmctx.nb_packets;
70 rmctx.audio_framesize = rmctx.block_align;
71 rmctx.block_align = rmctx.sub_packet_size;
72 fs = rmctx.audio_framesize;
73 sps= rmctx.block_align;
74 h = rmctx.sub_packet_h;
75 scrambling_unit_size = h*fs;
77 res =atrac3_decode_init(&q, &rmctx);
78 if(res < 0) {
79 DEBUGF("failed to initialize atrac decoder\n");
80 return CODEC_ERROR;
83 ci->set_elapsed(0);
84 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
86 /* The main decoder loop */
87 seek_start :
88 while((unsigned)elapsed < rmctx.duration)
90 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
91 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
92 if(consumed < 0 && playback_on != 0) {
93 if(playback_on == -1) {
94 /* Error only if packet-parsing failed and playback hadn't started */
95 DEBUGF("rm_get_packet failed\n");
96 return CODEC_ERROR;
98 else
99 goto done;
102 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
104 ci->yield();
105 if (ci->stop_codec || ci->new_track)
106 goto done;
108 if (ci->seek_time) {
109 ci->set_elapsed(ci->seek_time);
111 /* Do not allow seeking beyond the file's length */
112 if ((unsigned) ci->seek_time > ci->id3->length) {
113 ci->seek_complete();
114 goto done;
117 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
118 packet_count = rmctx.nb_packets;
119 rmctx.audio_pkt_cnt = 0;
120 rmctx.frame_number = 0;
122 /* Seek to the start of the track */
123 if (ci->seek_time == 1) {
124 ci->set_elapsed(0);
125 ci->seek_complete();
126 goto seek_start;
128 num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps));
129 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units);
130 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
131 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
132 if(consumed < 0 && playback_on != 0) {
133 if(playback_on == -1) {
134 /* Error only if packet-parsing failed and playback hadn't started */
135 DEBUGF("rm_get_packet failed\n");
136 return CODEC_ERROR;
138 else
139 goto done;
142 packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units;
143 rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate));
144 while(rmctx.audiotimestamp > (unsigned) ci->seek_time) {
145 rmctx.audio_pkt_cnt = 0;
146 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1));
147 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
148 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
149 packet_count += rmctx.audio_pkt_cnt;
150 num_units--;
152 time_offset = ci->seek_time - rmctx.audiotimestamp;
153 i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate));
154 elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i;
155 ci->set_elapsed(elapsed);
156 ci->seek_complete();
158 if(pkt.length)
159 res = atrac3_decode_frame(&rmctx, &q, &datasize, pkt.frames[i], rmctx.block_align);
160 else /* indicates that there are no remaining frames */
161 goto done;
163 if(res != rmctx.block_align) {
164 DEBUGF("codec error\n");
165 return CODEC_ERROR;
168 if(datasize)
169 ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, q.samples_per_frame / rmctx.nb_channels);
170 playback_on = 1;
171 elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i;
172 ci->set_elapsed(elapsed);
173 rmctx.frame_number++;
175 packet_count -= rmctx.audio_pkt_cnt;
176 rmctx.audio_pkt_cnt = 0;
177 ci->advance_buffer(consumed);
180 done :
181 if (ci->request_next_track())
182 goto next_track;
184 return CODEC_OK;