summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2005-04-12 21:29:48 +0000
committerThom Johansen <thomj@rockbox.org>2005-04-12 21:29:48 +0000
commitad17fd47478bb3619ca4f097a555f02f84735c7f (patch)
tree930db449ebf09948d49350e984b8ba8f4d9d8b29 /apps/plugins
parent34e2f722f778defa9be7fffe9bb4ee415b799890 (diff)
downloadrockbox-ad17fd47478bb3619ca4f097a555f02f84735c7f.zip
rockbox-ad17fd47478bb3619ca4f097a555f02f84735c7f.tar.gz
rockbox-ad17fd47478bb3619ca4f097a555f02f84735c7f.tar.bz2
rockbox-ad17fd47478bb3619ca4f097a555f02f84735c7f.tar.xz
Musepack support, complete with mpc2wav plugin. Thanks go out to rasher for initiating the port.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6276 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/Makefile2
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/mpc2wav.c208
3 files changed, 210 insertions, 1 deletions
diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile
index 651a26c..9c3ff4a 100644
--- a/apps/plugins/Makefile
+++ b/apps/plugins/Makefile
@@ -17,7 +17,7 @@ ifdef APPEXTRA
endif
ifdef SOFTWARECODECS
- CODECLIBS = -lmad -la52 -lFLAC -lTremor -lwavpack
+ CODECLIBS = -lmad -la52 -lFLAC -lTremor -lwavpack -lmusepack
endif
LDS := plugin.lds
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index ae9128a..3dd7eb4 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -73,5 +73,6 @@ a52towav.c
flac2wav.c
vorbis2wav.c
wv2wav.c
+mpc2wav.c
iriverify.c
#endif
diff --git a/apps/plugins/mpc2wav.c b/apps/plugins/mpc2wav.c
new file mode 100644
index 0000000..747fbdc
--- /dev/null
+++ b/apps/plugins/mpc2wav.c
@@ -0,0 +1,208 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Thom Johansen
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/* This is a lovely mishmash of sample.c from libmusepack and mpa2wav.c,
+ * but happens to work, so no whining!
+ */
+
+#include "plugin.h"
+
+#if (CONFIG_HWCODEC == MASNONE)
+/* software codec platforms */
+
+#include <codecs/libmusepack/musepack.h>
+
+#include "lib/xxx2wav.h" /* Helper functions common to test decoders */
+
+static struct plugin_api* rb;
+mpc_decoder decoder;
+
+/*
+ Our implementations of the mpc_reader callback functions.
+*/
+mpc_int32_t
+read_impl(void *data, void *ptr, mpc_int32_t size)
+{
+ file_info_struct *f = (file_info_struct *)data;
+ mpc_int32_t num = f->filesize - f->curpos;
+ if (num > size)
+ num = size;
+ rb->memcpy(ptr, filebuf + f->curpos, num);
+ f->curpos += num;
+ return num;
+}
+
+bool
+seek_impl(void *data, mpc_int32_t offset)
+{
+ file_info_struct *f = (file_info_struct *)data;
+ if (offset > f->filesize) {
+ return 0;
+ } else {
+ f->curpos = offset;
+ return 1;
+ }
+}
+
+mpc_int32_t
+tell_impl(void *data)
+{
+ file_info_struct *f = (file_info_struct *)data;
+ return f->curpos;
+}
+
+mpc_int32_t
+get_size_impl(void *data)
+{
+ file_info_struct *f = (file_info_struct *)data;
+ return f->filesize;
+}
+
+bool
+canseek_impl(void *data)
+{
+ file_info_struct *f = (file_info_struct *)data;
+ return true;
+}
+
+static int
+shift_signed(MPC_SAMPLE_FORMAT val, int shift)
+{
+ if (shift > 0)
+ val <<= shift;
+ else if (shift < 0)
+ val >>= -shift;
+ return (int)val;
+}
+
+#define OUTPUT_BUFFER_SIZE 65536 /* Must be an integer multiple of 4. */
+
+unsigned char OutputBuffer[OUTPUT_BUFFER_SIZE];
+MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH];
+unsigned char *OutputPtr=OutputBuffer;
+const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
+
+#ifdef USE_IRAM
+extern char iramcopy[];
+extern char iramstart[];
+extern char iramend[];
+#endif
+
+/* this is the plugin entry point */
+enum plugin_status plugin_start(struct plugin_api* api, void* file)
+{
+ file_info_struct file_info;
+ unsigned short Sample;
+ unsigned status = 1;
+ int i;
+ mpc_reader reader;
+
+ /* Generic plugin inititialisation */
+
+ TEST_PLUGIN_API(api);
+ rb = api;
+
+#ifdef USE_IRAM
+ rb->memcpy(iramstart, iramcopy, iramend-iramstart);
+#endif
+
+ reader.read = read_impl;
+ reader.seek = seek_impl;
+ reader.tell = tell_impl;
+ reader.get_size = get_size_impl;
+ reader.canseek = canseek_impl;
+ reader.data = &file_info;
+
+ /* This function sets up the buffers and reads the file into RAM */
+
+ if (local_init(file, "/libmusepacktest.wav", &file_info, api)) {
+ return PLUGIN_ERROR;
+ }
+
+ /* read file's streaminfo data */
+ mpc_streaminfo info;
+ mpc_streaminfo_init(&info);
+ if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
+ rb->splash(HZ, true, "Not an MPC file.");
+ return PLUGIN_ERROR;
+ }
+ file_info.samplerate=info.sample_freq;
+ /* instantiate a decoder with our file reader */
+ mpc_decoder_setup(&decoder, &reader);
+ if (!mpc_decoder_initialize(&decoder, &info)) {
+ rb->splash(HZ, true, "Error in init.");
+ return PLUGIN_ERROR;
+ }
+ file_info.frames_decoded = 0;
+ file_info.start_tick = *(rb->current_tick);
+
+ rb->button_clear_queue();
+
+ /* This is the decoding loop. */
+ while (status != 0) {
+ status = mpc_decoder_decode(&decoder, sample_buffer, 0, 0);
+ if (status == (unsigned)(-1)) {
+ //decode error
+ rb->splash(HZ, true, "Error decoding file.");
+ break;
+ }
+ else //status>0
+ {
+ file_info.current_sample += status;
+ file_info.frames_decoded++;
+ /* Convert musepack's numbers to an array of 16-bit LE signed integers */
+#if 1 /* uncomment to time without byte swapping and disk writing */
+ for(i = 0; i < status*info.channels; i += info.channels)
+ {
+ /* Left channel */
+ Sample=shift_signed(sample_buffer[i], 16 - MPC_FIXED_POINT_SCALE_SHIFT);
+ *(OutputPtr++)=Sample&0xff;
+ *(OutputPtr++)=Sample>>8;
+
+ /* Right channel. If the decoded stream is monophonic then
+ * the right output channel is the same as the left one.
+ */
+ if(info.channels==2)
+ Sample=shift_signed(sample_buffer[i + 1], 16 - MPC_FIXED_POINT_SCALE_SHIFT);
+ *(OutputPtr++)=Sample&0xff;
+ *(OutputPtr++)=Sample>>8;
+
+ /* Flush the buffer if it is full. */
+ if(OutputPtr==OutputBufferEnd)
+ {
+ rb->write(file_info.outfile,OutputBuffer,OUTPUT_BUFFER_SIZE);
+ OutputPtr=OutputBuffer;
+ }
+ }
+#endif
+
+ }
+ display_status(&file_info);
+
+ if (rb->button_get(false)!=BUTTON_NONE) {
+ close_wav(&file_info);
+ return PLUGIN_OK;
+ }
+ }
+ close_wav(&file_info);
+ rb->splash(HZ*2, true, "FINISHED!");
+
+ return PLUGIN_OK;
+}
+#endif /* CONFIG_HWCODEC == MASNONE */