summaryrefslogtreecommitdiffstats
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
parentdacbc16d5b2c2a113eab6b9295db12795d98e2cc (diff)
downloadrockbox-febd9750f1f89404a22a30be1313c1b4c4873f81.tar.gz
rockbox-febd9750f1f89404a22a30be1313c1b4c4873f81.tar.bz2
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
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/viewers.config2
-rw-r--r--apps/plugins/wav2wv.c294
3 files changed, 297 insertions, 0 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 76d26e7e59..50cebb9f87 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -68,6 +68,7 @@ alpine_cdc.c
#if CONFIG_HWCODEC == MASNONE /* software codec platforms */
iriverify.c
+wav2wv.c
#else
splitedit.c
metronome.c
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index e0c794afc6..ddb80cd06a 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -20,3 +20,5 @@ m3u,iriverify.rock,00 00 00 00 00 00
mpc,mpc2wav.rock, 00 00 00 00 00 00
mid,midi2wav.rock, 20 70 70 3F 00 00
rsp,searchengine.rock, 0e 11 11 31 7e 60
+wav,wav2wv.rock, 00 00 00 00 00 00
+
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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 David Bryant
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+#include <codecs/libwavpack/wavpack.h>
+
+#define SAMPLES_PER_BLOCK 22050
+
+static struct plugin_api* rb;
+
+void *memset(void *s, int c, size_t n) {
+ return(rb->memset(s,c,n));
+}
+
+void *memcpy(void *dest, const void *src, size_t n) {
+ return(rb->memcpy(dest,src,n));
+}
+
+static char *audiobuf;
+static int audiobuflen;
+
+static struct wav_header {
+ char ckID [4]; /* RIFF chuck header */
+ long ckSize;
+ char formType [4];
+
+ char fmt_ckID [4]; /* format chunk header */
+ long fmt_ckSize;
+ ushort FormatTag, NumChannels;
+ ulong SampleRate, BytesPerSecond;
+ ushort BlockAlign, BitsPerSample;
+
+ char data_ckID [4]; /* data chunk header */
+ long data_ckSize;
+} raw_header, native_header;
+
+#define WAV_HEADER_FORMAT "4L44LSSLLSS4L"
+
+static void wvupdate (long start_tick,
+ long sample_rate,
+ ulong total_samples,
+ ulong samples_converted,
+ ulong bytes_read,
+ ulong bytes_written)
+{
+ long elapsed_ticks = *rb->current_tick - start_tick;
+ int compression = 0, progress = 0, realtime = 0;
+ char buf[32];
+
+ if (total_samples)
+ progress = (int)(((long long) samples_converted * 100 +
+ (total_samples/2)) / total_samples);
+
+ if (elapsed_ticks)
+ realtime = (int)(((long long) samples_converted * 100 * HZ /
+ sample_rate + (elapsed_ticks/2)) / elapsed_ticks);
+
+ if (bytes_read)
+ compression = (int)(((long long)(bytes_read - bytes_written) * 100 +
+ (bytes_read/2)) / bytes_read);
+
+ rb->snprintf(buf, 32, "elapsed time: %d secs", (elapsed_ticks + (HZ/2)) / HZ);
+ rb->lcd_puts(0, 2, buf);
+
+ rb->snprintf(buf, 32, "progress: %d%%", progress);
+ rb->lcd_puts(0, 4, buf);
+
+ rb->snprintf(buf, 32, "realtime: %d%% ", realtime);
+ rb->lcd_puts(0, 6, buf);
+
+ rb->snprintf(buf, 32, "compression: %d%% ", compression);
+ rb->lcd_puts(0, 8, buf);
+
+#ifdef HAVE_LCD_BITMAP
+ rb->lcd_update();
+#endif
+}
+
+static int wav2wv (char *filename)
+{
+ int in_fd, out_fd, num_chans, error = false, last_buttons;
+ unsigned long total_bytes_read = 0, total_bytes_written = 0;
+ unsigned long total_samples, samples_remaining;
+ long *input_buffer = (long *) audiobuf;
+ unsigned char *output_buffer = audiobuf + 0x100000;
+ char *extension, save_a;
+ WavpackConfig config;
+ WavpackContext *wpc;
+ long start_tick;
+
+ rb->lcd_clear_display();
+ rb->lcd_puts_scroll(0, 0, filename);
+#ifdef HAVE_LCD_BITMAP
+ rb->lcd_update();
+#endif
+
+ last_buttons = rb->button_status ();
+ start_tick = *rb->current_tick;
+ extension = filename + rb->strlen (filename) - 3;
+
+ if (rb->strcasecmp (extension, "wav")) {
+ rb->splash(HZ*2, true, "only for wav files!");
+ return 1;
+ }
+
+ in_fd = rb->open(filename, O_RDONLY);
+
+ if (in_fd < 0) {
+ rb->splash(HZ*2, true, "could not open file!");
+ return true;
+ }
+
+ if (rb->read (in_fd, &raw_header, sizeof (raw_header)) != sizeof (raw_header)) {
+ rb->splash(HZ*2, true, "could not read file!");
+ return true;
+ }
+
+ total_bytes_read += sizeof (raw_header);
+ rb->memcpy (&native_header, &raw_header, sizeof (raw_header));
+ little_endian_to_native (&native_header, WAV_HEADER_FORMAT);
+
+ if (rb->strncmp (native_header.ckID, "RIFF", 4) ||
+ rb->strncmp (native_header.fmt_ckID, "fmt ", 4) ||
+ rb->strncmp (native_header.data_ckID, "data", 4) ||
+ native_header.FormatTag != 1 || native_header.BitsPerSample != 16) {
+ rb->splash(HZ*2, true, "incompatible wav file!");
+ return true;
+ }
+
+ wpc = WavpackOpenFileOutput ();
+ WavpackSetOutputBuffer (wpc, output_buffer, output_buffer + 0x100000);
+
+ rb->memset (&config, 0, sizeof (config));
+ config.bits_per_sample = 16;
+ config.bytes_per_sample = 2;
+ config.sample_rate = native_header.SampleRate;
+ num_chans = config.num_channels = native_header.NumChannels;
+ total_samples = native_header.data_ckSize / native_header.BlockAlign;
+
+ if (!WavpackSetConfiguration (wpc, &config, total_samples)) {
+ rb->splash(HZ*2, true, "internal error!");
+ rb->close (in_fd);
+ return true;
+ }
+
+ WavpackAddWrapper (wpc, &raw_header, sizeof (raw_header));
+ save_a = extension [1];
+ extension [1] = extension [2];
+ extension [2] = 0;
+
+ out_fd = rb->creat (filename, O_WRONLY);
+
+ extension [2] = extension [1];
+ extension [1] = save_a;
+
+ if (out_fd < 0) {
+ rb->splash(HZ*2, true, "could not create file!");
+ rb->close (in_fd);
+ return true;
+ }
+
+ wvupdate (start_tick, native_header.SampleRate, total_samples, 0, 0, 0);
+
+ for (samples_remaining = total_samples; samples_remaining;) {
+ unsigned long samples_count, bytes_count;
+ int cnt, buttons;
+ long value, *lp;
+ char *cp;
+
+ samples_count = SAMPLES_PER_BLOCK;
+
+ if (samples_count > samples_remaining)
+ samples_count = samples_remaining;
+
+ bytes_count = samples_count * num_chans * 2;
+
+ if (rb->read (in_fd, input_buffer, bytes_count) != (long) bytes_count) {
+ rb->splash(HZ*2, true, "could not read file!");
+ error = true;
+ break;
+ }
+
+ total_bytes_read += bytes_count;
+ cp = (char *) input_buffer + bytes_count;
+ lp = input_buffer + samples_count * num_chans;
+ cnt = samples_count;
+
+ if (num_chans == 2)
+ while (cnt--) {
+ value = *--cp << 8;
+ value += *--cp & 0xff;
+ *--lp = value;
+ value = *--cp << 8;
+ value += *--cp & 0xff;
+ *--lp = value;
+ }
+ else
+ while (cnt--) {
+ value = *--cp << 8;
+ value += *--cp & 0xff;
+ *--lp = value;
+ }
+
+ bytes_count = WavpackPackSamples (wpc, input_buffer, samples_count);
+
+ if (!bytes_count) {
+ rb->splash(HZ*2, true, "internal error!");
+ error = true;
+ break;
+ }
+
+ if (rb->write (out_fd, output_buffer, bytes_count) != (long) bytes_count) {
+ rb->splash(HZ*2, true, "could not write file!");
+ error = true;
+ break;
+ }
+
+ total_bytes_written += bytes_count;
+ samples_remaining -= samples_count;
+
+ wvupdate (start_tick, native_header.SampleRate, total_samples,
+ total_samples - samples_remaining, total_bytes_read, total_bytes_written);
+
+ buttons = rb->button_status ();
+
+ if (last_buttons == BUTTON_NONE && buttons != BUTTON_NONE) {
+ rb->splash(HZ*2, true, "operation aborted!");
+ error = true;
+ break;
+ }
+ else
+ last_buttons = buttons;
+ }
+
+ rb->close (out_fd);
+ rb->close (in_fd);
+
+ if (error) {
+ save_a = extension [1];
+ extension [1] = extension [2];
+ extension [2] = 0;
+ rb->remove (filename);
+ extension [2] = extension [1];
+ extension [1] = save_a;
+ }
+ else
+ rb->splash(HZ*3, true, "operation successful");
+
+ return error;
+}
+
+enum plugin_status plugin_start(struct plugin_api* api, void *parameter)
+{
+ TEST_PLUGIN_API(api);
+
+ rb = api;
+
+ if (!parameter)
+ return PLUGIN_ERROR;
+
+ audiobuf = rb->plugin_get_audio_buffer(&audiobuflen);
+
+ if (audiobuflen < 0x200000) {
+ rb->splash(HZ*2, true, "not enough memory!");
+ return PLUGIN_ERROR;
+ }
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(true);
+#endif
+
+ wav2wv (parameter);
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(false);
+#endif
+ return PLUGIN_OK;
+}