diff options
Diffstat (limited to 'lib/rbcodec/codecs/wmapro.c')
-rw-r--r-- | lib/rbcodec/codecs/wmapro.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/wmapro.c b/lib/rbcodec/codecs/wmapro.c new file mode 100644 index 0000000000..bab3b5a027 --- /dev/null +++ b/lib/rbcodec/codecs/wmapro.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Mohamed Tarek | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "codeclib.h" | ||
23 | #include "libasf/asf.h" | ||
24 | #include "libwmapro/wmaprodec.h" | ||
25 | |||
26 | CODEC_HEADER | ||
27 | |||
28 | static int32_t *dec[2]; /* pointers to the output buffers in WMAProDecodeCtx in | ||
29 | wmaprodec.c */ | ||
30 | |||
31 | |||
32 | /* this is the codec entry point */ | ||
33 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
34 | { | ||
35 | if (reason == CODEC_LOAD) { | ||
36 | /* Generic codec initialisation */ | ||
37 | ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH); | ||
38 | } | ||
39 | |||
40 | return CODEC_OK; | ||
41 | } | ||
42 | |||
43 | /* this is called for each file to process */ | ||
44 | enum codec_status codec_run(void) | ||
45 | { | ||
46 | uint32_t elapsedtime; | ||
47 | asf_waveformatex_t wfx; /* Holds the stream properties */ | ||
48 | int res; /* Return values from asf_read_packet() and decode_packet() */ | ||
49 | uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */ | ||
50 | int audiobufsize; /* Payload size */ | ||
51 | int packetlength = 0; /* Logical packet size (minus the header size) */ | ||
52 | int outlen = 0; /* Number of bytes written to the output buffer */ | ||
53 | int pktcnt = 0; /* Count of the packets played */ | ||
54 | uint8_t *data; /* Pointer to decoder input buffer */ | ||
55 | int size; /* Size of the input frame to the decoder */ | ||
56 | intptr_t param; | ||
57 | |||
58 | restart_track: | ||
59 | if (codec_init()) { | ||
60 | LOGF("(WMA PRO) Error: Error initialising codec\n"); | ||
61 | return CODEC_ERROR; | ||
62 | } | ||
63 | |||
64 | /* Copy the format metadata we've stored in the id3 TOC field. This | ||
65 | saves us from parsing it again here. */ | ||
66 | memcpy(&wfx, ci->id3->toc, sizeof(wfx)); | ||
67 | |||
68 | ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate); | ||
69 | ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ? | ||
70 | STEREO_MONO : STEREO_NONINTERLEAVED); | ||
71 | codec_set_replaygain(ci->id3); | ||
72 | |||
73 | if (decode_init(&wfx) < 0) { | ||
74 | LOGF("(WMA PRO) Error: Unsupported or corrupt file\n"); | ||
75 | return CODEC_ERROR; | ||
76 | } | ||
77 | |||
78 | /* Now advance the file position to the first frame */ | ||
79 | ci->seek_buffer(ci->id3->first_frame_offset); | ||
80 | |||
81 | elapsedtime = 0; | ||
82 | ci->set_elapsed(0); | ||
83 | |||
84 | /* The main decoding loop */ | ||
85 | |||
86 | while (pktcnt < wfx.numpackets) | ||
87 | { | ||
88 | enum codec_command_action action = ci->get_command(¶m); | ||
89 | |||
90 | if (action == CODEC_ACTION_HALT) | ||
91 | break; | ||
92 | |||
93 | /* Deal with any pending seek requests */ | ||
94 | if (action == CODEC_ACTION_SEEK_TIME) { | ||
95 | if (param == 0) { | ||
96 | ci->set_elapsed(0); | ||
97 | ci->seek_complete(); | ||
98 | goto restart_track; /* Pretend you never saw this... */ | ||
99 | } | ||
100 | |||
101 | elapsedtime = asf_seek(param, &wfx); | ||
102 | if (elapsedtime < 1){ | ||
103 | ci->set_elapsed(0); | ||
104 | ci->seek_complete(); | ||
105 | break; | ||
106 | } | ||
107 | |||
108 | ci->set_elapsed(elapsedtime); | ||
109 | ci->seek_complete(); | ||
110 | } | ||
111 | |||
112 | res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx); | ||
113 | |||
114 | if (res < 0) { | ||
115 | LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res); | ||
116 | return CODEC_ERROR; | ||
117 | } else { | ||
118 | data = audiobuf; | ||
119 | size = audiobufsize; | ||
120 | pktcnt++; | ||
121 | |||
122 | /* We now loop on the packet, decoding and outputting the subframes | ||
123 | * one-by-one. For more information about how wma pro structures its | ||
124 | * audio frames, see libwmapro/wmaprodec.c */ | ||
125 | while(size > 0) | ||
126 | { | ||
127 | res = decode_packet(&wfx, dec, &outlen, data, size); | ||
128 | if(res < 0) { | ||
129 | LOGF("(WMA PRO) Error: decode_packet returned %d", res); | ||
130 | return CODEC_ERROR; | ||
131 | } | ||
132 | data += res; | ||
133 | size -= res; | ||
134 | if(outlen) { | ||
135 | ci->yield (); | ||
136 | outlen /= (wfx.channels); | ||
137 | ci->pcmbuf_insert(dec[0], dec[1], outlen ); | ||
138 | elapsedtime += outlen*10/(wfx.rate/100); | ||
139 | ci->set_elapsed(elapsedtime); | ||
140 | ci->yield (); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | } | ||
145 | |||
146 | /* Advance to the next logical packet */ | ||
147 | ci->advance_buffer(packetlength); | ||
148 | } | ||
149 | |||
150 | return CODEC_OK; | ||
151 | } | ||
152 | |||