From 1dd672fe3226fa77113f35e4d72f50b863484c63 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 22 Jun 2005 19:41:30 +0000 Subject: [PATCH] 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 --- apps/FILES | 3 +- apps/Makefile | 1 + apps/SOURCES | 3 +- apps/codecs.c | 364 ++++++++++++ apps/codecs.h | 403 ++++++++++++++ apps/codecs/Makefile | 81 ++- apps/{plugins/codeca52.c => codecs/a52.c} | 20 +- apps/{plugins/codecflac.c => codecs/flac.c} | 24 +- apps/codecs/lib/Makefile | 46 ++ apps/{plugins => codecs}/lib/codeclib.c | 9 +- apps/{plugins => codecs}/lib/codeclib.h | 7 +- apps/{plugins => codecs}/lib/xxx2wav.c | 53 +- apps/{plugins => codecs}/lib/xxx2wav.h | 6 +- apps/codecs/mpa.c | 521 ++++++++++++++++++ apps/{plugins/codecmpc.c => codecs/mpc.c} | 26 +- apps/codecs/vorbis.c | 168 ++++++ apps/{plugins/codecwav.c => codecs/wav.c} | 26 +- .../codecwavpack.c => codecs/wavpack.c} | 22 +- apps/playback.c | 24 +- apps/playback.h | 54 -- apps/plugin.c | 54 -- apps/plugin.h | 7 - apps/plugins/CODECS | 7 - apps/plugins/Makefile | 15 +- apps/plugins/SOURCES | 11 +- apps/plugins/codecmpa.c | 520 ----------------- apps/plugins/codecvorbis.c | 166 ------ apps/plugins/lib/SOURCES | 3 +- tools/buildzip.pl | 2 +- 29 files changed, 1709 insertions(+), 937 deletions(-) create mode 100644 apps/codecs.c create mode 100644 apps/codecs.h rename apps/{plugins/codeca52.c => codecs/a52.c} (93%) rename apps/{plugins/codecflac.c => codecs/flac.c} (95%) create mode 100644 apps/codecs/lib/Makefile rename apps/{plugins => codecs}/lib/codeclib.c (81%) rename apps/{plugins => codecs}/lib/codeclib.h (92%) rename apps/{plugins => codecs}/lib/xxx2wav.c (90%) rename apps/{plugins => codecs}/lib/xxx2wav.h (92%) create mode 100644 apps/codecs/mpa.c rename apps/{plugins/codecmpc.c => codecs/mpc.c} (92%) create mode 100644 apps/codecs/vorbis.c rename apps/{plugins/codecwav.c => codecs/wav.c} (88%) rename apps/{plugins/codecwavpack.c => codecs/wavpack.c} (93%) delete mode 100644 apps/plugins/CODECS delete mode 100644 apps/plugins/codecmpa.c delete mode 100644 apps/plugins/codecvorbis.c diff --git a/apps/FILES b/apps/FILES index daa1856093..2a25386a6f 100644 --- a/apps/FILES +++ b/apps/FILES @@ -16,7 +16,6 @@ plugins/viewers.config plugins/snake2.levels SOURCES plugins/SOURCES -plugins/CODECS plugins/lib/SOURCES plugins/rockboy/*.[ch] plugins/rockboy/Makefile @@ -53,3 +52,5 @@ codecs/dumb/src/core/* codecs/dumb/src/helpers/* codecs/dumb/src/it/* codecs/libmusepack/* +codecs/lib/*.[ch] +codecs/lib/Makefile diff --git a/apps/Makefile b/apps/Makefile index 6287f494dc..ec97a6666a 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -57,6 +57,7 @@ endif dep: $(DEPFILE) build-codecs: + @$(MAKE) -C codecs/lib OBJDIR=$(OBJDIR)/codecs/lib @$(MAKE) -C codecs OBJDIR=$(OBJDIR)/codecs rocks: diff --git a/apps/SOURCES b/apps/SOURCES index fb8acd75c6..738533105b 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -48,9 +48,10 @@ recorder/radio.c #ifdef HAVE_RECORDING recorder/recording.c #endif -#ifdef IRIVER_H100 +#if CONFIG_HWCODEC == MASNONE playback.c metadata.c +codecs.c #ifndef SIMULATOR pcm_recording.c #endif diff --git a/apps/codecs.c b/apps/codecs.c new file mode 100644 index 0000000000..d366c934da --- /dev/null +++ b/apps/codecs.c @@ -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 +#include +#include +#include +#include +#include +#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, + ¤t_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; +} diff --git a/apps/codecs.h b/apps/codecs.h new file mode 100644 index 0000000000..2c2a4cfe43 --- /dev/null +++ b/apps/codecs.h @@ -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 +#include +#include +#include +#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 amount bytes from file buffer to . + 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 + amount of data. tells the buffer system + how much data it should try to allocate. If is 0, + end of file is reached. */ + void* (*request_buffer)(size_t *realsize, size_t reqsize); + /* Advance file buffer position by 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 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 diff --git a/apps/codecs/Makefile b/apps/codecs/Makefile index ffd8eab44d..970048e6a0 100644 --- a/apps/codecs/Makefile +++ b/apps/codecs/Makefile @@ -10,20 +10,97 @@ INCLUDES = -I$(FIRMDIR)/include -I$(FIRMDIR)/export -I$(FIRMDIR)/common \ -I$(FIRMDIR)/drivers -I$(APPSDIR) -Ilib -I$(BUILDDIR) CFLAGS = $(GCCOPTS) $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \ - -DMEM=${MEMORYSIZE} + -DMEM=${MEMORYSIZE} -DCODEC ifdef APPEXTRA INCLUDES += -I$(APPSDIR)/$(APPEXTRA) 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 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 +$(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: @echo "MAKE in libmad" diff --git a/apps/plugins/codeca52.c b/apps/codecs/a52.c similarity index 93% rename from apps/plugins/codeca52.c rename to apps/codecs/a52.c index ced5ced4a4..d35854e16e 100644 --- a/apps/plugins/codeca52.c +++ b/apps/codecs/a52.c @@ -17,7 +17,7 @@ * ****************************************************************************/ -#include "plugin.h" +#include "codec.h" #include /* Needed by a52.h */ #include @@ -28,7 +28,7 @@ #define BUFFER_SIZE 4096 -struct plugin_api* rb; +struct codec_api* rb; struct codec_api* ci; static float gain = 1; @@ -154,17 +154,17 @@ extern char iramstart[]; extern char iramend[]; #endif -/* this is the plugin entry point */ -enum plugin_status plugin_start(struct plugin_api* api, void* parm) +/* this is the codec entry point */ +enum codec_status codec_start(struct codec_api* api, void* parm) { size_t n; unsigned char* filebuf; - /* Generic plugin initialisation */ - TEST_PLUGIN_API(api); + /* Generic codec initialisation */ + TEST_CODEC_API(api); rb = api; - ci = (struct codec_api*)parm; + ci = (struct codec_api*)api; #ifndef SIMULATOR rb->memcpy(iramstart, iramcopy, iramend-iramstart); @@ -175,8 +175,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) next_track: - if (codec_init(api, ci)) { - return PLUGIN_ERROR; + if (codec_init(api)) { + return CODEC_ERROR; } /* 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); - return PLUGIN_OK; + return CODEC_OK; } diff --git a/apps/plugins/codecflac.c b/apps/codecs/flac.c similarity index 95% rename from apps/plugins/codecflac.c rename to apps/codecs/flac.c index 1cc95b3f2d..93134bb801 100644 --- a/apps/plugins/codecflac.c +++ b/apps/codecs/flac.c @@ -17,7 +17,7 @@ * ****************************************************************************/ -#include "plugin.h" +#include "codec.h" #include #include "playback.h" @@ -26,7 +26,7 @@ #define FLAC_MAX_SUPPORTED_BLOCKSIZE 4608 #define FLAC_MAX_SUPPORTED_CHANNELS 2 -static struct plugin_api* rb; +static struct codec_api* rb; static uint32_t samplesdone; /* Called when the FLAC decoder needs some FLAC data to decode */ @@ -159,14 +159,14 @@ extern char iramstart[]; extern char iramend[]; #endif -/* this is the plugin entry point */ -enum plugin_status plugin_start(struct plugin_api* api, void* parm) +/* this is the codec entry point */ +enum codec_status codec_start(struct codec_api* api, void* parm) { - struct codec_api* ci = (struct codec_api*)parm; - FLAC__SeekableStreamDecoder* flacDecoder; + struct codec_api* ci = api; + FLAC__SeekableStreamDecoder* flacDecoder; - /* Generic plugin initialisation */ - TEST_PLUGIN_API(api); + /* Generic codec initialisation */ + 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... :-) */ @@ -182,8 +182,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) next_track: - if (codec_init(api, ci)) { - return PLUGIN_ERROR; + if (codec_init(api)) { + return CODEC_ERROR; } /* 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? */ if (FLAC__seekable_stream_decoder_init(flacDecoder)) { - return PLUGIN_ERROR; + return CODEC_ERROR; } /* 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()) goto next_track; - return PLUGIN_OK; + return CODEC_OK; } diff --git a/apps/codecs/lib/Makefile b/apps/codecs/lib/Makefile new file mode 100644 index 0000000000..08dcd2a66b --- /dev/null +++ b/apps/codecs/lib/Makefile @@ -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) diff --git a/apps/plugins/lib/codeclib.c b/apps/codecs/lib/codeclib.c similarity index 81% rename from apps/plugins/lib/codeclib.c rename to apps/codecs/lib/codeclib.c index 9d9cc0b91b..3aa6216be3 100644 --- a/apps/plugins/lib/codeclib.c +++ b/apps/codecs/lib/codeclib.c @@ -17,21 +17,22 @@ * ****************************************************************************/ -/* Various "helper functions" common to all the xxx2wav decoder plugins */ +/* "helper functions" common to all codecs */ #include "plugin.h" #include "playback.h" #include "codeclib.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; xxx2wav_set_api(rb); 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; } diff --git a/apps/plugins/lib/codeclib.h b/apps/codecs/lib/codeclib.h similarity index 92% rename from apps/plugins/lib/codeclib.h rename to apps/codecs/lib/codeclib.h index 876e69b57e..116f210c5f 100644 --- a/apps/plugins/lib/codeclib.h +++ b/apps/codecs/lib/codeclib.h @@ -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) #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); 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); diff --git a/apps/plugins/lib/xxx2wav.c b/apps/codecs/lib/xxx2wav.c similarity index 90% rename from apps/plugins/lib/xxx2wav.c rename to apps/codecs/lib/xxx2wav.c index 8eadfb815e..1bc1837f39 100644 --- a/apps/plugins/lib/xxx2wav.c +++ b/apps/codecs/lib/xxx2wav.c @@ -22,10 +22,10 @@ #if (CONFIG_HWCODEC == MASNONE) /* software codec platforms, not for simulator */ -#include "plugin.h" +#include "codecs.h" #include "xxx2wav.h" -static struct plugin_api* local_rb; +static struct codec_api* local_rb; int mem_ptr; 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* filebuf; // The rest of the audio buffer -void* codec_malloc(size_t size) { - void* x; +void* codec_malloc(size_t size) +{ + void* x; - x=&mallocbuf[mem_ptr]; - mem_ptr+=(size+3)&~3; // Keep memory 32-bit aligned (if it was already?) + x=&mallocbuf[mem_ptr]; + mem_ptr+=(size+3)&~3; // Keep memory 32-bit aligned (if it was already?) /* if(TIME_AFTER(*(local_rb->current_tick), last_tick + HZ)) { char s[32]; @@ -48,24 +49,26 @@ void* codec_malloc(size_t size) { last_tick = *(local_rb->current_tick); local_rb->lcd_update(); }*/ - return(x); + return(x); } -void* codec_calloc(size_t nmemb, size_t size) { - void* x; - x = codec_malloc(nmemb*size); - local_rb->memset(x,0,nmemb*size); - return(x); +void* codec_calloc(size_t nmemb, size_t size) +{ + void* x; + x = codec_malloc(nmemb*size); + local_rb->memset(x,0,nmemb*size); + return(x); } -void* codec_alloca(size_t size) { - void* x; - x = codec_malloc(size); - return(x); +void* codec_alloca(size_t size) +{ + void* x; + x = codec_malloc(size); + return(x); } void codec_free(void* ptr) { - (void)ptr; + (void)ptr; } 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 0,0,0,0, // 4 - ChunkSize (filesize-8) '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 0,0,0,0 // 40 - Subchunk2Size }; +#endif - -void xxx2wav_set_api(struct plugin_api* rb) +void xxx2wav_set_api(struct codec_api* 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]; int i,n,bytesleft; @@ -218,7 +226,8 @@ int local_init(char* infilename, char* outfilename, file_info_struct* file_info, return(0); } -void close_wav(file_info_struct* file_info) { +void close_wav(file_info_struct* file_info) +{ int x; 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->close(file_info->outfile); } +#endif /* 0 */ + #endif /* CONFIG_HWCODEC == MASNONE */ diff --git a/apps/plugins/lib/xxx2wav.h b/apps/codecs/lib/xxx2wav.h similarity index 92% rename from apps/plugins/lib/xxx2wav.h rename to apps/codecs/lib/xxx2wav.h index 7e1b942820..1fa7dc9413 100644 --- a/apps/plugins/lib/xxx2wav.h +++ b/apps/codecs/lib/xxx2wav.h @@ -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 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 xxx2wav_set_api(struct plugin_api* rb); +void xxx2wav_set_api(struct codec_api* rb); diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c new file mode 100644 index 0000000000..beb71d78a5 --- /dev/null +++ b/apps/codecs/mpa.c @@ -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 + +#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;imp3data->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; +} diff --git a/apps/plugins/codecmpc.c b/apps/codecs/mpc.c similarity index 92% rename from apps/plugins/codecmpc.c rename to apps/codecs/mpc.c index 19eb518687..9b4a6164ef 100644 --- a/apps/plugins/codecmpc.c +++ b/apps/codecs/mpc.c @@ -17,12 +17,12 @@ * ****************************************************************************/ -#include "plugin.h" +#include "codec.h" #include "playback.h" #include "lib/codeclib.h" #include -static struct plugin_api* rb; +static struct codec_api* rb; mpc_decoder decoder; /* @@ -92,10 +92,10 @@ extern char iramstart[]; extern char iramend[]; #endif -/* this is the plugin entry point */ -enum plugin_status plugin_start(struct plugin_api* api, void* parm) +/* this is the codec entry point */ +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 long samplesdone; unsigned long frequency; @@ -103,9 +103,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) unsigned int i; mpc_reader reader; - /* Generic plugin inititialisation */ + /* Generic codec inititialisation */ - TEST_PLUGIN_API(api); + TEST_CODEC_API(api); rb = api; #ifndef SIMULATOR @@ -117,8 +117,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) next_track: - if (codec_init(api, ci)) { - return PLUGIN_ERROR; + if (codec_init(api)) { + return CODEC_ERROR; } /* Create a decoder instance */ @@ -134,14 +134,14 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) mpc_streaminfo info; mpc_streaminfo_init(&info); if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) { - return PLUGIN_ERROR; + return CODEC_ERROR; } frequency=info.sample_freq; /* instantiate a decoder with our file reader */ mpc_decoder_setup(&decoder, &reader); if (!mpc_decoder_initialize(&decoder, &info)) { - return PLUGIN_ERROR; + return CODEC_ERROR; } /* 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); if (status == (unsigned)(-1)) { //decode error - return PLUGIN_ERROR; + return CODEC_ERROR; } else //status>0 { @@ -209,6 +209,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) if (ci->request_next_track()) goto next_track; - return PLUGIN_OK; + return CODEC_OK; } diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c new file mode 100644 index 0000000000..969fdf365b --- /dev/null +++ b/apps/codecs/vorbis.c @@ -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),¤t_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;irequest_next_track()) + goto next_track; + + return CODEC_OK; +} + diff --git a/apps/plugins/codecwav.c b/apps/codecs/wav.c similarity index 88% rename from apps/plugins/codecwav.c rename to apps/codecs/wav.c index 230b316a82..d750b64b62 100644 --- a/apps/plugins/codecwav.c +++ b/apps/codecs/wav.c @@ -17,7 +17,7 @@ * ****************************************************************************/ -#include "plugin.h" +#include "codec.h" #include "playback.h" #include "lib/codeclib.h" @@ -32,11 +32,11 @@ extern char iramstart[]; extern char iramend[]; #endif -/* this is the plugin entry point */ -enum plugin_status plugin_start(struct plugin_api* api, void* parm) +/* this is the codec entry point */ +enum codec_status codec_start(struct codec_api* api, void* parm) { - struct plugin_api* rb = (struct plugin_api*)api; - struct codec_api* ci = (struct codec_api*)parm; + struct codec_api* rb = api; + struct codec_api* ci = api; unsigned long samplerate,numbytes,totalsamples,samplesdone,nsamples; int channels,bytespersample,bitspersample; unsigned int i; @@ -45,8 +45,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) unsigned char* header; unsigned short* wavbuf; - /* Generic plugin initialisation */ - TEST_PLUGIN_API(api); + /* Generic codec initialisation */ + 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... :-) */ @@ -62,18 +62,18 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) next_track: - if (codec_init(api, ci)) { - return PLUGIN_ERROR; + if (codec_init(api)) { + return CODEC_ERROR; } /* FIX: Correctly parse WAV header - we assume canonical 44-byte header */ header=ci->request_buffer(&n,44); if (n!=44) { - return PLUGIN_ERROR; + return CODEC_ERROR; } 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); @@ -84,7 +84,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) totalsamples=numbytes/bytespersample; if ((bitspersample!=16) || (channels != 2)) { - return PLUGIN_ERROR; + return CODEC_ERROR; } ci->advance_buffer(44); @@ -132,5 +132,5 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) if (ci->request_next_track()) goto next_track; - return PLUGIN_OK; + return CODEC_OK; } diff --git a/apps/plugins/codecwavpack.c b/apps/codecs/wavpack.c similarity index 93% rename from apps/plugins/codecwavpack.c rename to apps/codecs/wavpack.c index 1e56dbd88e..e18dac6a36 100644 --- a/apps/plugins/codecwavpack.c +++ b/apps/codecs/wavpack.c @@ -17,13 +17,13 @@ * ****************************************************************************/ -#include "plugin.h" +#include "codec.h" #include #include "playback.h" #include "lib/codeclib.h" -static struct plugin_api *rb; +static struct codec_api *rb; static struct codec_api *ci; #define BUFFER_SIZE 4096 @@ -41,18 +41,18 @@ extern char iramstart[]; extern char iramend[]; #endif -/* this is the plugin entry point */ -enum plugin_status plugin_start(struct plugin_api* api, void* parm) +/* this is the codec entry point */ +enum codec_status codec_start(struct codec_api* api, void* parm) { WavpackContext *wpc; char error [80]; int bps, nchans; - /* Generic plugin initialisation */ - TEST_PLUGIN_API(api); + /* Generic codec initialisation */ + TEST_CODEC_API(api); rb = api; - ci = (struct codec_api*) parm; + ci = api; #ifndef SIMULATOR rb->memcpy(iramstart, iramcopy, iramend-iramstart); @@ -64,15 +64,15 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) next_track: - if (codec_init(api, ci)) - return PLUGIN_ERROR; + if (codec_init(api)) + return CODEC_ERROR; /* Create a decoder instance */ wpc = WavpackOpenFileInput (read_callback, error); if (!wpc) - return PLUGIN_ERROR; + return CODEC_ERROR; bps = WavpackGetBytesPerSample (wpc); nchans = WavpackGetReducedChannels (wpc); @@ -181,5 +181,5 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) if (ci->request_next_track()) goto next_track; - return PLUGIN_OK; + return CODEC_OK; } diff --git a/apps/playback.c b/apps/playback.c index 0881d6e4c5..3bd4ff69dd 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -33,7 +33,7 @@ #include "debug.h" #include "sprintf.h" #include "settings.h" -#include "plugin.h" +#include "codecs.h" #include "wps.h" #include "wps-display.h" #include "audio.h" @@ -63,13 +63,13 @@ static volatile bool playing; static volatile bool paused; -#define CODEC_VORBIS "/.rockbox/codecs/codecvorbis.rock"; -#define CODEC_MPA_L3 "/.rockbox/codecs/codecmpa.rock"; -#define CODEC_FLAC "/.rockbox/codecs/codecflac.rock"; -#define CODEC_WAV "/.rockbox/codecs/codecwav.rock"; -#define CODEC_A52 "/.rockbox/codecs/codeca52.rock"; -#define CODEC_MPC "/.rockbox/codecs/codecmpc.rock"; -#define CODEC_WAVPACK "/.rockbox/codecs/codecwavpack.rock"; +#define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"; +#define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"; +#define CODEC_FLAC "/.rockbox/codecs/flac.codec"; +#define CODEC_WAV "/.rockbox/codecs/wav.codec"; +#define CODEC_A52 "/.rockbox/codecs/a52.codec"; +#define CODEC_MPC "/.rockbox/codecs/mpc.codec"; +#define CODEC_WAVPACK "/.rockbox/codecs/wavpack.codec"; #define AUDIO_FILL_CYCLE (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; /* 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 variable keeps information about whether to go a next/previous track. */ @@ -1074,7 +1074,7 @@ void codec_thread(void) switch (ev.id) { case CODEC_LOAD_DISK: ci.stop_codec = false; - status = codec_load_file((char *)ev.data, &ci); + status = codec_load_file((char *)ev.data); break ; case CODEC_LOAD: @@ -1089,7 +1089,7 @@ void codec_thread(void) ci.stop_codec = false; wrap = (int)&codecbuf[codecbuflen] - (int)cur_ti->codecbuf; status = codec_load_ram(cur_ti->codecbuf, codecsize, - &ci, &codecbuf[0], wrap); + &codecbuf[0], wrap); break ; #ifndef SIMULATOR @@ -1103,7 +1103,7 @@ void codec_thread(void) switch (ev.id) { case CODEC_LOAD_DISK: case CODEC_LOAD: - if (status != PLUGIN_OK) { + if (status != CODEC_OK) { logf("Codec failure"); splash(HZ*2, true, "Codec failure"); playing = false; diff --git a/apps/playback.h b/apps/playback.h index 06b82b40e4..24fc8570e8 100644 --- a/apps/playback.h +++ b/apps/playback.h @@ -51,60 +51,6 @@ struct track_info { 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 amount bytes from file buffer to . - 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 - amount of data. tells the buffer system - how much data it should try to allocate. If is 0, - end of file is reached. */ - void* (*request_buffer)(size_t *realsize, size_t reqsize); - /* Advance file buffer position by 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 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 diff --git a/apps/plugin.c b/apps/plugin.c index a1a0b0629c..97f811e252 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -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) { enum plugin_status (*plugin_start)(struct plugin_api* api, void* param); diff --git a/apps/plugin.h b/apps/plugin.h index 94967c7673..6bd4ed7fe2 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -403,13 +403,6 @@ struct plugin_api { #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); void* plugin_get_buffer(int *buffer_size); void* plugin_get_audio_buffer(int *buffer_size); diff --git a/apps/plugins/CODECS b/apps/plugins/CODECS deleted file mode 100644 index ea921a68da..0000000000 --- a/apps/plugins/CODECS +++ /dev/null @@ -1,7 +0,0 @@ -codecvorbis.elf -codecmpa.elf -codecflac.elf -codecwav.elf -codeca52.elf -codecmpc.elf -codecwavpack.elf diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile index 44e055d2a4..fbae027ca3 100644 --- a/apps/plugins/Makefile +++ b/apps/plugins/Makefile @@ -22,7 +22,6 @@ endif LDS := plugin.lds LINKFILE := $(OBJDIR)/pluginlink.lds -LINKCODEC := $(OBJDIR)/codeclink.lds DEPFILE = $(OBJDIR)/dep-plugins # 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 $(SILENT)(file=`basename $@`; \ echo "LD $$file"; \ - match=`grep $$file CODECS`; \ - 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) + $(CC) $(GCCOPTS) -O -nostdlib -o $@ $< -L$(BUILDDIR) $(CODECLIBS) -lplugin -lgcc -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/$*.map) $(OBJDIR)/%.rock : $(OBJDIR)/%.elf @echo "OBJCOPY "`basename $@` @@ -108,7 +101,7 @@ endif # end of simulator section include $(TOOLSDIR)/make.inc $(BUILDDIR)/libplugin.a: - @echo "MAKE in lib" + @echo "MAKE in plugin/lib" @mkdir -p $(OBJDIR)/lib @$(MAKE) -C lib OBJDIR=$(OBJDIR)/lib @@ -116,10 +109,6 @@ $(LINKFILE): $(LDS) @echo "build $@" @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P - >$@ -$(LINKCODEC): $(LDS) - @echo "build $@" - @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) -DCODEC $(INCLUDES) $(TARGET) $(DEFINES) -E -P - >$@ - $(SUBDIRS): @echo "MAKE in $@" @mkdir -p $(OBJDIR)/$@ diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index 34f014d9d6..933625aac2 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES @@ -67,22 +67,15 @@ alpine_cdc.c #endif #if CONFIG_HWCODEC == MASNONE /* software codec platforms */ +#if 0 mpa2wav.c a52towav.c flac2wav.c vorbis2wav.c -#ifdef IRIVER_H100 -codecvorbis.c -codecmpa.c -codecflac.c -codecwav.c -codeca52.c -codecmpc.c -codecwavpack.c -#endif wv2wav.c mpc2wav.c midi2wav.c +#endif iriverify.c #else splitedit.c diff --git a/apps/plugins/codecmpa.c b/apps/plugins/codecmpa.c deleted file mode 100644 index 768c3fe0fd..0000000000 --- a/apps/plugins/codecmpa.c +++ /dev/null @@ -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 - -#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;imp3data->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; -} diff --git a/apps/plugins/codecvorbis.c b/apps/plugins/codecvorbis.c deleted file mode 100644 index 8e884714d0..0000000000 --- a/apps/plugins/codecvorbis.c +++ /dev/null @@ -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 - -#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),¤t_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;irequest_next_track()) - goto next_track; - - return PLUGIN_OK; -} - diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index f8ed798102..0914f109da 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES @@ -34,9 +34,8 @@ gray_verline.c #ifdef HAVE_LCD_CHARCELLS playergfx.c #endif +#if 0 #if CONFIG_HWCODEC == MASNONE /* software codec platforms */ xxx2wav.c -#ifdef IRIVER_H100 -codeclib.c #endif #endif diff --git a/tools/buildzip.pl b/tools/buildzip.pl index b5ff864058..3da8753541 100755 --- a/tools/buildzip.pl +++ b/tools/buildzip.pl @@ -48,7 +48,7 @@ sub buildzip { mkdir ".rockbox/langs", 0777; mkdir ".rockbox/rocks", 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/`; open VIEWERS, "$ROOT/apps/plugins/viewers.config" or