Initial 800x480 cabbiev2 port, based on 480x800x16 one
[kugel-rb.git] / apps / codecs / wma.c
bloba0950d4eb061a517bf92666462db8520e8d69a9d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "codeclib.h"
23 #include "libasf/asf.h"
24 #include "libwma/wmadec.h"
26 CODEC_HEADER
28 /* NOTE: WMADecodeContext is 120152 bytes (on x86) */
29 static WMADecodeContext wmadec;
31 /* this is the codec entry point */
32 enum codec_status codec_main(void)
34 uint32_t elapsedtime;
35 int retval;
36 asf_waveformatex_t wfx;
37 size_t resume_offset;
38 int i;
39 int wmares, res;
40 uint8_t* audiobuf;
41 int audiobufsize;
42 int packetlength = 0;
43 int errcount = 0;
45 /* Generic codec initialisation */
46 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
48 next_track:
50 /* Wait for the metadata to be read */
51 while (!*ci->taginfo_ready && !ci->stop_codec)
52 ci->sleep(1);
54 retval = CODEC_OK;
56 /* Remember the resume position - when the codec is opened, the
57 playback engine will reset it. */
58 resume_offset = ci->id3->offset;
59 restart_track:
60 if (codec_init()) {
61 LOGF("WMA: Error initialising codec\n");
62 retval = CODEC_ERROR;
63 goto exit;
66 /* Copy the format metadata we've stored in the id3 TOC field. This
67 saves us from parsing it again here. */
68 memcpy(&wfx, ci->id3->toc, sizeof(wfx));
70 if (wma_decode_init(&wmadec,&wfx) < 0) {
71 LOGF("WMA: Unsupported or corrupt file\n");
72 retval = CODEC_ERROR;
73 goto exit;
76 if (resume_offset > ci->id3->first_frame_offset)
78 /* Get start of current packet */
79 int packet_offset = (resume_offset - ci->id3->first_frame_offset)
80 % wfx.packet_size;
81 ci->seek_buffer(resume_offset - packet_offset);
82 elapsedtime = asf_get_timestamp(&i);
83 ci->set_elapsed(elapsedtime);
85 else
87 /* Now advance the file position to the first frame */
88 ci->seek_buffer(ci->id3->first_frame_offset);
89 elapsedtime = 0;
92 resume_offset = 0;
93 ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
94 ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
95 STEREO_MONO : STEREO_NONINTERLEAVED);
96 codec_set_replaygain(ci->id3);
98 /* The main decoding loop */
100 res = 1;
101 while (res >= 0)
103 ci->yield();
104 if (ci->stop_codec || ci->new_track) {
105 goto done;
108 /* Deal with any pending seek requests */
109 if (ci->seek_time){
111 if (ci->seek_time == 1) {
112 ci->seek_complete();
113 goto restart_track; /* Pretend you never saw this... */
116 elapsedtime = asf_seek(ci->seek_time, &wfx);
117 if (elapsedtime < 1){
118 ci->seek_complete();
119 goto next_track;
121 /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/
122 ci->set_elapsed(elapsedtime);
124 /*flush the wma decoder state*/
125 wmadec.last_superframe_len = 0;
126 wmadec.last_bitoffset = 0;
127 ci->seek_complete();
129 errcount = 0;
130 new_packet:
131 res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);
133 if (res < 0) {
134 /* We'll try to recover from a parse error a certain number of
135 * times. If we succeed, the error counter will be reset.
138 errcount++;
139 DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount);
140 if (errcount > 5) {
141 goto done;
142 } else {
143 ci->advance_buffer(packetlength);
144 goto new_packet;
146 } else if (res > 0) {
147 wma_decode_superframe_init(&wmadec, audiobuf, audiobufsize);
149 for (i=0; i < wmadec.nb_frames; i++)
151 wmares = wma_decode_superframe_frame(&wmadec,
152 audiobuf, audiobufsize);
154 ci->yield ();
156 if (wmares < 0) {
157 /* Do the above, but for errors in decode. */
158 errcount++;
159 DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount);
160 if (errcount > 5) {
161 goto done;
162 } else {
163 ci->advance_buffer(packetlength);
164 goto new_packet;
166 } else if (wmares > 0) {
167 ci->pcmbuf_insert((*wmadec.frame_out)[0], (*wmadec.frame_out)[1], wmares);
168 elapsedtime += (wmares*10)/(wfx.rate/100);
169 ci->set_elapsed(elapsedtime);
171 ci->yield();
175 ci->advance_buffer(packetlength);
177 retval = CODEC_OK;
179 done:
180 /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/
182 if (ci->request_next_track())
183 goto next_track;
184 exit:
185 return retval;