summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorDave Bryant <bryant@rockbox.org>2005-06-13 06:15:05 +0000
committerDave Bryant <bryant@rockbox.org>2005-06-13 06:15:05 +0000
commit7dad7d3a6a7b9c2a972d0426488eed503f39cf72 (patch)
tree40dc4c48063c1430da6156c0a180ba7cda73d4a8 /apps
parent57c6f6e57ee7823678f98a21f44fb9563c228fca (diff)
downloadrockbox-7dad7d3a6a7b9c2a972d0426488eed503f39cf72.tar.gz
rockbox-7dad7d3a6a7b9c2a972d0426488eed503f39cf72.zip
Initial commit of actual WavPack codec... :)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6699 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/codecwavpack.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/apps/plugins/codecwavpack.c b/apps/plugins/codecwavpack.c
new file mode 100644
index 0000000000..1e56dbd88e
--- /dev/null
+++ b/apps/plugins/codecwavpack.c
@@ -0,0 +1,185 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 David Bryant
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
22#include <codecs/libwavpack/wavpack.h>
23#include "playback.h"
24#include "lib/codeclib.h"
25
26static struct plugin_api *rb;
27static struct codec_api *ci;
28
29#define BUFFER_SIZE 4096
30
31static long temp_buffer [BUFFER_SIZE] IDATA_ATTR;
32
33static long read_callback (void *buffer, long bytes)
34{
35 return ci->read_filebuf (buffer, bytes);
36}
37
38#ifndef SIMULATOR
39extern char iramcopy[];
40extern char iramstart[];
41extern char iramend[];
42#endif
43
44/* this is the plugin entry point */
45enum plugin_status plugin_start(struct plugin_api* api, void* parm)
46{
47 WavpackContext *wpc;
48 char error [80];
49 int bps, nchans;
50
51 /* Generic plugin initialisation */
52 TEST_PLUGIN_API(api);
53
54 rb = api;
55 ci = (struct codec_api*) parm;
56
57#ifndef SIMULATOR
58 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
59#endif
60
61 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10));
62 ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
63 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128));
64
65 next_track:
66
67 if (codec_init(api, ci))
68 return PLUGIN_ERROR;
69
70 /* Create a decoder instance */
71
72 wpc = WavpackOpenFileInput (read_callback, error);
73
74 if (!wpc)
75 return PLUGIN_ERROR;
76
77 bps = WavpackGetBytesPerSample (wpc);
78 nchans = WavpackGetReducedChannels (wpc);
79
80 ci->set_elapsed (0);
81
82 /* The main decoder loop */
83
84 while (1) {
85 long nsamples;
86
87 if (ci->seek_time && ci->taginfo_ready && ci->id3->length) {
88 int curpos_ms = (WavpackGetSampleIndex (wpc) + 220) / 441 * 10;
89 int n, d, skip;
90
91 if (ci->seek_time > curpos_ms) {
92 n = ci->seek_time - curpos_ms;
93 d = ci->id3->length - curpos_ms;
94 skip = (int)((long long)(ci->filesize - ci->curpos) * n / d);
95 ci->seek_buffer (ci->curpos + skip);
96 }
97 else {
98 n = curpos_ms - ci->seek_time;
99 d = curpos_ms;
100 skip = (int)((long long) ci->curpos * n / d);
101 ci->seek_buffer (ci->curpos - skip);
102 }
103
104 wpc = WavpackOpenFileInput (read_callback, error);
105 ci->seek_time = 0;
106
107 if (!wpc)
108 break;
109
110 ci->set_elapsed ((int)((long long) WavpackGetSampleIndex (wpc) * 1000 / 44100));
111 rb->yield ();
112 }
113
114 nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / 2);
115
116 if (!nsamples || ci->stop_codec || ci->reload_codec)
117 break;
118
119 /* convert mono to stereo here, in place */
120
121 if (nchans == 1) {
122 long *dst = temp_buffer + (nsamples * 2);
123 long *src = temp_buffer + nsamples;
124 long count = nsamples;
125
126 while (count--) {
127 *--dst = *--src;
128 *--dst = *src;
129 if (!(count & 0x7f))
130 rb->yield ();
131 }
132 }
133
134 if (bps == 1) {
135 short *dst = (short *) temp_buffer;
136 long *src = temp_buffer;
137 long count = nsamples;
138
139 while (count--) {
140 *dst++ = *src++ << 8;
141 *dst++ = *src++ << 8;
142 if (!(count & 0x7f))
143 rb->yield ();
144 }
145 }
146 else if (bps == 2) {
147 short *dst = (short *) temp_buffer;
148 long *src = temp_buffer;
149 long count = nsamples;
150
151 while (count--) {
152 *dst++ = *src++;
153 *dst++ = *src++;
154 if (!(count & 0x7f))
155 rb->yield ();
156 }
157 }
158 else {
159 short *dst = (short *) temp_buffer;
160 int shift = (bps - 2) * 8;
161 long *src = temp_buffer;
162 long count = nsamples;
163
164 while (count--) {
165 *dst++ = *src++ >> shift;
166 *dst++ = *src++ >> shift;
167 if (!(count & 0x7f))
168 rb->yield ();
169 }
170 }
171
172 if (ci->stop_codec || ci->reload_codec)
173 break;
174
175 while (!ci->audiobuffer_insert ((char *) temp_buffer, nsamples * 4))
176 rb->yield ();
177
178 ci->set_elapsed ((WavpackGetSampleIndex (wpc) + 220) / 441 * 10);
179 }
180
181 if (ci->request_next_track())
182 goto next_track;
183
184 return PLUGIN_OK;
185}