summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/codecmpc.c214
2 files changed, 215 insertions, 0 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 35a7d39cbf..7131f8329e 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -77,6 +77,7 @@ codecmpa.c
77codecflac.c 77codecflac.c
78codecwav.c 78codecwav.c
79codeca52.c 79codeca52.c
80codecmpc.c
80#endif 81#endif
81wv2wav.c 82wv2wav.c
82mpc2wav.c 83mpc2wav.c
diff --git a/apps/plugins/codecmpc.c b/apps/plugins/codecmpc.c
new file mode 100644
index 0000000000..3fe35705eb
--- /dev/null
+++ b/apps/plugins/codecmpc.c
@@ -0,0 +1,214 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Thom Johansen
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "plugin.h"
21#include "playback.h"
22#include "lib/codeclib.h"
23#include <codecs/libmusepack/musepack.h>
24
25static struct plugin_api* rb;
26mpc_decoder decoder;
27
28/*
29 Our implementations of the mpc_reader callback functions.
30*/
31mpc_int32_t
32read_impl(void *data, void *ptr, mpc_int32_t size)
33{
34 struct codec_api* ci = (struct codec_api*)data;
35
36 return((mpc_int32_t)(ci->read_filebuf(ptr,size)));
37}
38
39bool
40seek_impl(void *data, mpc_int32_t offset)
41{
42 struct codec_api* ci = (struct codec_api*)data;
43
44 /* We don't support seeking yet. */
45 (void)ci;
46 (void)offset;
47 return 0;
48}
49
50mpc_int32_t
51tell_impl(void *data)
52{
53 struct codec_api* ci = (struct codec_api*)data;
54
55 return ci->curpos;
56}
57
58mpc_int32_t
59get_size_impl(void *data)
60{
61 struct codec_api* ci = (struct codec_api*)data;
62 return ci->filesize;
63}
64
65bool
66canseek_impl(void *data)
67{
68 (void)data;
69 return false;
70}
71
72static int
73shift_signed(MPC_SAMPLE_FORMAT val, int shift)
74{
75 if (shift > 0)
76 val <<= shift;
77 else if (shift < 0)
78 val >>= -shift;
79 return (int)val;
80}
81
82#define OUTPUT_BUFFER_SIZE 65536 /* Must be an integer multiple of 4. */
83
84unsigned char OutputBuffer[OUTPUT_BUFFER_SIZE];
85MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH];
86unsigned char *OutputPtr=OutputBuffer;
87const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
88
89#ifdef USE_IRAM
90extern char iramcopy[];
91extern char iramstart[];
92extern char iramend[];
93#endif
94
95/* this is the plugin entry point */
96enum plugin_status plugin_start(struct plugin_api* api, void* parm)
97{
98 struct codec_api* ci = (struct codec_api*)parm;
99 unsigned short Sample;
100 unsigned long samplesdone;
101 unsigned long frequency;
102 unsigned status = 1;
103 unsigned int i;
104 mpc_reader reader;
105
106 /* Generic plugin inititialisation */
107
108 TEST_PLUGIN_API(api);
109 rb = api;
110
111#ifndef SIMULATOR
112 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
113#endif
114
115 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
116 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16));
117
118 next_track:
119
120 if (codec_init(api, ci)) {
121 return PLUGIN_ERROR;
122 }
123
124 /* Create a decoder instance */
125
126 reader.read = read_impl;
127 reader.seek = seek_impl;
128 reader.tell = tell_impl;
129 reader.get_size = get_size_impl;
130 reader.canseek = canseek_impl;
131 reader.data = ci;
132
133 /* read file's streaminfo data */
134 mpc_streaminfo info;
135 mpc_streaminfo_init(&info);
136 if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
137 return PLUGIN_ERROR;
138 }
139 frequency=info.sample_freq;
140
141 /* instantiate a decoder with our file reader */
142 mpc_decoder_setup(&decoder, &reader);
143 if (!mpc_decoder_initialize(&decoder, &info)) {
144 return PLUGIN_ERROR;
145 }
146
147 /* Initialise the output buffer. */
148 OutputPtr=OutputBuffer;
149 OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
150
151 /* This is the decoding loop. */
152 samplesdone=0;
153 while (status != 0) {
154 if (ci->stop_codec || ci->reload_codec) {
155 break;
156 }
157
158 status = mpc_decoder_decode(&decoder, sample_buffer, 0, 0);
159 if (status == (unsigned)(-1)) {
160 //decode error
161 return PLUGIN_ERROR;
162 }
163 else //status>0
164 {
165 // file_info.current_sample += status;
166 // file_info.frames_decoded++;
167 /* Convert musepack's numbers to an array of 16-bit BE signed integers */
168 for(i = 0; i < status*info.channels; i += info.channels)
169 {
170 /* Left channel */
171 Sample=shift_signed(sample_buffer[i], 16 - MPC_FIXED_POINT_SCALE_SHIFT);
172 *(OutputPtr++)=Sample>>8;
173 *(OutputPtr++)=Sample&0xff;
174
175 /* Right channel. If the decoded stream is monophonic then
176 * the right output channel is the same as the left one.
177 */
178 if(info.channels==2) {
179 Sample=shift_signed(sample_buffer[i + 1], 16 - MPC_FIXED_POINT_SCALE_SHIFT);
180 }
181 *(OutputPtr++)=Sample>>8;
182 *(OutputPtr++)=Sample&0xff;
183
184 samplesdone++;
185
186 /* Flush the buffer if it is full. */
187 if(OutputPtr==OutputBufferEnd)
188 {
189 rb->yield();
190 while (!ci->audiobuffer_insert(OutputBuffer, OUTPUT_BUFFER_SIZE)) {
191 rb->yield();
192 }
193
194 ci->set_elapsed(samplesdone/(frequency/1000));
195 OutputPtr=OutputBuffer;
196 }
197 }
198 }
199 }
200
201 /* Flush the remaining data in the output buffer */
202 if (OutputPtr > OutputBuffer) {
203 rb->yield();
204 while (!ci->audiobuffer_insert(OutputBuffer, OutputPtr-OutputBuffer)) {
205 rb->yield();
206 }
207 }
208
209 if (ci->request_next_track())
210 goto next_track;
211
212 return PLUGIN_OK;
213}
214