moved and renamed the codecs, gave the codecs a new extension (.codec),

unified to a single codec-only API, made a new codeclib, disabled the building
of the *2wav plugins


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6812 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Daniel Stenberg 2005-06-22 19:41:30 +00:00
parent b7aaa641b8
commit 1dd672fe32
29 changed files with 1709 additions and 937 deletions

View file

@ -16,7 +16,6 @@ plugins/viewers.config
plugins/snake2.levels plugins/snake2.levels
SOURCES SOURCES
plugins/SOURCES plugins/SOURCES
plugins/CODECS
plugins/lib/SOURCES plugins/lib/SOURCES
plugins/rockboy/*.[ch] plugins/rockboy/*.[ch]
plugins/rockboy/Makefile plugins/rockboy/Makefile
@ -53,3 +52,5 @@ codecs/dumb/src/core/*
codecs/dumb/src/helpers/* codecs/dumb/src/helpers/*
codecs/dumb/src/it/* codecs/dumb/src/it/*
codecs/libmusepack/* codecs/libmusepack/*
codecs/lib/*.[ch]
codecs/lib/Makefile

View file

@ -57,6 +57,7 @@ endif
dep: $(DEPFILE) dep: $(DEPFILE)
build-codecs: build-codecs:
@$(MAKE) -C codecs/lib OBJDIR=$(OBJDIR)/codecs/lib
@$(MAKE) -C codecs OBJDIR=$(OBJDIR)/codecs @$(MAKE) -C codecs OBJDIR=$(OBJDIR)/codecs
rocks: rocks:

View file

@ -48,9 +48,10 @@ recorder/radio.c
#ifdef HAVE_RECORDING #ifdef HAVE_RECORDING
recorder/recording.c recorder/recording.c
#endif #endif
#ifdef IRIVER_H100 #if CONFIG_HWCODEC == MASNONE
playback.c playback.c
metadata.c metadata.c
codecs.c
#ifndef SIMULATOR #ifndef SIMULATOR
pcm_recording.c pcm_recording.c
#endif #endif

364
apps/codecs.c Normal file
View file

@ -0,0 +1,364 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 Björn Stenberg
*
* 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 <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <atoi.h>
#include <timefuncs.h>
#include <ctype.h>
#include "debug.h"
#include "button.h"
#include "lcd.h"
#include "dir.h"
#include "file.h"
#include "kernel.h"
#include "sprintf.h"
#include "logf.h"
#include "screens.h"
#include "misc.h"
#include "mas.h"
#include "codecs.h"
#include "lang.h"
#include "keyboard.h"
#include "mpeg.h"
#include "buffer.h"
#include "mp3_playback.h"
#include "backlight.h"
#include "ata.h"
#include "talk.h"
#include "mp3data.h"
#include "powermgmt.h"
#include "system.h"
#include "sound.h"
#include "database.h"
#if (CONFIG_HWCODEC == MASNONE)
#include "pcm_playback.h"
#endif
#ifdef HAVE_LCD_BITMAP
#include "peakmeter.h"
#include "widgets.h"
#include "bmp.h"
#endif
#ifdef SIMULATOR
#if CONFIG_HWCODEC == MASNONE
static unsigned char codecbuf[CODEC_BUFFER_SIZE];
#endif
void *sim_codec_load(char *plugin, int *fd);
void sim_codec_close(int fd);
#else
#define sim_codec_close(x)
extern unsigned char codecbuf[];
#endif
extern void* plugin_get_audio_buffer(int *buffer_size);
static int codec_test(int api_version, int model, int memsize);
const struct codec_api ci = {
CODEC_API_VERSION,
codec_test,
0, /* filesize */
0, /* curpos */
NULL, /* id3 */
NULL, /* mp3data */
NULL, /* taginfo_ready */
false, /* stop_codec */
false, /* reload_codec */
0, /* seek_time */
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
/* lcd */
lcd_clear_display,
lcd_puts,
lcd_puts_scroll,
lcd_stop_scroll,
lcd_set_contrast,
#ifdef HAVE_LCD_CHARCELLS
lcd_define_pattern,
lcd_get_locked_pattern,
lcd_unlock_pattern,
lcd_putc,
lcd_put_cursor,
lcd_remove_cursor,
PREFIX(lcd_icon),
#else
lcd_putsxy,
lcd_puts_style,
lcd_puts_scroll_style,
lcd_bitmap,
lcd_drawline,
lcd_clearline,
lcd_drawpixel,
lcd_clearpixel,
lcd_setfont,
font_get,
lcd_clearrect,
lcd_fillrect,
lcd_drawrect,
lcd_invertrect,
lcd_getstringsize,
lcd_update,
lcd_update_rect,
scrollbar,
checkbox,
&lcd_framebuffer[0][0],
lcd_blit,
#ifndef SIMULATOR
lcd_roll,
#endif
#endif
backlight_on,
backlight_off,
backlight_set_timeout,
splash,
/* file */
(open_func)PREFIX(open),
close,
(read_func)read,
PREFIX(lseek),
(creat_func)PREFIX(creat),
(write_func)write,
PREFIX(remove),
PREFIX(rename),
PREFIX(ftruncate),
fdprintf,
read_line,
settings_parseline,
#ifndef SIMULATOR
ata_sleep,
#endif
/* dir */
PREFIX(opendir),
PREFIX(closedir),
PREFIX(readdir),
PREFIX(mkdir),
/* kernel/ system */
PREFIX(sleep),
yield,
&current_tick,
default_event_handler,
default_event_handler_ex,
create_thread,
remove_thread,
reset_poweroff_timer,
#ifndef SIMULATOR
system_memory_guard,
&cpu_frequency,
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
cpu_boost,
#endif
#endif
/* strings and memory */
snprintf,
strcpy,
strncpy,
strlen,
strrchr,
strcmp,
strcasecmp,
strncasecmp,
memset,
memcpy,
_ctype_,
atoi,
strchr,
strcat,
memcmp,
strcasestr,
/* sound */
sound_set,
#ifndef SIMULATOR
mp3_play_data,
mp3_play_pause,
mp3_play_stop,
mp3_is_playing,
#if CONFIG_HWCODEC != MASNONE
bitswap,
#endif
#if CONFIG_HWCODEC == MASNONE
pcm_play_data,
pcm_play_stop,
pcm_set_frequency,
pcm_is_playing,
pcm_play_pause,
#endif
#endif
/* playback control */
PREFIX(audio_play),
audio_stop,
audio_pause,
audio_resume,
audio_next,
audio_prev,
audio_ff_rewind,
audio_next_track,
playlist_amount,
audio_status,
audio_has_changed_track,
audio_current_track,
audio_flush_and_reload_tracks,
audio_get_file_pos,
#if !defined(SIMULATOR) && (CONFIG_HWCODEC != MASNONE)
mpeg_get_last_header,
#endif
#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
sound_set_pitch,
#endif
#if !defined(SIMULATOR) && (CONFIG_HWCODEC != MASNONE)
/* MAS communication */
mas_readmem,
mas_writemem,
mas_readreg,
mas_writereg,
#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
mas_codec_writereg,
mas_codec_readreg,
#endif
#endif /* !simulator and HWCODEC != MASNONE */
/* tag database */
&tagdbheader,
&tagdb_fd,
&tagdb_initialized,
tagdb_init,
/* misc */
srand,
rand,
(qsort_func)qsort,
kbd_input,
get_time,
set_time,
plugin_get_audio_buffer,
#if defined(DEBUG) || defined(SIMULATOR)
debugf,
#endif
&global_settings,
mp3info,
count_mp3_frames,
create_xing_header,
find_next_frame,
battery_level,
battery_level_safe,
#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
peak_meter_scale_value,
peak_meter_set_use_dbfs,
peak_meter_get_use_dbfs,
#endif
#ifdef HAVE_LCD_BITMAP
read_bmp_file,
#endif
/* new stuff at the end, sort into place next time
the API gets incompatible */
#ifdef ROCKBOX_HAS_LOGF
logf,
#endif
};
int codec_load_ram(char* codecptr, size_t size, void* ptr2, size_t bufwrap)
{
enum codec_status (*codec_start)(const struct codec_api* api, void* param);
int copy_n;
int status;
if ((char *)&codecbuf[0] != codecptr) {
/* zero out codec buffer to ensure a properly zeroed bss area */
memset(codecbuf, 0, CODEC_BUFFER_SIZE);
size = MIN(size, CODEC_BUFFER_SIZE);
copy_n = MIN(size, bufwrap);
memcpy(codecbuf, codecptr, copy_n);
size -= copy_n;
if (size > 0) {
memcpy(&codecbuf[copy_n], ptr2, size);
}
}
codec_start = (void*)&codecbuf;
invalidate_icache();
status = codec_start(&ci, NULL);
return status;
}
int codec_load_file(const char *plugin)
{
char msgbuf[80];
int fd;
int rc;
fd = open(plugin, O_RDONLY);
if (fd < 0) {
snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", plugin);
logf("Codec load error:%d", fd);
splash(HZ*2, true, msgbuf);
return fd;
}
rc = read(fd, &codecbuf[0], CODEC_BUFFER_SIZE);
close(fd);
if (rc <= 0) {
logf("Codec read error");
return CODEC_ERROR;
}
return codec_load_ram(codecbuf, (size_t)rc, NULL, 0);
}
static int codec_test(int api_version, int model, int memsize)
{
if (api_version < CODEC_MIN_API_VERSION ||
api_version > CODEC_API_VERSION)
return CODEC_WRONG_API_VERSION;
(void)model;
#if 0
if (model != MODEL)
return CODEC_WRONG_MODEL;
#endif
if (memsize != MEM)
return CODEC_WRONG_MODEL;
return CODEC_OK;
}

403
apps/codecs.h Normal file
View file

@ -0,0 +1,403 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 Björn Stenberg
*
* 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.
*
****************************************************************************/
#ifndef _CODECS_H_
#define _CODECS_H_
/* instruct simulator code to not redefine any symbols when compiling codecs.
(the CODEC macro is defined in apps/codecs/Makefile) */
#ifdef CODEC
#define NO_REDEFINES_PLEASE
#endif
#ifndef MEM
#define MEM 2
#endif
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "config.h"
#include "dir.h"
#include "kernel.h"
#include "button.h"
#include "font.h"
#include "system.h"
#include "lcd.h"
#include "id3.h"
#include "mpeg.h"
#include "audio.h"
#include "mp3_playback.h"
#if (HWCODEC == MASNONE)
#include "pcm_playback.h"
#endif
#include "settings.h"
#include "thread.h"
#include "playlist.h"
#ifdef HAVE_LCD_BITMAP
#include "widgets.h"
#endif
#include "sound.h"
#ifdef HAVE_REMOTE_LCD
#include "lcd-remote.h"
#endif
#ifdef CODEC
#if defined(DEBUG) || defined(SIMULATOR)
#undef DEBUGF
#define DEBUGF rb->debugf
#undef LDEBUGF
#define LDEBUGF rb->debugf
#else
#define DEBUGF(...)
#define LDEBUGF(...)
#endif
#ifdef ROCKBOX_HAS_LOGF
#undef LOGF
#define LOGF rb->logf
#else
#define LOGF(...)
#endif
#endif
/* This size must match the one set in ../plugins/plugin.lds */
#define CODEC_BUFFER_SIZE 0x3C000
#ifdef SIMULATOR
#define PREFIX(_x_) sim_ ## _x_
#else
#define PREFIX(_x_) _x_
#endif
/* increase this every time the api struct changes */
#define CODEC_API_VERSION 40
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */
#define CODEC_MIN_API_VERSION 40
/* codec return codes */
enum codec_status {
CODEC_OK = 0,
CODEC_USB_CONNECTED,
CODEC_WRONG_API_VERSION = -1,
CODEC_WRONG_MODEL = -2,
CODEC_ERROR = -3,
};
/* compatibility test macro */
#define TEST_CODEC_API(_api_) \
do { \
int _rc_ = _api_->codec_test(CODEC_API_VERSION, 1, MEM); \
if (_rc_<0) \
return _rc_; \
} while(0)
/* NOTE: To support backwards compatibility, only add new functions at
the end of the structure. Every time you add a new function,
remember to increase CODEC_API_VERSION. If you make changes to the
existing APIs then also update CODEC_MIN_API_VERSION to current
version
*/
struct codec_api {
/* these two fields must always be first, to ensure
TEST_CODEC_API will always work */
int version;
int (*codec_test)(int api_version, int model, int memsize);
off_t filesize; /* Total file length */
off_t curpos; /* Current buffer position */
/* For gapless mp3 */
struct mp3entry *id3; /* TAG metadata pointer */
struct mp3info *mp3data; /* MP3 metadata pointer */
bool *taginfo_ready; /* Is metadata read */
/* Codec should periodically check if stop_codec is set to true.
In case it's, codec must return with PLUGIN_OK status immediately. */
bool stop_codec;
/* Codec should periodically check if reload_codec is set to true.
In case it's, codec should reload itself without exiting. */
bool reload_codec;
/* If seek_time != 0, codec should seek to that song position (in ms)
if codec supports seeking. */
int seek_time;
/* Returns buffer to malloc array. Only codeclib should need this. */
void* (*get_codec_memory)(size_t *size);
/* Insert PCM data into audio buffer for playback. Playback will start
automatically. */
bool (*audiobuffer_insert)(char *data, size_t length);
/* Set song position in WPS (value in ms). */
void (*set_elapsed)(unsigned int value);
/* Read next <size> amount bytes from file buffer to <ptr>.
Will return number of bytes read or 0 if end of file. */
size_t (*read_filebuf)(void *ptr, size_t size);
/* Request pointer to file buffer which can be used to read
<realsize> amount of data. <reqsize> tells the buffer system
how much data it should try to allocate. If <realsize> is 0,
end of file is reached. */
void* (*request_buffer)(size_t *realsize, size_t reqsize);
/* Advance file buffer position by <amount> amount of bytes. */
void (*advance_buffer)(size_t amount);
/* Advance file buffer to a pointer location inside file buffer. */
void (*advance_buffer_loc)(void *ptr);
/* Seek file buffer to position <newpos> beginning of file. */
bool (*seek_buffer)(off_t newpos);
/* Calculate mp3 seek position from given time data in ms. */
off_t (*mp3_get_filepos)(int newtime);
/* Request file change from file buffer. Returns true is next
track is available and changed. If return value is false,
codec should exit immediately with PLUGIN_OK status. */
bool (*request_next_track)(void);
/* Configure different codec buffer parameters. */
void (*configure)(int setting, void *value);
/* lcd */
void (*lcd_clear_display)(void);
void (*lcd_puts)(int x, int y, const unsigned char *string);
void (*lcd_puts_scroll)(int x, int y, const unsigned char* string);
void (*lcd_stop_scroll)(void);
void (*lcd_set_contrast)(int x);
#ifdef HAVE_LCD_CHARCELLS
void (*lcd_define_pattern)(int which,const char *pattern);
unsigned char (*lcd_get_locked_pattern)(void);
void (*lcd_unlock_pattern)(unsigned char pat);
void (*lcd_putc)(int x, int y, unsigned short ch);
void (*lcd_put_cursor)(int x, int y, char cursor_char);
void (*lcd_remove_cursor)(void);
void (*PREFIX(lcd_icon))(int icon, bool enable);
#else
void (*lcd_putsxy)(int x, int y, const unsigned char *string);
void (*lcd_puts_style)(int x, int y, const unsigned char *str, int style);
void (*lcd_puts_scroll_style)(int x, int y, const unsigned char* string,
int style);
void (*lcd_bitmap)(const unsigned char *src, int x, int y,
int nx, int ny, bool clear);
void (*lcd_drawline)(int x1, int y1, int x2, int y2);
void (*lcd_clearline)(int x1, int y1, int x2, int y2);
void (*lcd_drawpixel)(int x, int y);
void (*lcd_clearpixel)(int x, int y);
void (*lcd_setfont)(int font);
struct font* (*font_get)(int font);
void (*lcd_clearrect)(int x, int y, int nx, int ny);
void (*lcd_fillrect)(int x, int y, int nx, int ny);
void (*lcd_drawrect)(int x, int y, int nx, int ny);
void (*lcd_invertrect)(int x, int y, int nx, int ny);
int (*lcd_getstringsize)(const unsigned char *str, int *w, int *h);
void (*lcd_update)(void);
void (*lcd_update_rect)(int x, int y, int width, int height);
void (*scrollbar)(int x, int y, int width, int height, int items,
int min_shown, int max_shown, int orientation);
void (*checkbox)(int x, int y, int width, int height, bool checked);
unsigned char* lcd_framebuffer;
void (*lcd_blit) (const unsigned char* p_data, int x, int y, int width,
int height, int stride);
#ifndef SIMULATOR
void (*lcd_roll)(int pixels);
#endif
#endif
void (*backlight_on)(void);
void (*backlight_off)(void);
void (*backlight_set_timeout)(int index);
void (*splash)(int ticks, bool center, const char *fmt, ...);
/* file */
int (*PREFIX(open))(const char* pathname, int flags);
int (*close)(int fd);
ssize_t (*read)(int fd, void* buf, size_t count);
off_t (*PREFIX(lseek))(int fd, off_t offset, int whence);
int (*PREFIX(creat))(const char *pathname, mode_t mode);
ssize_t (*write)(int fd, const void* buf, size_t count);
int (*PREFIX(remove))(const char* pathname);
int (*PREFIX(rename))(const char* path, const char* newname);
int (*PREFIX(ftruncate))(int fd, off_t length);
int (*fdprintf)(int fd, const char *fmt, ...);
int (*read_line)(int fd, char* buffer, int buffer_size);
bool (*settings_parseline)(char* line, char** name, char** value);
#ifndef SIMULATOR
int (*ata_sleep)(void);
#endif
/* dir */
DIR* (*PREFIX(opendir))(const char* name);
int (*PREFIX(closedir))(DIR* dir);
struct dirent* (*PREFIX(readdir))(DIR* dir);
int (*PREFIX(mkdir))(const char *name, int mode);
/* kernel/ system */
void (*PREFIX(sleep))(int ticks);
void (*yield)(void);
long* current_tick;
long (*default_event_handler)(long event);
long (*default_event_handler_ex)(long event, void (*callback)(void *), void *parameter);
int (*create_thread)(void* function, void* stack, int stack_size, const char *name);
void (*remove_thread)(int threadnum);
void (*reset_poweroff_timer)(void);
#ifndef SIMULATOR
int (*system_memory_guard)(int newmode);
long *cpu_frequency;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
void (*cpu_boost)(bool on_off);
#endif
#endif
/* strings and memory */
int (*snprintf)(char *buf, size_t size, const char *fmt, ...);
char* (*strcpy)(char *dst, const char *src);
char* (*strncpy)(char *dst, const char *src, size_t length);
size_t (*strlen)(const char *str);
char * (*strrchr)(const char *s, int c);
int (*strcmp)(const char *, const char *);
int (*strcasecmp)(const char *, const char *);
int (*strncasecmp)(const char *s1, const char *s2, size_t n);
void* (*memset)(void *dst, int c, size_t length);
void* (*memcpy)(void *out, const void *in, size_t n);
const char *_ctype_;
int (*atoi)(const char *str);
char *(*strchr)(const char *s, int c);
char *(*strcat)(char *s1, const char *s2);
int (*memcmp)(const void *s1, const void *s2, size_t n);
char *(*strcasestr) (const char* phaystack, const char* pneedle);
/* sound */
void (*sound_set)(int setting, int value);
#ifndef SIMULATOR
void (*mp3_play_data)(const unsigned char* start, int size, void (*get_more)(unsigned char** start, int* size));
void (*mp3_play_pause)(bool play);
void (*mp3_play_stop)(void);
bool (*mp3_is_playing)(void);
#if CONFIG_HWCODEC != MASNONE
void (*bitswap)(unsigned char *data, int length);
#endif
#if CONFIG_HWCODEC == MASNONE
void (*pcm_play_data)(const unsigned char *start, int size,
void (*get_more)(unsigned char** start, long*size));
void (*pcm_play_stop)(void);
void (*pcm_set_frequency)(unsigned int frequency);
bool (*pcm_is_playing)(void);
void (*pcm_play_pause)(bool play);
#endif
#endif /* !SIMULATOR */
/* playback control */
void (*PREFIX(audio_play))(int offset);
void (*audio_stop)(void);
void (*audio_pause)(void);
void (*audio_resume)(void);
void (*audio_next)(void);
void (*audio_prev)(void);
void (*audio_ff_rewind)(int newtime);
struct mp3entry* (*audio_next_track)(void);
int (*playlist_amount)(void);
int (*audio_status)(void);
bool (*audio_has_changed_track)(void);
struct mp3entry* (*audio_current_track)(void);
void (*audio_flush_and_reload_tracks)(void);
int (*audio_get_file_pos)(void);
#if !defined(SIMULATOR) && (CONFIG_HWCODEC != MASNONE)
unsigned long (*mpeg_get_last_header)(void);
#endif
#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
void (*sound_set_pitch)(int pitch);
#endif
/* MAS communication */
#if !defined(SIMULATOR) && (CONFIG_HWCODEC != MASNONE)
int (*mas_readmem)(int bank, int addr, unsigned long* dest, int len);
int (*mas_writemem)(int bank, int addr, const unsigned long* src, int len);
int (*mas_readreg)(int reg);
int (*mas_writereg)(int reg, unsigned int val);
#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
int (*mas_codec_writereg)(int reg, unsigned int val);
int (*mas_codec_readreg)(int reg);
#endif
#endif
/* tag database */
struct tagdb_header *tagdbheader;
int *tagdb_fd;
int *tagdb_initialized;
int (*tagdb_init) (void);
/* misc */
void (*srand)(unsigned int seed);
int (*rand)(void);
void (*qsort)(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
int (*kbd_input)(char* buffer, int buflen);
struct tm* (*get_time)(void);
int (*set_time)(const struct tm *tm);
void* (*plugin_get_audio_buffer)(int* buffer_size);
#if defined(DEBUG) || defined(SIMULATOR)
void (*debugf)(const char *fmt, ...);
#endif
struct user_settings* global_settings;
bool (*mp3info)(struct mp3entry *entry, const char *filename, bool v1first);
int (*count_mp3_frames)(int fd, int startpos, int filesize,
void (*progressfunc)(int));
int (*create_xing_header)(int fd, int startpos, int filesize,
unsigned char *buf, int num_frames,
unsigned long header_template,
void (*progressfunc)(int), bool generate_toc);
unsigned long (*find_next_frame)(int fd, long *offset,
long max_offset, unsigned long last_header);
int (*battery_level)(void);
bool (*battery_level_safe)(void);
#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
unsigned short (*peak_meter_scale_value)(unsigned short val,
int meterwidth);
void (*peak_meter_set_use_dbfs)(int use);
int (*peak_meter_get_use_dbfs)(void);
#endif
#ifdef HAVE_LCD_BITMAP
int (*read_bmp_file)(char* filename, int *get_width, int *get_height,
char *bitmap, int maxsize);
#endif
/* new stuff at the end, sort into place next time
the API gets incompatible */
#ifdef ROCKBOX_HAS_LOGF
void (*logf)(const char *fmt, ...);
#endif
};
/* defined by the codec loader (codec.c) */
#if CONFIG_HWCODEC == MASNONE
int codec_load_ram(char* codecptr, size_t size, void* ptr2, size_t bufwrap);
int codec_load_file(const char* codec);
#endif
/* defined by the codec */
enum codec_status codec_start(struct codec_api* rockbox, void* parameter)
__attribute__ ((section (".entry")));
#endif

View file

@ -10,20 +10,97 @@
INCLUDES = -I$(FIRMDIR)/include -I$(FIRMDIR)/export -I$(FIRMDIR)/common \ INCLUDES = -I$(FIRMDIR)/include -I$(FIRMDIR)/export -I$(FIRMDIR)/common \
-I$(FIRMDIR)/drivers -I$(APPSDIR) -Ilib -I$(BUILDDIR) -I$(FIRMDIR)/drivers -I$(APPSDIR) -Ilib -I$(BUILDDIR)
CFLAGS = $(GCCOPTS) $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \ CFLAGS = $(GCCOPTS) $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \
-DMEM=${MEMORYSIZE} -DMEM=${MEMORYSIZE} -DCODEC
ifdef APPEXTRA ifdef APPEXTRA
INCLUDES += -I$(APPSDIR)/$(APPEXTRA) INCLUDES += -I$(APPSDIR)/$(APPEXTRA)
endif endif
ifdef SOFTWARECODECS
CODECLIBS = -lmad -la52 -lFLAC -lTremor -lwavpack -lmusepack
endif
# we "borrow" the plugin LDS file
LDS := $(APPSDIR)/plugins/plugin.lds
LINKCODEC := $(OBJDIR)/codeclink.lds
DEPFILE = $(OBJDIR)/dep-codecs
# This sets up 'SRC' based on the files mentioned in SOURCES
include $(TOOLSDIR)/makesrc.inc
ROCKS := $(SRC:%.c=$(OBJDIR)/%.codec)
SOURCES = $(SRC)
ELFS := $(SRC:%.c=$(OBJDIR)/%.elf)
OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
# as created by the cross-compiler for win32:
DEFS := $(SRC:%.c=$(OBJDIR)/%.def)
DIRS = .
.PHONY: libmad liba52 libFLAC libTremor libwavpack dumb libmusepack .PHONY: libmad liba52 libFLAC libTremor libwavpack dumb libmusepack
OUTPUT = $(SOFTWARECODECS) OUTPUT = $(SOFTWARECODECS)
all: $(OUTPUT) all: $(OUTPUT) $(ROCKS) $(DEPFILE)
ifndef SIMVER
$(OBJDIR)/%.elf: $(OBJDIR)/%.o $(LINKCODEC)
$(SILENT)(file=`basename $@`; \
echo "LD $$file"; \
$(CC) $(GCCOPTS) -O -nostdlib -o $@ $< -L$(BUILDDIR) $(CODECLIBS) -lcodec -lgcc -T$(LINKCODEC) -Wl,-Map,$(OBJDIR)/$*.map)
$(OBJDIR)/%.codec : $(OBJDIR)/%.elf
@echo "OBJCOPY "`basename $@`
@$(OC) -O binary $< $@
else
ifeq ($(SIMVER), x11)
###################################################
# This is the X11 simulator version
$(OBJDIR)/%.codec : $(OBJDIR)/%.o $(BUILDDIR)/libplugin.a
@echo "LD "`basename $@`
@$(CC) $(CFLAGS) -shared $< -L$(BUILDDIR) $(CODECLIBS) -lplugin -o $@
ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
# 'x' must be kept or you'll have "Win32 error 5"
# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
# #define ERROR_ACCESS_DENIED 5L
else
@chmod -x $@
endif
else # end of x11-simulator
###################################################
# This is the win32 simulator version
DLLTOOLFLAGS = --export-all
DLLWRAPFLAGS = -s --entry _DllMain@12 --target=i386-mingw32 -mno-cygwin
$(OBJDIR)/%.codec : $(OBJDIR)/%.o $(BUILDDIR)/libplugin.a
@echo "DLL "`basename $@`
@$(DLLTOOL) $(DLLTOOLFLAGS) -z $(OBJDIR)/$*.def $<
@$(DLLWRAP) $(DLLWRAPFLAGS) --def $(OBJDIR)/$*.def $< $(BUILDDIR)/libplugin.a \
$(patsubst -l%,$(BUILDDIR)/lib%.a,$(CODECLIBS)) -o $@
ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
# 'x' must be kept or you'll have "Win32 error 5"
# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
# #define ERROR_ACCESS_DENIED 5L
else
@chmod -x $@
endif
endif # end of win32-simulator
endif # end of simulator section
include $(TOOLSDIR)/make.inc include $(TOOLSDIR)/make.inc
$(BUILDDIR)/libcodec.a:
@echo "MAKE in codecs/lib"
@mkdir -p $(OBJDIR)/lib
@$(MAKE) -C lib OBJDIR=$(OBJDIR)/lib
$(LINKCODEC): $(LDS)
@echo "build $@"
@cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) -DCODEC $(INCLUDES) $(TARGET) $(DEFINES) -E -P - >$@
libmad: libmad:
@echo "MAKE in libmad" @echo "MAKE in libmad"

View file

@ -17,7 +17,7 @@
* *
****************************************************************************/ ****************************************************************************/
#include "plugin.h" #include "codec.h"
#include <inttypes.h> /* Needed by a52.h */ #include <inttypes.h> /* Needed by a52.h */
#include <codecs/liba52/config-a52.h> #include <codecs/liba52/config-a52.h>
@ -28,7 +28,7 @@
#define BUFFER_SIZE 4096 #define BUFFER_SIZE 4096
struct plugin_api* rb; struct codec_api* rb;
struct codec_api* ci; struct codec_api* ci;
static float gain = 1; static float gain = 1;
@ -154,17 +154,17 @@ extern char iramstart[];
extern char iramend[]; extern char iramend[];
#endif #endif
/* this is the plugin entry point */ /* this is the codec entry point */
enum plugin_status plugin_start(struct plugin_api* api, void* parm) enum codec_status codec_start(struct codec_api* api, void* parm)
{ {
size_t n; size_t n;
unsigned char* filebuf; unsigned char* filebuf;
/* Generic plugin initialisation */ /* Generic codec initialisation */
TEST_PLUGIN_API(api); TEST_CODEC_API(api);
rb = api; rb = api;
ci = (struct codec_api*)parm; ci = (struct codec_api*)api;
#ifndef SIMULATOR #ifndef SIMULATOR
rb->memcpy(iramstart, iramcopy, iramend-iramstart); rb->memcpy(iramstart, iramcopy, iramend-iramstart);
@ -175,8 +175,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
next_track: next_track:
if (codec_init(api, ci)) { if (codec_init(api)) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
/* Intialise the A52 decoder and check for success */ /* Intialise the A52 decoder and check for success */
@ -206,5 +206,5 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
//NOT NEEDED??: a52_free (state); //NOT NEEDED??: a52_free (state);
return PLUGIN_OK; return CODEC_OK;
} }

View file

@ -17,7 +17,7 @@
* *
****************************************************************************/ ****************************************************************************/
#include "plugin.h" #include "codec.h"
#include <codecs/libFLAC/include/FLAC/seekable_stream_decoder.h> #include <codecs/libFLAC/include/FLAC/seekable_stream_decoder.h>
#include "playback.h" #include "playback.h"
@ -26,7 +26,7 @@
#define FLAC_MAX_SUPPORTED_BLOCKSIZE 4608 #define FLAC_MAX_SUPPORTED_BLOCKSIZE 4608
#define FLAC_MAX_SUPPORTED_CHANNELS 2 #define FLAC_MAX_SUPPORTED_CHANNELS 2
static struct plugin_api* rb; static struct codec_api* rb;
static uint32_t samplesdone; static uint32_t samplesdone;
/* Called when the FLAC decoder needs some FLAC data to decode */ /* Called when the FLAC decoder needs some FLAC data to decode */
@ -159,14 +159,14 @@ extern char iramstart[];
extern char iramend[]; extern char iramend[];
#endif #endif
/* this is the plugin entry point */ /* this is the codec entry point */
enum plugin_status plugin_start(struct plugin_api* api, void* parm) enum codec_status codec_start(struct codec_api* api, void* parm)
{ {
struct codec_api* ci = (struct codec_api*)parm; struct codec_api* ci = api;
FLAC__SeekableStreamDecoder* flacDecoder; FLAC__SeekableStreamDecoder* flacDecoder;
/* Generic plugin initialisation */ /* Generic codec initialisation */
TEST_PLUGIN_API(api); TEST_CODEC_API(api);
/* if you are using a global api pointer, don't forget to copy it! /* if you are using a global api pointer, don't forget to copy it!
otherwise you will get lovely "I04: IllInstr" errors... :-) */ otherwise you will get lovely "I04: IllInstr" errors... :-) */
@ -182,8 +182,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
next_track: next_track:
if (codec_init(api, ci)) { if (codec_init(api)) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
/* Create a decoder instance */ /* Create a decoder instance */
@ -209,7 +209,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
/* QUESTION: What do we do when the init fails? */ /* QUESTION: What do we do when the init fails? */
if (FLAC__seekable_stream_decoder_init(flacDecoder)) { if (FLAC__seekable_stream_decoder_init(flacDecoder)) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
/* The first thing to do is to parse the metadata */ /* The first thing to do is to parse the metadata */
@ -244,5 +244,5 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
if (ci->request_next_track()) if (ci->request_next_track())
goto next_track; goto next_track;
return PLUGIN_OK; return CODEC_OK;
} }

46
apps/codecs/lib/Makefile Normal file
View file

@ -0,0 +1,46 @@
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
# $Id$
#
# ../.. for the codec.h in the apps dir
# .. for stuff in the codecs dir
# . for stuff in the codeclib dir
INCLUDES=-I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
-I$(FIRMDIR)/common -I$(BUILDDIR)
ifdef APPEXTRA
INCLUDES += -I$(APPSDIR)/$(APPEXTRA)
endif
CFLAGS = $(GCCOPTS) \
$(INCLUDES) $(TARGET) $(EXTRA_DEFINES) -DMEM=${MEMORYSIZE} -DCODEC
# This sets up 'SRC' based on the files mentioned in SOURCES
include $(TOOLSDIR)/makesrc.inc
SOURCES = $(SRC)
OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
DEPFILE = $(OBJDIR)/dep-codeclib
DIRS = .
OUTPUT = $(BUILDDIR)/libcodec.a
all: $(OUTPUT)
$(OUTPUT): $(OBJS)
@echo "AR+RANLIB $@"
@$(AR) ruv $@ $+ >/dev/null 2>&1
@$(RANLIB) $@
include $(TOOLSDIR)/make.inc
clean:
@echo "cleaning lib"
@rm -f $(OBJS) $(OUTPUT) $(DEPFILE)
-include $(DEPFILE)

View file

@ -17,21 +17,22 @@
* *
****************************************************************************/ ****************************************************************************/
/* Various "helper functions" common to all the xxx2wav decoder plugins */ /* "helper functions" common to all codecs */
#include "plugin.h" #include "plugin.h"
#include "playback.h" #include "playback.h"
#include "codeclib.h" #include "codeclib.h"
#include "xxx2wav.h" #include "xxx2wav.h"
struct plugin_api* local_rb; struct codec_api *local_rb;
int codec_init(struct plugin_api* rb, struct codec_api* ci) { int codec_init(struct codec_api* rb)
{
local_rb = rb; local_rb = rb;
xxx2wav_set_api(rb); xxx2wav_set_api(rb);
mem_ptr = 0; mem_ptr = 0;
mallocbuf = (unsigned char *)ci->get_codec_memory((size_t *)&bufsize); mallocbuf = (unsigned char *)rb->get_codec_memory((size_t *)&bufsize);
return 0; return 0;
} }

View file

@ -17,7 +17,10 @@
* *
****************************************************************************/ ****************************************************************************/
/* Various "helper functions" common to all the xxx2wav decoder plugins */ #include "config.h"
#include "codecs.h"
/* Various codec "helper functions" */
#if CONFIG_CPU == MCF5249 && !defined(SIMULATOR) #if CONFIG_CPU == MCF5249 && !defined(SIMULATOR)
#define ICODE_ATTR __attribute__ ((section(".icode"))) #define ICODE_ATTR __attribute__ ((section(".icode")))
@ -42,5 +45,5 @@ void *memset(void *s, int c, size_t n);
int memcmp(const void *s1, const void *s2, size_t n); int memcmp(const void *s1, const void *s2, size_t n);
void* memmove(const void *s1, const void *s2, size_t n); void* memmove(const void *s1, const void *s2, size_t n);
int codec_init(struct plugin_api* rb, struct codec_api* ci); int codec_init(struct codec_api* rb);

View file

@ -22,10 +22,10 @@
#if (CONFIG_HWCODEC == MASNONE) #if (CONFIG_HWCODEC == MASNONE)
/* software codec platforms, not for simulator */ /* software codec platforms, not for simulator */
#include "plugin.h" #include "codecs.h"
#include "xxx2wav.h" #include "xxx2wav.h"
static struct plugin_api* local_rb; static struct codec_api* local_rb;
int mem_ptr; int mem_ptr;
int bufsize; int bufsize;
@ -33,11 +33,12 @@ unsigned char* audiobuf; // The actual audio buffer from Rockbox
unsigned char* mallocbuf; // 512K from the start of audio buffer unsigned char* mallocbuf; // 512K from the start of audio buffer
unsigned char* filebuf; // The rest of the audio buffer unsigned char* filebuf; // The rest of the audio buffer
void* codec_malloc(size_t size) { void* codec_malloc(size_t size)
void* x; {
void* x;
x=&mallocbuf[mem_ptr]; x=&mallocbuf[mem_ptr];
mem_ptr+=(size+3)&~3; // Keep memory 32-bit aligned (if it was already?) mem_ptr+=(size+3)&~3; // Keep memory 32-bit aligned (if it was already?)
/* /*
if(TIME_AFTER(*(local_rb->current_tick), last_tick + HZ)) { if(TIME_AFTER(*(local_rb->current_tick), last_tick + HZ)) {
char s[32]; char s[32];
@ -48,24 +49,26 @@ void* codec_malloc(size_t size) {
last_tick = *(local_rb->current_tick); last_tick = *(local_rb->current_tick);
local_rb->lcd_update(); local_rb->lcd_update();
}*/ }*/
return(x); return(x);
} }
void* codec_calloc(size_t nmemb, size_t size) { void* codec_calloc(size_t nmemb, size_t size)
void* x; {
x = codec_malloc(nmemb*size); void* x;
local_rb->memset(x,0,nmemb*size); x = codec_malloc(nmemb*size);
return(x); local_rb->memset(x,0,nmemb*size);
return(x);
} }
void* codec_alloca(size_t size) { void* codec_alloca(size_t size)
void* x; {
x = codec_malloc(size); void* x;
return(x); x = codec_malloc(size);
return(x);
} }
void codec_free(void* ptr) { void codec_free(void* ptr) {
(void)ptr; (void)ptr;
} }
void* codec_realloc(void* ptr, size_t size) { void* codec_realloc(void* ptr, size_t size) {
@ -146,6 +149,7 @@ void display_status(file_info_struct* file_info) {
} }
} }
#if 0
static unsigned char wav_header[44]={'R','I','F','F', // 0 - ChunkID static unsigned char wav_header[44]={'R','I','F','F', // 0 - ChunkID
0,0,0,0, // 4 - ChunkSize (filesize-8) 0,0,0,0, // 4 - ChunkSize (filesize-8)
'W','A','V','E', // 8 - Format 'W','A','V','E', // 8 - Format
@ -160,14 +164,18 @@ static unsigned char wav_header[44]={'R','I','F','F', // 0 - ChunkID
'd','a','t','a', // 36 - Subchunk2ID 'd','a','t','a', // 36 - Subchunk2ID
0,0,0,0 // 40 - Subchunk2Size 0,0,0,0 // 40 - Subchunk2Size
}; };
#endif
void xxx2wav_set_api(struct codec_api* rb)
void xxx2wav_set_api(struct plugin_api* rb)
{ {
local_rb = rb; local_rb = rb;
} }
int local_init(char* infilename, char* outfilename, file_info_struct* file_info, struct plugin_api* rb) { #if 0
int local_init(char* infilename, char* outfilename,
file_info_struct* file_info,
struct codec_api* rb)
{
char s[32]; char s[32];
int i,n,bytesleft; int i,n,bytesleft;
@ -218,7 +226,8 @@ int local_init(char* infilename, char* outfilename, file_info_struct* file_info,
return(0); return(0);
} }
void close_wav(file_info_struct* file_info) { void close_wav(file_info_struct* file_info)
{
int x; int x;
int filesize=local_rb->filesize(file_info->outfile); int filesize=local_rb->filesize(file_info->outfile);
@ -256,4 +265,6 @@ void close_wav(file_info_struct* file_info) {
local_rb->write(file_info->outfile,wav_header,sizeof(wav_header)); local_rb->write(file_info->outfile,wav_header,sizeof(wav_header));
local_rb->close(file_info->outfile); local_rb->close(file_info->outfile);
} }
#endif /* 0 */
#endif /* CONFIG_HWCODEC == MASNONE */ #endif /* CONFIG_HWCODEC == MASNONE */

View file

@ -62,6 +62,8 @@ int memcmp(const void *s1, const void *s2, size_t n);
void* memmove(const void *s1, const void *s2, size_t n); void* memmove(const void *s1, const void *s2, size_t n);
void display_status(file_info_struct* file_info); void display_status(file_info_struct* file_info);
int local_init(char* infilename, char* outfilename, file_info_struct* file_info, struct plugin_api* rb); int local_init(char* infilename, char* outfilename,
file_info_struct* file_info,
struct codec_api* rb);
void close_wav(file_info_struct* file_info); void close_wav(file_info_struct* file_info);
void xxx2wav_set_api(struct plugin_api* rb); void xxx2wav_set_api(struct codec_api* rb);

521
apps/codecs/mpa.c Normal file
View file

@ -0,0 +1,521 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 Dave Chapman
*
* 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 "codec.h"
#include <codecs/libmad/mad.h>
#include "playback.h"
#include "mp3data.h"
#include "lib/codeclib.h"
static struct codec_api* rb;
struct mad_stream Stream IDATA_ATTR;
struct mad_frame Frame IDATA_ATTR;
struct mad_synth Synth IDATA_ATTR;
mad_timer_t Timer;
struct dither d0, d1;
/* The following function is used inside libmad - let's hope it's never
called.
*/
void abort(void) {
}
/* The "dither" code to convert the 24-bit samples produced by libmad was
taken from the coolplayer project - coolplayer.sourceforge.net */
struct dither {
mad_fixed_t error[3];
mad_fixed_t random;
};
# define SAMPLE_DEPTH 16
# define scale(x, y) dither((x), (y))
/*
* NAME: prng()
* DESCRIPTION: 32-bit pseudo-random number generator
*/
static __inline
unsigned long prng(unsigned long state)
{
return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}
/*
* NAME: dither()
* DESCRIPTION: dither and scale sample
*/
static __inline
signed int dither(mad_fixed_t sample, struct dither *dither)
{
unsigned int scalebits;
mad_fixed_t output, mask, random;
enum {
MIN = -MAD_F_ONE,
MAX = MAD_F_ONE - 1
};
/* noise shape */
sample += dither->error[0] - dither->error[1] + dither->error[2];
dither->error[2] = dither->error[1];
dither->error[1] = dither->error[0] / 2;
/* bias */
output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
mask = (1L << scalebits) - 1;
/* dither */
random = prng(dither->random);
output += (random & mask) - (dither->random & mask);
//dither->random = random;
/* clip */
if (output > MAX) {
output = MAX;
if (sample > MAX)
sample = MAX;
}
else if (output < MIN) {
output = MIN;
if (sample < MIN)
sample = MIN;
}
/* quantize */
output &= ~mask;
/* error feedback */
dither->error[0] = sample - output;
/* scale */
return output >> scalebits;
}
static __inline
signed int detect_silence(mad_fixed_t sample)
{
unsigned int scalebits;
mad_fixed_t output, mask;
enum {
MIN = -MAD_F_ONE,
MAX = MAD_F_ONE - 1
};
/* bias */
output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
mask = (1L << scalebits) - 1;
/* clip */
if (output > MAX) {
output = MAX;
if (sample > MAX)
sample = MAX;
}
else if (output < MIN) {
output = MIN;
if (sample < MIN)
sample = MIN;
}
/* quantize */
output &= ~mask;
/* scale */
output >>= scalebits + 4;
if (output == 0x00 || output == 0xff)
return 1;
return 0;
}
#define SHRT_MAX 32767
#define INPUT_CHUNK_SIZE 8192
#define OUTPUT_BUFFER_SIZE 65536 /* Must be an integer multiple of 4. */
unsigned char OutputBuffer[OUTPUT_BUFFER_SIZE];
unsigned char *OutputPtr;
unsigned char *GuardPtr=NULL;
const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
long resampled_data[2][5000]; /* enough to cope with 11khz upsampling */
mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR;
unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR;
/* TODO: what latency does layer 1 have? */
int mpeg_latency[3] = { 0, 481, 529 };
#ifdef USE_IRAM
extern char iramcopy[];
extern char iramstart[];
extern char iramend[];
#endif
#undef DEBUG_GAPLESS
struct resampler {
long last_sample, phase, delta;
};
#if CONFIG_CPU==MCF5249 && !defined(SIMULATOR)
#define INIT() asm volatile ("move.l #0xb0, %macsr") /* frac, round, clip */
#define FRACMUL(x, y) \
({ \
long t; \
asm volatile ("mac.l %[a], %[b], %%acc0\n\t" \
"movclr.l %%acc0, %[t]\n\t" \
: [t] "=r" (t) : [a] "r" (x), [b] "r" (y)); \
t; \
})
#else
#define INIT()
#define FRACMUL(x, y) (long)(((long long)(x)*(long long)(y)) << 1)
#endif
/* linear resampling, introduces one sample delay, because of our inability to
look into the future at the end of a frame */
long downsample(long *in, long *out, int num, struct resampler *s)
{
long i = 1, pos;
long last = s->last_sample;
INIT();
pos = s->phase >> 16;
/* check if we need last sample of previous frame for interpolation */
if (pos > 0)
last = in[pos - 1];
out[0] = last + FRACMUL((s->phase & 0xffff) << 15, in[pos] - last);
s->phase += s->delta;
while ((pos = s->phase >> 16) < num) {
out[i++] = in[pos - 1] + FRACMUL((s->phase & 0xffff) << 15, in[pos] - in[pos - 1]);
s->phase += s->delta;
}
/* wrap phase accumulator back to start of next frame */
s->phase -= num << 16;
s->last_sample = in[num - 1];
return i;
}
long upsample(long *in, long *out, int num, struct resampler *s)
{
long i = 0, pos;
INIT();
while ((pos = s->phase >> 16) == 0) {
out[i++] = s->last_sample + FRACMUL((s->phase & 0xffff) << 15, in[pos] - s->last_sample);
s->phase += s->delta;
}
while ((pos = s->phase >> 16) < num) {
out[i++] = in[pos - 1] + FRACMUL((s->phase & 0xffff) << 15, in[pos] - in[pos - 1]);
s->phase += s->delta;
}
/* wrap phase accumulator back to start of next frame */
s->phase -= num << 16;
s->last_sample = in[num - 1];
return i;
}
long resample(long *in, long *out, int num, struct resampler *s)
{
if (s->delta >= (1 << 16))
return downsample(in, out, num, s);
else
return upsample(in, out, num, s);
}
/* this is the codec entry point */
enum codec_status codec_start(struct codec_api* api, void* parm)
{
struct codec_api *ci = api;
struct mp3info *info;
int Status=0;
size_t size;
int file_end;
unsigned short Sample;
char *InputBuffer;
unsigned int samplecount;
unsigned int samplesdone;
bool first_frame;
#ifdef DEBUG_GAPLESS
bool first = true;
int fd;
#endif
int i;
int yieldcounter = 0;
int stop_skip, start_skip;
struct resampler lr = { 0, 0, 0 }, rr = { 0, 0, 0 };
long length;
/* Generic codec inititialisation */
(void)parm;
TEST_CODEC_API(api);
rb = api;
#ifdef USE_IRAM
rb->memcpy(iramstart, iramcopy, iramend-iramstart);
#endif
/* This function sets up the buffers and reads the file into RAM */
if (codec_init(api)) {
return CODEC_ERROR;
}
/* Create a decoder instance */
ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16));
memset(&Stream, 0, sizeof(struct mad_stream));
memset(&Frame, 0, sizeof(struct mad_frame));
memset(&Synth, 0, sizeof(struct mad_synth));
memset(&Timer, 0, sizeof(mad_timer_t));
mad_stream_init(&Stream);
mad_frame_init(&Frame);
mad_synth_init(&Synth);
mad_timer_reset(&Timer);
/* We do this so libmad doesn't try to call codec_calloc() */
memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
Frame.overlap = &mad_frame_overlap;
Stream.main_data = &mad_main_data;
/* This label might need to be moved above all the init code, but I don't
think reiniting the codec is necessary for MPEG. It might even be unwanted
for gapless playback */
next_track:
#ifdef DEBUG_GAPLESS
if (first)
fd = rb->open("/first.pcm", O_WRONLY | O_CREAT);
else
fd = rb->open("/second.pcm", O_WRONLY | O_CREAT);
first = false;
#endif
info = ci->mp3data;
first_frame = false;
file_end = 0;
OutputPtr = OutputBuffer;
while (!*ci->taginfo_ready)
rb->yield();
ci->request_buffer(&size, ci->id3->first_frame_offset);
ci->advance_buffer(size);
if (info->enc_delay >= 0 && info->enc_padding >= 0) {
stop_skip = info->enc_padding - mpeg_latency[info->layer];
if (stop_skip < 0) stop_skip = 0;
start_skip = info->enc_delay + mpeg_latency[info->layer];
} else {
stop_skip = 0;
/* We want to skip this amount anyway */
start_skip = mpeg_latency[info->layer];
}
/* NOTE: currently this doesn't work, the below calculated samples_count
seems to be right, but sometimes libmad just can't supply us with
all the data we need... */
if (info->frame_count) {
/* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3,
it's probably not correct at all for MPEG2 and layer 1 */
samplecount = info->frame_count*1152 - (start_skip + stop_skip);
samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10;
} else {
samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10;
samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10;
}
/* rb->snprintf(buf2, sizeof(buf2), "sc: %d", samplecount);
rb->splash(0, true, buf2);
rb->snprintf(buf2, sizeof(buf2), "length: %d", ci->id3->length);
rb->splash(HZ*5, true, buf2);
rb->snprintf(buf2, sizeof(buf2), "frequency: %d", ci->id3->frequency);
rb->splash(HZ*5, true, buf2); */
lr.delta = rr.delta = ci->id3->frequency*65536/44100;
/* This is the decoding loop. */
while (1) {
rb->yield();
if (ci->stop_codec || ci->reload_codec) {
break ;
}
if (ci->seek_time) {
unsigned int sample_loc;
int newpos;
sample_loc = ci->seek_time/1000 * ci->id3->frequency;
newpos = ci->mp3_get_filepos(ci->seek_time-1);
if (ci->seek_buffer(newpos)) {
if (sample_loc >= samplecount + samplesdone)
break ;
samplecount += samplesdone - sample_loc;
samplesdone = sample_loc;
}
ci->seek_time = 0;
}
/* Lock buffers */
if (Stream.error == 0) {
InputBuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE);
if (size == 0 || InputBuffer == NULL)
break ;
mad_stream_buffer(&Stream, InputBuffer, size);
}
//if ((int)ci->curpos >= ci->id3->first_frame_offset)
//first_frame = true;
if(mad_frame_decode(&Frame,&Stream))
{
if (Stream.error == MAD_FLAG_INCOMPLETE || Stream.error == MAD_ERROR_BUFLEN) {
// rb->splash(HZ*1, true, "Incomplete");
/* This makes the codec to support partially corrupted files too. */
if (file_end == 30)
break ;
/* Fill the buffer */
Stream.error = 0;
file_end++;
continue ;
}
else if(MAD_RECOVERABLE(Stream.error))
{
if(Stream.error!=MAD_ERROR_LOSTSYNC || Stream.this_frame!=GuardPtr)
{
// rb->splash(HZ*1, true, "Recoverable...!");
}
continue;
}
else if(Stream.error==MAD_ERROR_BUFLEN) {
//rb->splash(HZ*1, true, "Buflen error");
break ;
} else {
//rb->splash(HZ*1, true, "Unrecoverable error");
Status=1;
break;
}
}
if (Stream.next_frame)
ci->advance_buffer_loc((void *)Stream.next_frame);
file_end = false;
/* ?? Do we need the timer module? */
// mad_timer_add(&Timer,Frame.header.duration);
/* DAVE: This can be used to attenuate the audio */
// if(DoFilter)
// ApplyFilter(&Frame);
mad_synth_frame(&Synth,&Frame);
//if (!first_frame) {
//samplecount -= Synth.pcm.length;
//continue ;
//}
/* Convert MAD's numbers to an array of 16-bit LE signed integers */
/* We skip start_skip number of samples here, this should only happen for
very first frame in the stream. */
/* TODO: possible for start_skip to exceed one frames worth of samples? */
length = resample((long *)&Synth.pcm.samples[0][start_skip], resampled_data[0], Synth.pcm.length, &lr);
if (MAD_NCHANNELS(&Frame.header) == 2)
resample((long *)&Synth.pcm.samples[1][start_skip], resampled_data[1], Synth.pcm.length, &rr);
for (i = 0;i<length;i++)
{
start_skip = 0; /* not very elegant, and might want to keep this value */
samplesdone++;
//if (ci->mp3data->padding > 0) {
// ci->mp3data->padding--;
// continue ;
//}
/*if (!first_frame) {
if (detect_silence(Synth.pcm.samples[0][i]))
continue ;
first_frame = true;
}*/
/* Left channel */
Sample=scale(resampled_data[0][i],&d0);
*(OutputPtr++)=Sample>>8;
*(OutputPtr++)=Sample&0xff;
/* Right channel. If the decoded stream is monophonic then
* the right output channel is the same as the left one.
*/
if(MAD_NCHANNELS(&Frame.header)==2)
Sample=scale(resampled_data[1][i],&d1);
*(OutputPtr++)=Sample>>8;
*(OutputPtr++)=Sample&0xff;
samplecount--;
if (samplecount == 0) {
#ifdef DEBUG_GAPLESS
rb->write(fd, OutputBuffer, (int)OutputPtr-(int)OutputBuffer);
#endif
while (!ci->audiobuffer_insert(OutputBuffer, (int)OutputPtr-(int)OutputBuffer))
rb->yield();
goto song_end;
}
if (yieldcounter++ == 200) {
rb->yield();
yieldcounter = 0;
}
/* Flush the buffer if it is full. */
if(OutputPtr==OutputBufferEnd)
{
#ifdef DEBUG_GAPLESS
rb->write(fd, OutputBuffer, OUTPUT_BUFFER_SIZE);
#endif
while (!ci->audiobuffer_insert(OutputBuffer, OUTPUT_BUFFER_SIZE))
rb->yield();
OutputPtr=OutputBuffer;
}
}
ci->set_elapsed(samplesdone / (ci->id3->frequency/1000));
}
song_end:
#ifdef DEBUG_GAPLESS
rb->close(fd);
#endif
Stream.error = 0;
if (ci->request_next_track())
goto next_track;
return CODEC_OK;
}

View file

@ -17,12 +17,12 @@
* *
****************************************************************************/ ****************************************************************************/
#include "plugin.h" #include "codec.h"
#include "playback.h" #include "playback.h"
#include "lib/codeclib.h" #include "lib/codeclib.h"
#include <codecs/libmusepack/musepack.h> #include <codecs/libmusepack/musepack.h>
static struct plugin_api* rb; static struct codec_api* rb;
mpc_decoder decoder; mpc_decoder decoder;
/* /*
@ -92,10 +92,10 @@ extern char iramstart[];
extern char iramend[]; extern char iramend[];
#endif #endif
/* this is the plugin entry point */ /* this is the codec entry point */
enum plugin_status plugin_start(struct plugin_api* api, void* parm) enum codec_status codec_start(struct codec_api* api, void* parm)
{ {
struct codec_api* ci = (struct codec_api*)parm; struct codec_api* ci = api;
unsigned short Sample; unsigned short Sample;
unsigned long samplesdone; unsigned long samplesdone;
unsigned long frequency; unsigned long frequency;
@ -103,9 +103,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
unsigned int i; unsigned int i;
mpc_reader reader; mpc_reader reader;
/* Generic plugin inititialisation */ /* Generic codec inititialisation */
TEST_PLUGIN_API(api); TEST_CODEC_API(api);
rb = api; rb = api;
#ifndef SIMULATOR #ifndef SIMULATOR
@ -117,8 +117,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
next_track: next_track:
if (codec_init(api, ci)) { if (codec_init(api)) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
/* Create a decoder instance */ /* Create a decoder instance */
@ -134,14 +134,14 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
mpc_streaminfo info; mpc_streaminfo info;
mpc_streaminfo_init(&info); mpc_streaminfo_init(&info);
if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) { if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
frequency=info.sample_freq; frequency=info.sample_freq;
/* instantiate a decoder with our file reader */ /* instantiate a decoder with our file reader */
mpc_decoder_setup(&decoder, &reader); mpc_decoder_setup(&decoder, &reader);
if (!mpc_decoder_initialize(&decoder, &info)) { if (!mpc_decoder_initialize(&decoder, &info)) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
/* Initialise the output buffer. */ /* Initialise the output buffer. */
@ -158,7 +158,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
status = mpc_decoder_decode(&decoder, sample_buffer, 0, 0); status = mpc_decoder_decode(&decoder, sample_buffer, 0, 0);
if (status == (unsigned)(-1)) { if (status == (unsigned)(-1)) {
//decode error //decode error
return PLUGIN_ERROR; return CODEC_ERROR;
} }
else //status>0 else //status>0
{ {
@ -209,6 +209,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
if (ci->request_next_track()) if (ci->request_next_track())
goto next_track; goto next_track;
return PLUGIN_OK; return CODEC_OK;
} }

168
apps/codecs/vorbis.c Normal file
View file

@ -0,0 +1,168 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 Björn Stenberg
*
* 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 "kernel.h"
#include "codecs.h"
#include "Tremor/ivorbisfile.h"
#include "playback.h"
#include "lib/codeclib.h"
static struct codec_api* rb;
/* Some standard functions and variables needed by Tremor */
int errno;
size_t strlen(const char *s)
{
return(rb->strlen(s));
}
char *strcpy(char *dest, const char *src)
{
return(rb->strcpy(dest,src));
}
char *strcat(char *dest, const char *src)
{
return(rb->strcat(dest,src));
}
size_t read_handler(void *ptr, size_t size, size_t nmemb, void *datasource)
{
return rb->read_filebuf(ptr, nmemb*size);
}
int seek_handler(void *datasource, ogg_int64_t offset, int whence)
{
/* We are not seekable at the moment */
(void)datasource;
(void)offset;
(void)whence;
return -1;
}
int close_handler(void *datasource)
{
(void)datasource;
return 0;
}
long tell_handler(void *datasource)
{
return rb->curpos;
}
#ifdef USE_IRAM
extern char iramcopy[];
extern char iramstart[];
extern char iramend[];
#endif
/* reserve the PCM buffer in the IRAM area */
static char pcmbuf[4096] IDATA_ATTR;
/* this is the codec entry point */
enum codec_status codec_start(struct codec_api* api, void* parm)
{
ov_callbacks callbacks;
OggVorbis_File vf;
vorbis_info* vi;
int error;
long n;
int current_section;
int eof;
#if BYTE_ORDER == BIG_ENDIAN
int i;
char x;
#endif
TEST_CODEC_API(api);
/* if you are using a global api pointer, don't forget to copy it!
otherwise you will get lovely "I04: IllInstr" errors... :-) */
rb = api;
#ifdef USE_IRAM
rb->memcpy(iramstart, iramcopy, iramend-iramstart);
#endif
rb->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
rb->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*64));
/* We need to flush reserver memory every track load. */
next_track:
if (codec_init(rb)) {
return CODEC_ERROR;
}
/* Create a decoder instance */
callbacks.read_func=read_handler;
callbacks.seek_func=seek_handler;
callbacks.tell_func=tell_handler;
callbacks.close_func=close_handler;
error=ov_open_callbacks(rb,&vf,NULL,0,callbacks);
vi=ov_info(&vf,-1);
if (vi==NULL) {
// rb->splash(HZ*2, true, "Vorbis Error");
return CODEC_ERROR;
}
eof=0;
while (!eof) {
/* Read host-endian signed 16 bit PCM samples */
n=ov_read(&vf,pcmbuf,sizeof(pcmbuf),&current_section);
if (n==0) {
eof=1;
}
else if (n < 0) {
DEBUGF("Error decoding frame\n");
} else {
rb->yield();
if (rb->stop_codec || rb->reload_codec)
break ;
rb->yield();
while (!rb->audiobuffer_insert(pcmbuf, n))
rb->yield();
rb->set_elapsed(ov_time_tell(&vf));
#if BYTE_ORDER == BIG_ENDIAN
for (i=0;i<n;i+=2) {
x=pcmbuf[i]; pcmbuf[i]=pcmbuf[i+1]; pcmbuf[i+1]=x;
}
#endif
}
}
if (rb->request_next_track())
goto next_track;
return CODEC_OK;
}

View file

@ -17,7 +17,7 @@
* *
****************************************************************************/ ****************************************************************************/
#include "plugin.h" #include "codec.h"
#include "playback.h" #include "playback.h"
#include "lib/codeclib.h" #include "lib/codeclib.h"
@ -32,11 +32,11 @@ extern char iramstart[];
extern char iramend[]; extern char iramend[];
#endif #endif
/* this is the plugin entry point */ /* this is the codec entry point */
enum plugin_status plugin_start(struct plugin_api* api, void* parm) enum codec_status codec_start(struct codec_api* api, void* parm)
{ {
struct plugin_api* rb = (struct plugin_api*)api; struct codec_api* rb = api;
struct codec_api* ci = (struct codec_api*)parm; struct codec_api* ci = api;
unsigned long samplerate,numbytes,totalsamples,samplesdone,nsamples; unsigned long samplerate,numbytes,totalsamples,samplesdone,nsamples;
int channels,bytespersample,bitspersample; int channels,bytespersample,bitspersample;
unsigned int i; unsigned int i;
@ -45,8 +45,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
unsigned char* header; unsigned char* header;
unsigned short* wavbuf; unsigned short* wavbuf;
/* Generic plugin initialisation */ /* Generic codec initialisation */
TEST_PLUGIN_API(api); TEST_CODEC_API(api);
/* if you are using a global api pointer, don't forget to copy it! /* if you are using a global api pointer, don't forget to copy it!
otherwise you will get lovely "I04: IllInstr" errors... :-) */ otherwise you will get lovely "I04: IllInstr" errors... :-) */
@ -62,18 +62,18 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
next_track: next_track:
if (codec_init(api, ci)) { if (codec_init(api)) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
/* FIX: Correctly parse WAV header - we assume canonical 44-byte header */ /* FIX: Correctly parse WAV header - we assume canonical 44-byte header */
header=ci->request_buffer(&n,44); header=ci->request_buffer(&n,44);
if (n!=44) { if (n!=44) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
if ((memcmp(header,"RIFF",4)!=0) || (memcmp(&header[8],"WAVEfmt",7)!=0)) { if ((memcmp(header,"RIFF",4)!=0) || (memcmp(&header[8],"WAVEfmt",7)!=0)) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
samplerate=header[24]|(header[25]<<8)|(header[26]<<16)|(header[27]<<24); samplerate=header[24]|(header[25]<<8)|(header[26]<<16)|(header[27]<<24);
@ -84,7 +84,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
totalsamples=numbytes/bytespersample; totalsamples=numbytes/bytespersample;
if ((bitspersample!=16) || (channels != 2)) { if ((bitspersample!=16) || (channels != 2)) {
return PLUGIN_ERROR; return CODEC_ERROR;
} }
ci->advance_buffer(44); ci->advance_buffer(44);
@ -132,5 +132,5 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
if (ci->request_next_track()) if (ci->request_next_track())
goto next_track; goto next_track;
return PLUGIN_OK; return CODEC_OK;
} }

View file

@ -17,13 +17,13 @@
* *
****************************************************************************/ ****************************************************************************/
#include "plugin.h" #include "codec.h"
#include <codecs/libwavpack/wavpack.h> #include <codecs/libwavpack/wavpack.h>
#include "playback.h" #include "playback.h"
#include "lib/codeclib.h" #include "lib/codeclib.h"
static struct plugin_api *rb; static struct codec_api *rb;
static struct codec_api *ci; static struct codec_api *ci;
#define BUFFER_SIZE 4096 #define BUFFER_SIZE 4096
@ -41,18 +41,18 @@ extern char iramstart[];
extern char iramend[]; extern char iramend[];
#endif #endif
/* this is the plugin entry point */ /* this is the codec entry point */
enum plugin_status plugin_start(struct plugin_api* api, void* parm) enum codec_status codec_start(struct codec_api* api, void* parm)
{ {
WavpackContext *wpc; WavpackContext *wpc;
char error [80]; char error [80];
int bps, nchans; int bps, nchans;
/* Generic plugin initialisation */ /* Generic codec initialisation */
TEST_PLUGIN_API(api); TEST_CODEC_API(api);
rb = api; rb = api;
ci = (struct codec_api*) parm; ci = api;
#ifndef SIMULATOR #ifndef SIMULATOR
rb->memcpy(iramstart, iramcopy, iramend-iramstart); rb->memcpy(iramstart, iramcopy, iramend-iramstart);
@ -64,15 +64,15 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
next_track: next_track:
if (codec_init(api, ci)) if (codec_init(api))
return PLUGIN_ERROR; return CODEC_ERROR;
/* Create a decoder instance */ /* Create a decoder instance */
wpc = WavpackOpenFileInput (read_callback, error); wpc = WavpackOpenFileInput (read_callback, error);
if (!wpc) if (!wpc)
return PLUGIN_ERROR; return CODEC_ERROR;
bps = WavpackGetBytesPerSample (wpc); bps = WavpackGetBytesPerSample (wpc);
nchans = WavpackGetReducedChannels (wpc); nchans = WavpackGetReducedChannels (wpc);
@ -181,5 +181,5 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
if (ci->request_next_track()) if (ci->request_next_track())
goto next_track; goto next_track;
return PLUGIN_OK; return CODEC_OK;
} }

View file

@ -33,7 +33,7 @@
#include "debug.h" #include "debug.h"
#include "sprintf.h" #include "sprintf.h"
#include "settings.h" #include "settings.h"
#include "plugin.h" #include "codecs.h"
#include "wps.h" #include "wps.h"
#include "wps-display.h" #include "wps-display.h"
#include "audio.h" #include "audio.h"
@ -63,13 +63,13 @@
static volatile bool playing; static volatile bool playing;
static volatile bool paused; static volatile bool paused;
#define CODEC_VORBIS "/.rockbox/codecs/codecvorbis.rock"; #define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec";
#define CODEC_MPA_L3 "/.rockbox/codecs/codecmpa.rock"; #define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec";
#define CODEC_FLAC "/.rockbox/codecs/codecflac.rock"; #define CODEC_FLAC "/.rockbox/codecs/flac.codec";
#define CODEC_WAV "/.rockbox/codecs/codecwav.rock"; #define CODEC_WAV "/.rockbox/codecs/wav.codec";
#define CODEC_A52 "/.rockbox/codecs/codeca52.rock"; #define CODEC_A52 "/.rockbox/codecs/a52.codec";
#define CODEC_MPC "/.rockbox/codecs/codecmpc.rock"; #define CODEC_MPC "/.rockbox/codecs/mpc.codec";
#define CODEC_WAVPACK "/.rockbox/codecs/codecwavpack.rock"; #define CODEC_WAVPACK "/.rockbox/codecs/wavpack.codec";
#define AUDIO_FILL_CYCLE (1024*256) #define AUDIO_FILL_CYCLE (1024*256)
#define AUDIO_DEFAULT_WATERMARK (1024*256) #define AUDIO_DEFAULT_WATERMARK (1024*256)
@ -153,7 +153,7 @@ static struct track_info tracks[MAX_TRACK];
static volatile struct track_info *cur_ti; static volatile struct track_info *cur_ti;
/* Codec API including function callbacks. */ /* Codec API including function callbacks. */
static struct codec_api ci; extern struct codec_api ci;
/* When we change a song and buffer is not in filling state, this /* When we change a song and buffer is not in filling state, this
variable keeps information about whether to go a next/previous track. */ variable keeps information about whether to go a next/previous track. */
@ -1074,7 +1074,7 @@ void codec_thread(void)
switch (ev.id) { switch (ev.id) {
case CODEC_LOAD_DISK: case CODEC_LOAD_DISK:
ci.stop_codec = false; ci.stop_codec = false;
status = codec_load_file((char *)ev.data, &ci); status = codec_load_file((char *)ev.data);
break ; break ;
case CODEC_LOAD: case CODEC_LOAD:
@ -1089,7 +1089,7 @@ void codec_thread(void)
ci.stop_codec = false; ci.stop_codec = false;
wrap = (int)&codecbuf[codecbuflen] - (int)cur_ti->codecbuf; wrap = (int)&codecbuf[codecbuflen] - (int)cur_ti->codecbuf;
status = codec_load_ram(cur_ti->codecbuf, codecsize, status = codec_load_ram(cur_ti->codecbuf, codecsize,
&ci, &codecbuf[0], wrap); &codecbuf[0], wrap);
break ; break ;
#ifndef SIMULATOR #ifndef SIMULATOR
@ -1103,7 +1103,7 @@ void codec_thread(void)
switch (ev.id) { switch (ev.id) {
case CODEC_LOAD_DISK: case CODEC_LOAD_DISK:
case CODEC_LOAD: case CODEC_LOAD:
if (status != PLUGIN_OK) { if (status != CODEC_OK) {
logf("Codec failure"); logf("Codec failure");
splash(HZ*2, true, "Codec failure"); splash(HZ*2, true, "Codec failure");
playing = false; playing = false;

View file

@ -51,60 +51,6 @@ struct track_info {
int playlist_offset; /* File location in playlist */ int playlist_offset; /* File location in playlist */
}; };
/* Codec Interface */
struct codec_api {
off_t filesize; /* Total file length */
off_t curpos; /* Current buffer position */
/* For gapless mp3 */
struct mp3entry *id3; /* TAG metadata pointer */
struct mp3info *mp3data; /* MP3 metadata pointer */
bool *taginfo_ready; /* Is metadata read */
/* Codec should periodically check if stop_codec is set to true.
In case it's, codec must return with PLUGIN_OK status immediately. */
bool stop_codec;
/* Codec should periodically check if reload_codec is set to true.
In case it's, codec should reload itself without exiting. */
bool reload_codec;
/* If seek_time != 0, codec should seek to that song position (in ms)
if codec supports seeking. */
int seek_time;
/* Returns buffer to malloc array. Only codeclib should need this. */
void* (*get_codec_memory)(size_t *size);
/* Insert PCM data into audio buffer for playback. Playback will start
automatically. */
bool (*audiobuffer_insert)(char *data, size_t length);
/* Set song position in WPS (value in ms). */
void (*set_elapsed)(unsigned int value);
/* Read next <size> amount bytes from file buffer to <ptr>.
Will return number of bytes read or 0 if end of file. */
size_t (*read_filebuf)(void *ptr, size_t size);
/* Request pointer to file buffer which can be used to read
<realsize> amount of data. <reqsize> tells the buffer system
how much data it should try to allocate. If <realsize> is 0,
end of file is reached. */
void* (*request_buffer)(size_t *realsize, size_t reqsize);
/* Advance file buffer position by <amount> amount of bytes. */
void (*advance_buffer)(size_t amount);
/* Advance file buffer to a pointer location inside file buffer. */
void (*advance_buffer_loc)(void *ptr);
/* Seek file buffer to position <newpos> beginning of file. */
bool (*seek_buffer)(off_t newpos);
/* Calculate mp3 seek position from given time data in ms. */
off_t (*mp3_get_filepos)(int newtime);
/* Request file change from file buffer. Returns true is next
track is available and changed. If return value is false,
codec should exit immediately with PLUGIN_OK status. */
bool (*request_next_track)(void);
/* Configure different codec buffer parameters. */
void (*configure)(int setting, void *value);
};
#endif #endif

View file

@ -332,60 +332,6 @@ static const struct plugin_api rockbox_api = {
}; };
#if CONFIG_HWCODEC == MASNONE
int codec_load_ram(char* codecptr, size_t size, void *parameter, void* ptr2,
size_t bufwrap)
{
enum plugin_status (*plugin_start)(struct plugin_api* api, void* param);
int copy_n;
int status;
if ((char *)&codecbuf[0] != codecptr) {
/* zero out codec buffer to ensure a properly zeroed bss area */
memset(codecbuf, 0, CODEC_BUFFER_SIZE);
size = MIN(size, CODEC_BUFFER_SIZE);
copy_n = MIN(size, bufwrap);
memcpy(codecbuf, codecptr, copy_n);
size -= copy_n;
if (size > 0) {
memcpy(&codecbuf[copy_n], ptr2, size);
}
}
plugin_start = (void*)&codecbuf;
invalidate_icache();
status = plugin_start((struct plugin_api*) &rockbox_api, parameter);
return status;
}
int codec_load_file(const char *plugin, void *parameter)
{
char msgbuf[80];
int fd;
int rc;
fd = open(plugin, O_RDONLY);
if (fd < 0) {
snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", plugin);
logf("Codec load error:%d", fd);
splash(HZ*2, true, msgbuf);
return fd;
}
rc = read(fd, &codecbuf[0], CODEC_BUFFER_SIZE);
close(fd);
if (rc <= 0) {
logf("Codec read error");
return PLUGIN_ERROR;
}
return codec_load_ram(codecbuf, (size_t)rc, parameter, NULL, 0);
}
#endif
int plugin_load(const char* plugin, void* parameter) int plugin_load(const char* plugin, void* parameter)
{ {
enum plugin_status (*plugin_start)(struct plugin_api* api, void* param); enum plugin_status (*plugin_start)(struct plugin_api* api, void* param);

View file

@ -403,13 +403,6 @@ struct plugin_api {
#endif #endif
}; };
/* defined by the plugin loader (plugin.c) */
#if CONFIG_HWCODEC == MASNONE
int codec_load_ram(char* pluginptr, size_t size, void *parameter, void* ptr2,
size_t bufwrap);
int codec_load_file(const char* plugin, void* parameter);
#endif
int plugin_load(const char* plugin, void* parameter); int plugin_load(const char* plugin, void* parameter);
void* plugin_get_buffer(int *buffer_size); void* plugin_get_buffer(int *buffer_size);
void* plugin_get_audio_buffer(int *buffer_size); void* plugin_get_audio_buffer(int *buffer_size);

View file

@ -1,7 +0,0 @@
codecvorbis.elf
codecmpa.elf
codecflac.elf
codecwav.elf
codeca52.elf
codecmpc.elf
codecwavpack.elf

View file

@ -22,7 +22,6 @@ endif
LDS := plugin.lds LDS := plugin.lds
LINKFILE := $(OBJDIR)/pluginlink.lds LINKFILE := $(OBJDIR)/pluginlink.lds
LINKCODEC := $(OBJDIR)/codeclink.lds
DEPFILE = $(OBJDIR)/dep-plugins DEPFILE = $(OBJDIR)/dep-plugins
# This sets up 'SRC' based on the files mentioned in SOURCES # This sets up 'SRC' based on the files mentioned in SOURCES
@ -55,13 +54,7 @@ ifndef SIMVER
$(OBJDIR)/%.elf: $(OBJDIR)/%.o $(LINKFILE) $(LINKCODEC) $(BUILDDIR)/libplugin.a $(OBJDIR)/%.elf: $(OBJDIR)/%.o $(LINKFILE) $(LINKCODEC) $(BUILDDIR)/libplugin.a
$(SILENT)(file=`basename $@`; \ $(SILENT)(file=`basename $@`; \
echo "LD $$file"; \ echo "LD $$file"; \
match=`grep $$file CODECS`; \ $(CC) $(GCCOPTS) -O -nostdlib -o $@ $< -L$(BUILDDIR) $(CODECLIBS) -lplugin -lgcc -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/$*.map)
if test -z "$$match"; then \
LINKWITH=$(LINKFILE); \
else \
LINKWITH=$(LINKCODEC); \
fi; \
$(CC) $(GCCOPTS) -O -nostdlib -o $@ $< -L$(BUILDDIR) $(CODECLIBS) -lplugin -lgcc -T$$LINKWITH -Wl,-Map,$(OBJDIR)/$*.map)
$(OBJDIR)/%.rock : $(OBJDIR)/%.elf $(OBJDIR)/%.rock : $(OBJDIR)/%.elf
@echo "OBJCOPY "`basename $@` @echo "OBJCOPY "`basename $@`
@ -108,7 +101,7 @@ endif # end of simulator section
include $(TOOLSDIR)/make.inc include $(TOOLSDIR)/make.inc
$(BUILDDIR)/libplugin.a: $(BUILDDIR)/libplugin.a:
@echo "MAKE in lib" @echo "MAKE in plugin/lib"
@mkdir -p $(OBJDIR)/lib @mkdir -p $(OBJDIR)/lib
@$(MAKE) -C lib OBJDIR=$(OBJDIR)/lib @$(MAKE) -C lib OBJDIR=$(OBJDIR)/lib
@ -116,10 +109,6 @@ $(LINKFILE): $(LDS)
@echo "build $@" @echo "build $@"
@cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P - >$@ @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P - >$@
$(LINKCODEC): $(LDS)
@echo "build $@"
@cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) -DCODEC $(INCLUDES) $(TARGET) $(DEFINES) -E -P - >$@
$(SUBDIRS): $(SUBDIRS):
@echo "MAKE in $@" @echo "MAKE in $@"
@mkdir -p $(OBJDIR)/$@ @mkdir -p $(OBJDIR)/$@

View file

@ -67,22 +67,15 @@ alpine_cdc.c
#endif #endif
#if CONFIG_HWCODEC == MASNONE /* software codec platforms */ #if CONFIG_HWCODEC == MASNONE /* software codec platforms */
#if 0
mpa2wav.c mpa2wav.c
a52towav.c a52towav.c
flac2wav.c flac2wav.c
vorbis2wav.c vorbis2wav.c
#ifdef IRIVER_H100
codecvorbis.c
codecmpa.c
codecflac.c
codecwav.c
codeca52.c
codecmpc.c
codecwavpack.c
#endif
wv2wav.c wv2wav.c
mpc2wav.c mpc2wav.c
midi2wav.c midi2wav.c
#endif
iriverify.c iriverify.c
#else #else
splitedit.c splitedit.c

View file

@ -1,520 +0,0 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 Dave Chapman
*
* 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/libmad/mad.h>
#include "playback.h"
#include "mp3data.h"
#include "lib/codeclib.h"
static struct plugin_api* rb;
struct mad_stream Stream IDATA_ATTR;
struct mad_frame Frame IDATA_ATTR;
struct mad_synth Synth IDATA_ATTR;
mad_timer_t Timer;
struct dither d0, d1;
/* The following function is used inside libmad - let's hope it's never
called.
*/
void abort(void) {
}
/* The "dither" code to convert the 24-bit samples produced by libmad was
taken from the coolplayer project - coolplayer.sourceforge.net */
struct dither {
mad_fixed_t error[3];
mad_fixed_t random;
};
# define SAMPLE_DEPTH 16
# define scale(x, y) dither((x), (y))
/*
* NAME: prng()
* DESCRIPTION: 32-bit pseudo-random number generator
*/
static __inline
unsigned long prng(unsigned long state)
{
return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}
/*
* NAME: dither()
* DESCRIPTION: dither and scale sample
*/
static __inline
signed int dither(mad_fixed_t sample, struct dither *dither)
{
unsigned int scalebits;
mad_fixed_t output, mask, random;
enum {
MIN = -MAD_F_ONE,
MAX = MAD_F_ONE - 1
};
/* noise shape */
sample += dither->error[0] - dither->error[1] + dither->error[2];
dither->error[2] = dither->error[1];
dither->error[1] = dither->error[0] / 2;
/* bias */
output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
mask = (1L << scalebits) - 1;
/* dither */
random = prng(dither->random);
output += (random & mask) - (dither->random & mask);
//dither->random = random;
/* clip */
if (output > MAX) {
output = MAX;
if (sample > MAX)
sample = MAX;
}
else if (output < MIN) {
output = MIN;
if (sample < MIN)
sample = MIN;
}
/* quantize */
output &= ~mask;
/* error feedback */
dither->error[0] = sample - output;
/* scale */
return output >> scalebits;
}
static __inline
signed int detect_silence(mad_fixed_t sample)
{
unsigned int scalebits;
mad_fixed_t output, mask;
enum {
MIN = -MAD_F_ONE,
MAX = MAD_F_ONE - 1
};
/* bias */
output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
mask = (1L << scalebits) - 1;
/* clip */
if (output > MAX) {
output = MAX;
if (sample > MAX)
sample = MAX;
}
else if (output < MIN) {
output = MIN;
if (sample < MIN)
sample = MIN;
}
/* quantize */
output &= ~mask;
/* scale */
output >>= scalebits + 4;
if (output == 0x00 || output == 0xff)
return 1;
return 0;
}
#define SHRT_MAX 32767
#define INPUT_CHUNK_SIZE 8192
#define OUTPUT_BUFFER_SIZE 65536 /* Must be an integer multiple of 4. */
unsigned char OutputBuffer[OUTPUT_BUFFER_SIZE];
unsigned char *OutputPtr;
unsigned char *GuardPtr=NULL;
const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
long resampled_data[2][5000]; /* enough to cope with 11khz upsampling */
mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR;
unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR;
/* TODO: what latency does layer 1 have? */
int mpeg_latency[3] = { 0, 481, 529 };
#ifdef USE_IRAM
extern char iramcopy[];
extern char iramstart[];
extern char iramend[];
#endif
#undef DEBUG_GAPLESS
struct resampler {
long last_sample, phase, delta;
};
#if CONFIG_CPU==MCF5249 && !defined(SIMULATOR)
#define INIT() asm volatile ("move.l #0xb0, %macsr") /* frac, round, clip */
#define FRACMUL(x, y) \
({ \
long t; \
asm volatile ("mac.l %[a], %[b], %%acc0\n\t" \
"movclr.l %%acc0, %[t]\n\t" \
: [t] "=r" (t) : [a] "r" (x), [b] "r" (y)); \
t; \
})
#else
#define INIT()
#define FRACMUL(x, y) (long)(((long long)(x)*(long long)(y)) << 1)
#endif
/* linear resampling, introduces one sample delay, because of our inability to
look into the future at the end of a frame */
long downsample(long *in, long *out, int num, struct resampler *s)
{
long i = 1, pos;
long last = s->last_sample;
INIT();
pos = s->phase >> 16;
/* check if we need last sample of previous frame for interpolation */
if (pos > 0)
last = in[pos - 1];
out[0] = last + FRACMUL((s->phase & 0xffff) << 15, in[pos] - last);
s->phase += s->delta;
while ((pos = s->phase >> 16) < num) {
out[i++] = in[pos - 1] + FRACMUL((s->phase & 0xffff) << 15, in[pos] - in[pos - 1]);
s->phase += s->delta;
}
/* wrap phase accumulator back to start of next frame */
s->phase -= num << 16;
s->last_sample = in[num - 1];
return i;
}
long upsample(long *in, long *out, int num, struct resampler *s)
{
long i = 0, pos;
INIT();
while ((pos = s->phase >> 16) == 0) {
out[i++] = s->last_sample + FRACMUL((s->phase & 0xffff) << 15, in[pos] - s->last_sample);
s->phase += s->delta;
}
while ((pos = s->phase >> 16) < num) {
out[i++] = in[pos - 1] + FRACMUL((s->phase & 0xffff) << 15, in[pos] - in[pos - 1]);
s->phase += s->delta;
}
/* wrap phase accumulator back to start of next frame */
s->phase -= num << 16;
s->last_sample = in[num - 1];
return i;
}
long resample(long *in, long *out, int num, struct resampler *s)
{
if (s->delta >= (1 << 16))
return downsample(in, out, num, s);
else
return upsample(in, out, num, s);
}
/* this is the plugin entry point */
enum plugin_status plugin_start(struct plugin_api* api, void* parm)
{
struct codec_api *ci = (struct codec_api *)parm;
struct mp3info *info;
int Status=0;
size_t size;
int file_end;
unsigned short Sample;
char *InputBuffer;
unsigned int samplecount;
unsigned int samplesdone;
bool first_frame;
#ifdef DEBUG_GAPLESS
bool first = true;
int fd;
#endif
int i;
int yieldcounter = 0;
int stop_skip, start_skip;
struct resampler lr = { 0, 0, 0 }, rr = { 0, 0, 0 };
long length;
/* Generic plugin inititialisation */
TEST_PLUGIN_API(api);
rb = api;
#ifdef USE_IRAM
rb->memcpy(iramstart, iramcopy, iramend-iramstart);
#endif
/* This function sets up the buffers and reads the file into RAM */
if (codec_init(api, ci)) {
return PLUGIN_ERROR;
}
/* Create a decoder instance */
ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16));
memset(&Stream, 0, sizeof(struct mad_stream));
memset(&Frame, 0, sizeof(struct mad_frame));
memset(&Synth, 0, sizeof(struct mad_synth));
memset(&Timer, 0, sizeof(mad_timer_t));
mad_stream_init(&Stream);
mad_frame_init(&Frame);
mad_synth_init(&Synth);
mad_timer_reset(&Timer);
/* We do this so libmad doesn't try to call codec_calloc() */
memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
Frame.overlap = &mad_frame_overlap;
Stream.main_data = &mad_main_data;
/* This label might need to be moved above all the init code, but I don't
think reiniting the codec is necessary for MPEG. It might even be unwanted
for gapless playback */
next_track:
#ifdef DEBUG_GAPLESS
if (first)
fd = rb->open("/first.pcm", O_WRONLY | O_CREAT);
else
fd = rb->open("/second.pcm", O_WRONLY | O_CREAT);
first = false;
#endif
info = ci->mp3data;
first_frame = false;
file_end = 0;
OutputPtr = OutputBuffer;
while (!*ci->taginfo_ready)
rb->yield();
ci->request_buffer(&size, ci->id3->first_frame_offset);
ci->advance_buffer(size);
if (info->enc_delay >= 0 && info->enc_padding >= 0) {
stop_skip = info->enc_padding - mpeg_latency[info->layer];
if (stop_skip < 0) stop_skip = 0;
start_skip = info->enc_delay + mpeg_latency[info->layer];
} else {
stop_skip = 0;
/* We want to skip this amount anyway */
start_skip = mpeg_latency[info->layer];
}
/* NOTE: currently this doesn't work, the below calculated samples_count
seems to be right, but sometimes libmad just can't supply us with
all the data we need... */
if (info->frame_count) {
/* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3,
it's probably not correct at all for MPEG2 and layer 1 */
samplecount = info->frame_count*1152 - (start_skip + stop_skip);
samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10;
} else {
samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10;
samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10;
}
/* rb->snprintf(buf2, sizeof(buf2), "sc: %d", samplecount);
rb->splash(0, true, buf2);
rb->snprintf(buf2, sizeof(buf2), "length: %d", ci->id3->length);
rb->splash(HZ*5, true, buf2);
rb->snprintf(buf2, sizeof(buf2), "frequency: %d", ci->id3->frequency);
rb->splash(HZ*5, true, buf2); */
lr.delta = rr.delta = ci->id3->frequency*65536/44100;
/* This is the decoding loop. */
while (1) {
rb->yield();
if (ci->stop_codec || ci->reload_codec) {
break ;
}
if (ci->seek_time) {
unsigned int sample_loc;
int newpos;
sample_loc = ci->seek_time/1000 * ci->id3->frequency;
newpos = ci->mp3_get_filepos(ci->seek_time-1);
if (ci->seek_buffer(newpos)) {
if (sample_loc >= samplecount + samplesdone)
break ;
samplecount += samplesdone - sample_loc;
samplesdone = sample_loc;
}
ci->seek_time = 0;
}
/* Lock buffers */
if (Stream.error == 0) {
InputBuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE);
if (size == 0 || InputBuffer == NULL)
break ;
mad_stream_buffer(&Stream, InputBuffer, size);
}
//if ((int)ci->curpos >= ci->id3->first_frame_offset)
//first_frame = true;
if(mad_frame_decode(&Frame,&Stream))
{
if (Stream.error == MAD_FLAG_INCOMPLETE || Stream.error == MAD_ERROR_BUFLEN) {
// rb->splash(HZ*1, true, "Incomplete");
/* This makes the codec to support partially corrupted files too. */
if (file_end == 30)
break ;
/* Fill the buffer */
Stream.error = 0;
file_end++;
continue ;
}
else if(MAD_RECOVERABLE(Stream.error))
{
if(Stream.error!=MAD_ERROR_LOSTSYNC || Stream.this_frame!=GuardPtr)
{
// rb->splash(HZ*1, true, "Recoverable...!");
}
continue;
}
else if(Stream.error==MAD_ERROR_BUFLEN) {
//rb->splash(HZ*1, true, "Buflen error");
break ;
} else {
//rb->splash(HZ*1, true, "Unrecoverable error");
Status=1;
break;
}
}
if (Stream.next_frame)
ci->advance_buffer_loc((void *)Stream.next_frame);
file_end = false;
/* ?? Do we need the timer module? */
// mad_timer_add(&Timer,Frame.header.duration);
/* DAVE: This can be used to attenuate the audio */
// if(DoFilter)
// ApplyFilter(&Frame);
mad_synth_frame(&Synth,&Frame);
//if (!first_frame) {
//samplecount -= Synth.pcm.length;
//continue ;
//}
/* Convert MAD's numbers to an array of 16-bit LE signed integers */
/* We skip start_skip number of samples here, this should only happen for
very first frame in the stream. */
/* TODO: possible for start_skip to exceed one frames worth of samples? */
length = resample((long *)&Synth.pcm.samples[0][start_skip], resampled_data[0], Synth.pcm.length, &lr);
if (MAD_NCHANNELS(&Frame.header) == 2)
resample((long *)&Synth.pcm.samples[1][start_skip], resampled_data[1], Synth.pcm.length, &rr);
for (i = 0;i<length;i++)
{
start_skip = 0; /* not very elegant, and might want to keep this value */
samplesdone++;
//if (ci->mp3data->padding > 0) {
// ci->mp3data->padding--;
// continue ;
//}
/*if (!first_frame) {
if (detect_silence(Synth.pcm.samples[0][i]))
continue ;
first_frame = true;
}*/
/* Left channel */
Sample=scale(resampled_data[0][i],&d0);
*(OutputPtr++)=Sample>>8;
*(OutputPtr++)=Sample&0xff;
/* Right channel. If the decoded stream is monophonic then
* the right output channel is the same as the left one.
*/
if(MAD_NCHANNELS(&Frame.header)==2)
Sample=scale(resampled_data[1][i],&d1);
*(OutputPtr++)=Sample>>8;
*(OutputPtr++)=Sample&0xff;
samplecount--;
if (samplecount == 0) {
#ifdef DEBUG_GAPLESS
rb->write(fd, OutputBuffer, (int)OutputPtr-(int)OutputBuffer);
#endif
while (!ci->audiobuffer_insert(OutputBuffer, (int)OutputPtr-(int)OutputBuffer))
rb->yield();
goto song_end;
}
if (yieldcounter++ == 200) {
rb->yield();
yieldcounter = 0;
}
/* Flush the buffer if it is full. */
if(OutputPtr==OutputBufferEnd)
{
#ifdef DEBUG_GAPLESS
rb->write(fd, OutputBuffer, OUTPUT_BUFFER_SIZE);
#endif
while (!ci->audiobuffer_insert(OutputBuffer, OUTPUT_BUFFER_SIZE))
rb->yield();
OutputPtr=OutputBuffer;
}
}
ci->set_elapsed(samplesdone / (ci->id3->frequency/1000));
}
song_end:
#ifdef DEBUG_GAPLESS
rb->close(fd);
#endif
Stream.error = 0;
if (ci->request_next_track())
goto next_track;
return PLUGIN_OK;
}

View file

@ -1,166 +0,0 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 Björn Stenberg
*
* 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 "kernel.h"
#include "plugin.h"
#include <codecs/Tremor/ivorbisfile.h>
#include "playback.h"
#include "lib/codeclib.h"
static struct plugin_api* rb;
/* Some standard functions and variables needed by Tremor */
int errno;
size_t strlen(const char *s) {
return(rb->strlen(s));
}
char *strcpy(char *dest, const char *src) {
return(rb->strcpy(dest,src));
}
char *strcat(char *dest, const char *src) {
return(rb->strcat(dest,src));
}
size_t read_handler(void *ptr, size_t size, size_t nmemb, void *datasource) {
struct codec_api *p = (struct codec_api *) datasource;
return p->read_filebuf(ptr, nmemb*size);
}
int seek_handler(void *datasource, ogg_int64_t offset, int whence) {
/* We are not seekable at the moment */
(void)datasource;
(void)offset;
(void)whence;
return -1;
}
int close_handler(void *datasource) {
(void)datasource;
return 0;
}
long tell_handler(void *datasource) {
struct codec_api *p = (struct codec_api *) datasource;
return p->curpos;
}
#ifdef USE_IRAM
extern char iramcopy[];
extern char iramstart[];
extern char iramend[];
#endif
/* reserve the PCM buffer in the IRAM area */
static char pcmbuf[4096] IDATA_ATTR;
/* this is the plugin entry point */
enum plugin_status plugin_start(struct plugin_api* api, void* parm)
{
struct codec_api *ci = (struct codec_api *)parm;
ov_callbacks callbacks;
OggVorbis_File vf;
vorbis_info* vi;
int error;
long n;
int current_section;
int eof;
#if BYTE_ORDER == BIG_ENDIAN
int i;
char x;
#endif
TEST_PLUGIN_API(api);
/* if you are using a global api pointer, don't forget to copy it!
otherwise you will get lovely "I04: IllInstr" errors... :-) */
rb = api;
#ifdef USE_IRAM
rb->memcpy(iramstart, iramcopy, iramend-iramstart);
#endif
ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*64));
/* We need to flush reserver memory every track load. */
next_track:
if (codec_init(api, ci)) {
return PLUGIN_ERROR;
}
/* Create a decoder instance */
callbacks.read_func=read_handler;
callbacks.seek_func=seek_handler;
callbacks.tell_func=tell_handler;
callbacks.close_func=close_handler;
error=ov_open_callbacks(ci,&vf,NULL,0,callbacks);
vi=ov_info(&vf,-1);
if (vi==NULL) {
// rb->splash(HZ*2, true, "Vorbis Error");
return PLUGIN_ERROR;
}
eof=0;
while (!eof) {
/* Read host-endian signed 16 bit PCM samples */
n=ov_read(&vf,pcmbuf,sizeof(pcmbuf),&current_section);
if (n==0) {
eof=1;
} else if (n < 0) {
DEBUGF("Error decoding frame\n");
} else {
rb->yield();
if (ci->stop_codec || ci->reload_codec)
break ;
rb->yield();
while (!ci->audiobuffer_insert(pcmbuf, n))
rb->yield();
ci->set_elapsed(ov_time_tell(&vf));
#if BYTE_ORDER == BIG_ENDIAN
for (i=0;i<n;i+=2) {
x=pcmbuf[i]; pcmbuf[i]=pcmbuf[i+1]; pcmbuf[i+1]=x;
}
#endif
}
}
if (ci->request_next_track())
goto next_track;
return PLUGIN_OK;
}

View file

@ -34,9 +34,8 @@ gray_verline.c
#ifdef HAVE_LCD_CHARCELLS #ifdef HAVE_LCD_CHARCELLS
playergfx.c playergfx.c
#endif #endif
#if 0
#if CONFIG_HWCODEC == MASNONE /* software codec platforms */ #if CONFIG_HWCODEC == MASNONE /* software codec platforms */
xxx2wav.c xxx2wav.c
#ifdef IRIVER_H100
codeclib.c
#endif #endif
#endif #endif

View file

@ -48,7 +48,7 @@ sub buildzip {
mkdir ".rockbox/langs", 0777; mkdir ".rockbox/langs", 0777;
mkdir ".rockbox/rocks", 0777; mkdir ".rockbox/rocks", 0777;
mkdir ".rockbox/codecs", 0777; mkdir ".rockbox/codecs", 0777;
`find apps -name "codec*.rock" ! -empty | xargs --replace=foo cp foo .rockbox/codecs/`; `find apps -name "*.codec" ! -empty | xargs --replace=foo cp foo .rockbox/codecs/`;
`find apps -name "*.rock" -o -name "*.ovl" ! -empty ! -name "codec*.rock" | xargs --replace=foo cp foo .rockbox/rocks/`; `find apps -name "*.rock" -o -name "*.ovl" ! -empty ! -name "codec*.rock" | xargs --replace=foo cp foo .rockbox/rocks/`;
open VIEWERS, "$ROOT/apps/plugins/viewers.config" or open VIEWERS, "$ROOT/apps/plugins/viewers.config" or