rockbox/apps/plugins/wv2wav.c
Thom Johansen a1483e6e1d Patch #1189084 by David Bryant.
Wv2wav bug fixes.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6440 a1c6a512-1295-4272-9138-f99709370657
2005-05-08 17:10:01 +00:00

207 lines
5.2 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 Christian Gmeiner
*
* 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"
#if (CONFIG_HWCODEC == MASNONE)
/* software codec platforms */
#include "lib/xxx2wav.h" /* Helper functions common to test decoders */
#include <codecs/libwavpack/wavpack.h>
#define BUFFER_SIZE 4096
static struct plugin_api* rb;
static file_info_struct file_info;
static long temp_buffer [BUFFER_SIZE];
/* Reformat samples from longs in processor's native endian mode to
little-endian data with 2 bytes / sample. */
uchar* format_samples (int bps, uchar *dst, long *src, ulong samcnt)
{
long temp;
switch (bps)
{
case 1:
while (samcnt--)
{
*dst++ = (uchar)(temp = (*src++ << 8));
*dst++ = (uchar)(temp >> 8);
}
break;
case 2:
while (samcnt--)
{
*dst++ = (uchar)(temp = *src++);
*dst++ = (uchar)(temp >> 8);
}
break;
case 3:
while (samcnt--)
{
*dst++ = (uchar)(temp = (*src++ >> 8));
*dst++ = (uchar)(temp >> 8);
}
break;
case 4:
while (samcnt--)
{
*dst++ = (uchar)(temp = (*src++ >> 16));
*dst++ = (uchar)(temp >> 8);
}
break;
}
return dst;
}
/* this is our function to decode a memory block from a file */
void wvpack_decode_data(file_info_struct* file_info, int samples_to_decode, WavpackContext **wpc)
{
int bps = WavpackGetBytesPerSample(*wpc);
/* nothing to decode */
if (!samples_to_decode)
{
return;
}
/* decode now */
ulong samples_unpacked = WavpackUnpackSamples(*wpc, temp_buffer, samples_to_decode);
if (samples_unpacked)
{
/* update some infos */
file_info->current_sample += samples_unpacked;
/* for now, convert mono to stereo here, in place */
if (WavpackGetReducedChannels (*wpc) == 1) {
long *dst = temp_buffer + (samples_unpacked * 2);
long *src = temp_buffer + samples_unpacked;
long count = samples_unpacked;
while (count--) {
*--dst = *--src;
*--dst = *src;
}
}
format_samples (bps, (uchar *) temp_buffer, temp_buffer, samples_unpacked * file_info->channels);
rb->write(file_info->outfile, temp_buffer, samples_unpacked * 4);
}
}
/* callback function for wavpack
Maybe we do this at a lower level, but the
first thing is to get all working */
long Read(void* buffer, long size)
{
long oldpos = file_info.curpos;
if ((file_info.curpos + size) < file_info.filesize)
{
memcpy(buffer, &filebuf[file_info.curpos], size);
file_info.curpos += size;
}
else
{
memcpy(buffer, &filebuf[file_info.curpos], file_info.filesize-file_info.curpos);
file_info.curpos = file_info.filesize;
}
return (file_info.curpos - oldpos);
}
/* this is the plugin entry point */
enum plugin_status plugin_start(struct plugin_api* api, void* file)
{
WavpackContext *wpc;
char error[80];
/* generic plugin initialisation */
TEST_PLUGIN_API(api);
rb = api;
/* this function sets up the buffers and reads the file into RAM */
if (local_init(file,"/wvtest.wav",&file_info,api))
{
return PLUGIN_ERROR;
}
/* setup wavpack */
wpc = WavpackOpenFileInput(Read, error);
/* was there an error? */
if (!wpc)
{
rb->splash(HZ*2, true, error);
return PLUGIN_ERROR;
}
/* grap/set some infos (forcing some to temp values) */
file_info.channels = 2;
file_info.total_samples = WavpackGetNumSamples(wpc);
file_info.bitspersample = 16;
file_info.samplerate = WavpackGetSampleRate(wpc);
file_info.current_sample = 0;
/* deciding loop */
file_info.start_tick=*(rb->current_tick);
rb->button_clear_queue();
while (file_info.current_sample < file_info.total_samples)
{
wvpack_decode_data(&file_info, BUFFER_SIZE / file_info.channels, &wpc);
display_status(&file_info);
if (rb->button_get(false)!=BUTTON_NONE)
{
close_wav(&file_info);
return PLUGIN_OK;
}
}
close_wav(&file_info);
/* do some last checks */
if ((WavpackGetNumSamples (wpc) != (ulong) -1) && (file_info.current_sample != WavpackGetNumSamples (wpc)))
{
rb->splash(HZ*2, true, "incorrect number of samples!");
return PLUGIN_ERROR;
}
if (WavpackGetNumErrors (wpc)) {
rb->splash(HZ*2, true, "crc errors detected!");
return PLUGIN_ERROR;
}
rb->splash(HZ*2, true, "FINISHED!");
return PLUGIN_OK;
}
#endif /* CONFIG_HWCODEC == MASNONE */