summaryrefslogtreecommitdiff
path: root/apps/plugins/wav2wv.c
diff options
context:
space:
mode:
authorDave Bryant <bryant@rockbox.org>2005-07-04 07:07:43 +0000
committerDave Bryant <bryant@rockbox.org>2005-07-04 07:07:43 +0000
commitfebd9750f1f89404a22a30be1313c1b4c4873f81 (patch)
treee79855e044c8c190449a7d3a66d834abf3a179af /apps/plugins/wav2wv.c
parentdacbc16d5b2c2a113eab6b9295db12795d98e2cc (diff)
downloadrockbox-febd9750f1f89404a22a30be1313c1b4c4873f81.tar.gz
rockbox-febd9750f1f89404a22a30be1313c1b4c4873f81.zip
Created new viewer application to test WavPack encoding. Accepts .wav file
and generates lossless .wv with the same name. Runs at about 150% realtime for now. Only problem is that folder display (and playlist?) do not get updated when finished and since files don't show extensions it's a little hard to tell which is which (wav is first by alpha). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7010 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/wav2wv.c')
-rw-r--r--apps/plugins/wav2wv.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/apps/plugins/wav2wv.c b/apps/plugins/wav2wv.c
new file mode 100644
index 0000000000..24a7f8be6d
--- /dev/null
+++ b/apps/plugins/wav2wv.c
@@ -0,0 +1,294 @@
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#include "plugin.h"
20
21#include <codecs/libwavpack/wavpack.h>
22
23#define SAMPLES_PER_BLOCK 22050
24
25static struct plugin_api* rb;
26
27void *memset(void *s, int c, size_t n) {
28 return(rb->memset(s,c,n));
29}
30
31void *memcpy(void *dest, const void *src, size_t n) {
32 return(rb->memcpy(dest,src,n));
33}
34
35static char *audiobuf;
36static int audiobuflen;
37
38static struct wav_header {
39 char ckID [4]; /* RIFF chuck header */
40 long ckSize;
41 char formType [4];
42
43 char fmt_ckID [4]; /* format chunk header */
44 long fmt_ckSize;
45 ushort FormatTag, NumChannels;
46 ulong SampleRate, BytesPerSecond;
47 ushort BlockAlign, BitsPerSample;
48
49 char data_ckID [4]; /* data chunk header */
50 long data_ckSize;
51} raw_header, native_header;
52
53#define WAV_HEADER_FORMAT "4L44LSSLLSS4L"
54
55static void wvupdate (long start_tick,
56 long sample_rate,
57 ulong total_samples,
58 ulong samples_converted,
59 ulong bytes_read,
60 ulong bytes_written)
61{
62 long elapsed_ticks = *rb->current_tick - start_tick;
63 int compression = 0, progress = 0, realtime = 0;
64 char buf[32];
65
66 if (total_samples)
67 progress = (int)(((long long) samples_converted * 100 +
68 (total_samples/2)) / total_samples);
69
70 if (elapsed_ticks)
71 realtime = (int)(((long long) samples_converted * 100 * HZ /
72 sample_rate + (elapsed_ticks/2)) / elapsed_ticks);
73
74 if (bytes_read)
75 compression = (int)(((long long)(bytes_read - bytes_written) * 100 +
76 (bytes_read/2)) / bytes_read);
77
78 rb->snprintf(buf, 32, "elapsed time: %d secs", (elapsed_ticks + (HZ/2)) / HZ);
79 rb->lcd_puts(0, 2, buf);
80
81 rb->snprintf(buf, 32, "progress: %d%%", progress);
82 rb->lcd_puts(0, 4, buf);
83
84 rb->snprintf(buf, 32, "realtime: %d%% ", realtime);
85 rb->lcd_puts(0, 6, buf);
86
87 rb->snprintf(buf, 32, "compression: %d%% ", compression);
88 rb->lcd_puts(0, 8, buf);
89
90#ifdef HAVE_LCD_BITMAP
91 rb->lcd_update();
92#endif
93}
94
95static int wav2wv (char *filename)
96{
97 int in_fd, out_fd, num_chans, error = false, last_buttons;
98 unsigned long total_bytes_read = 0, total_bytes_written = 0;
99 unsigned long total_samples, samples_remaining;
100 long *input_buffer = (long *) audiobuf;
101 unsigned char *output_buffer = audiobuf + 0x100000;
102 char *extension, save_a;
103 WavpackConfig config;
104 WavpackContext *wpc;
105 long start_tick;
106
107 rb->lcd_clear_display();
108 rb->lcd_puts_scroll(0, 0, filename);
109#ifdef HAVE_LCD_BITMAP
110 rb->lcd_update();
111#endif
112
113 last_buttons = rb->button_status ();
114 start_tick = *rb->current_tick;
115 extension = filename + rb->strlen (filename) - 3;
116
117 if (rb->strcasecmp (extension, "wav")) {
118 rb->splash(HZ*2, true, "only for wav files!");
119 return 1;
120 }
121
122 in_fd = rb->open(filename, O_RDONLY);
123
124 if (in_fd < 0) {
125 rb->splash(HZ*2, true, "could not open file!");
126 return true;
127 }
128
129 if (rb->read (in_fd, &raw_header, sizeof (raw_header)) != sizeof (raw_header)) {
130 rb->splash(HZ*2, true, "could not read file!");
131 return true;
132 }
133
134 total_bytes_read += sizeof (raw_header);
135 rb->memcpy (&native_header, &raw_header, sizeof (raw_header));
136 little_endian_to_native (&native_header, WAV_HEADER_FORMAT);
137
138 if (rb->strncmp (native_header.ckID, "RIFF", 4) ||
139 rb->strncmp (native_header.fmt_ckID, "fmt ", 4) ||
140 rb->strncmp (native_header.data_ckID, "data", 4) ||
141 native_header.FormatTag != 1 || native_header.BitsPerSample != 16) {
142 rb->splash(HZ*2, true, "incompatible wav file!");
143 return true;
144 }
145
146 wpc = WavpackOpenFileOutput ();
147 WavpackSetOutputBuffer (wpc, output_buffer, output_buffer + 0x100000);
148
149 rb->memset (&config, 0, sizeof (config));
150 config.bits_per_sample = 16;
151 config.bytes_per_sample = 2;
152 config.sample_rate = native_header.SampleRate;
153 num_chans = config.num_channels = native_header.NumChannels;
154 total_samples = native_header.data_ckSize / native_header.BlockAlign;
155
156 if (!WavpackSetConfiguration (wpc, &config, total_samples)) {
157 rb->splash(HZ*2, true, "internal error!");
158 rb->close (in_fd);
159 return true;
160 }
161
162 WavpackAddWrapper (wpc, &raw_header, sizeof (raw_header));
163 save_a = extension [1];
164 extension [1] = extension [2];
165 extension [2] = 0;
166
167 out_fd = rb->creat (filename, O_WRONLY);
168
169 extension [2] = extension [1];
170 extension [1] = save_a;
171
172 if (out_fd < 0) {
173 rb->splash(HZ*2, true, "could not create file!");
174 rb->close (in_fd);
175 return true;
176 }
177
178 wvupdate (start_tick, native_header.SampleRate, total_samples, 0, 0, 0);
179
180 for (samples_remaining = total_samples; samples_remaining;) {
181 unsigned long samples_count, bytes_count;
182 int cnt, buttons;
183 long value, *lp;
184 char *cp;
185
186 samples_count = SAMPLES_PER_BLOCK;
187
188 if (samples_count > samples_remaining)
189 samples_count = samples_remaining;
190
191 bytes_count = samples_count * num_chans * 2;
192
193 if (rb->read (in_fd, input_buffer, bytes_count) != (long) bytes_count) {
194 rb->splash(HZ*2, true, "could not read file!");
195 error = true;
196 break;
197 }
198
199 total_bytes_read += bytes_count;
200 cp = (char *) input_buffer + bytes_count;
201 lp = input_buffer + samples_count * num_chans;
202 cnt = samples_count;
203
204 if (num_chans == 2)
205 while (cnt--) {
206 value = *--cp << 8;
207 value += *--cp & 0xff;
208 *--lp = value;
209 value = *--cp << 8;
210 value += *--cp & 0xff;
211 *--lp = value;
212 }
213 else
214 while (cnt--) {
215 value = *--cp << 8;
216 value += *--cp & 0xff;
217 *--lp = value;
218 }
219
220 bytes_count = WavpackPackSamples (wpc, input_buffer, samples_count);
221
222 if (!bytes_count) {
223 rb->splash(HZ*2, true, "internal error!");
224 error = true;
225 break;
226 }
227
228 if (rb->write (out_fd, output_buffer, bytes_count) != (long) bytes_count) {
229 rb->splash(HZ*2, true, "could not write file!");
230 error = true;
231 break;
232 }
233
234 total_bytes_written += bytes_count;
235 samples_remaining -= samples_count;
236
237 wvupdate (start_tick, native_header.SampleRate, total_samples,
238 total_samples - samples_remaining, total_bytes_read, total_bytes_written);
239
240 buttons = rb->button_status ();
241
242 if (last_buttons == BUTTON_NONE && buttons != BUTTON_NONE) {
243 rb->splash(HZ*2, true, "operation aborted!");
244 error = true;
245 break;
246 }
247 else
248 last_buttons = buttons;
249 }
250
251 rb->close (out_fd);
252 rb->close (in_fd);
253
254 if (error) {
255 save_a = extension [1];
256 extension [1] = extension [2];
257 extension [2] = 0;
258 rb->remove (filename);
259 extension [2] = extension [1];
260 extension [1] = save_a;
261 }
262 else
263 rb->splash(HZ*3, true, "operation successful");
264
265 return error;
266}
267
268enum plugin_status plugin_start(struct plugin_api* api, void *parameter)
269{
270 TEST_PLUGIN_API(api);
271
272 rb = api;
273
274 if (!parameter)
275 return PLUGIN_ERROR;
276
277 audiobuf = rb->plugin_get_audio_buffer(&audiobuflen);
278
279 if (audiobuflen < 0x200000) {
280 rb->splash(HZ*2, true, "not enough memory!");
281 return PLUGIN_ERROR;
282 }
283
284#ifdef HAVE_ADJUSTABLE_CPU_FREQ
285 rb->cpu_boost(true);
286#endif
287
288 wav2wv (parameter);
289
290#ifdef HAVE_ADJUSTABLE_CPU_FREQ
291 rb->cpu_boost(false);
292#endif
293 return PLUGIN_OK;
294}