commit asap codec. plays .sap files. At the moment it only plays the default song. So subSongs are ignored.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18121 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dominik Wenger 2008-07-26 15:16:10 +00:00
parent 4e4bf82fb7
commit 25bb37bb68
18 changed files with 461 additions and 10 deletions

View file

@ -141,6 +141,7 @@ metadata/vorbis.c
metadata/wave.c
metadata/wavpack.c
metadata/a52.c
metadata/asap.c
#endif
#ifdef HAVE_TAGCACHE
tagcache.c

View file

@ -124,7 +124,7 @@ struct codec_api ci = {
memmove,
memcmp,
memchr,
strcasestr,
#if defined(DEBUG) || defined(SIMULATOR)
debugf,
#endif

View file

@ -196,6 +196,7 @@ struct codec_api {
void* (*memmove)(void *out, const void *in, size_t n);
int (*memcmp)(const void *s1, const void *s2, size_t n);
void *(*memchr)(const void *s1, int c, size_t n);
char *(*strcasestr) (const char* phaystack, const char* pneedle);
#if defined(DEBUG) || defined(SIMULATOR)
void (*debugf)(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);

View file

@ -17,8 +17,8 @@ ifdef APPEXTRA
endif
ifdef SOFTWARECODECS
CODECLIBS = -lspc -lmad -la52 -lffmpegFLAC -lTremor -lwavpack -lmusepack -lalac -lfaad -lm4a -lspeex -ldemac -lwma
OUTPUT = libspc libmad liba52 libffmpegFLAC libwma libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac
CODECLIBS = -lspc -lmad -la52 -lffmpegFLAC -lTremor -lwavpack -lmusepack -lalac -lfaad -lm4a -lspeex -ldemac -lwma -lasap
OUTPUT = libspc libmad liba52 libffmpegFLAC libwma libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac libasap
endif
# we "borrow" the plugin LDS file
@ -40,7 +40,7 @@ DIRS = .
CODECDEPS = $(LINKCODEC) $(BUILDDIR)/libcodec.a
.PHONY: libspc libmad liba52 libffmpegFLAC libTremor libspeex libwavpack libmusepack libalac libfaad libm4a libdemac libwma
.PHONY: libspc libmad liba52 libffmpegFLAC libTremor libspeex libwavpack libmusepack libalac libfaad libm4a libdemac libwma libasap
all: $(LINKCODEC) $(ROCKS)
@ -70,6 +70,7 @@ $(OBJDIR)/aiff_enc.elf: $(OBJDIR)/aiff_enc.o $(OBJDIR)/codec_crt0.o
$(OBJDIR)/mp3_enc.elf: $(OBJDIR)/mp3_enc.o $(OBJDIR)/codec_crt0.o
$(OBJDIR)/wav_enc.elf: $(OBJDIR)/wav_enc.o $(OBJDIR)/codec_crt0.o
$(OBJDIR)/wavpack_enc.elf: $(OBJDIR)/wavpack_enc.o $(BUILDDIR)/libwavpack.a $(OBJDIR)/codec_crt0.o
$(OBJDIR)/asap.elf : $(OBJDIR)/asap.o $(BUILDDIR)/libasap.a $(OBJDIR)/codec_crt0.o
$(OBJDIR)/%.elf: $(OBJDIR)/codec_crt0.o
$(call PRINTS,LD $(@F))$(CC) $(CFLAGS) -o $@ $^ -L$(BUILDDIR) -lcodec -lgcc \
@ -218,6 +219,11 @@ libdemac:
$(SILENT)mkdir -p $(OBJDIR)/libdemac
$(call PRINTS,MAKE in libdemac)$(MAKE) -C demac/libdemac OBJDIR=$(OBJDIR)/libdemac OUTPUT=$(BUILDDIR)/libdemac.a
$(BUILDDIR)/libasap.a: libasap
libasap:
$(SILENT)mkdir -p $(OBJDIR)/asap
$(call PRINTS,MAKE in asap)$(MAKE) -C asap OBJDIR=$(OBJDIR)/asap OUTPUT=$(BUILDDIR)/libasap.a
clean:
$(call PRINTS,cleaning codecs)rm -fr $(OBJDIR)/spc $(BUILDDIR)/libspc.a $(OBJDIR)/libmad $(BUILDDIR)/libmad.a $(OBJDIR)/liba52 $(BUILDDIR)/liba52.a $(OBJDIR)/libffmpegFLAC $(BUILDDIR)/libffmpegFLAC.a $(OBJDIR)/Tremor $(BUILDDIR)/libTremor.a $(OBJDIR)/libspeex $(BUILDDIR)/libSpeex.a $(OBJDIR)/libwavpack $(BUILDDIR)/libwavpack.a $(OBJDIR)/libmusepack $(BUILDDIR)/libmusepack.a $(OBJDIR)/libalac $(BUILDDIR)/libalac.a $(OBJDIR)/libfaad $(BUILDDIR)/libfaad.a $(OBJDIR)/libm4a $(BUILDDIR)/libm4a.a $(OBJDIR)/libdemac $(BUILDDIR)/libdemac.a $(OBJDIR)/libwma $(BUILDDIR)/libwma.a
$(SILENT)$(MAKE) -C spc clean OBJDIR=$(OBJDIR)/spc

View file

@ -21,6 +21,7 @@ sid.c
adx.c
nsf.c
spc.c
asap.c
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
/* encoders */
aiff_enc.c

131
apps/codecs/asap.c Normal file
View file

@ -0,0 +1,131 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: asap.c 17847 2008-06-28 18:10:04Z domonoky $
*
* Copyright (C) 2008 Dominik Wenger
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "codeclib.h"
#include "asap/asap.h"
CODEC_HEADER
#define CHUNK_SIZE (1024*8)
static byte samples[CHUNK_SIZE]; /* The sample buffer */
static ASAP_State asap; /* asap codec state */
/* this is the codec entry point */
enum codec_status codec_main(void)
{
int n_bytes;
int song;
int duration;
char* module;
/* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
next_track:
if (codec_init()) {
DEBUGF("codec init failed\n");
return CODEC_ERROR;
}
while (!*ci->taginfo_ready && !ci->stop_codec)
ci->sleep(1);
codec_set_replaygain(ci->id3);
int bytes_done =0;
int filesize;
ci->seek_buffer(0);
module = ci->request_buffer(&filesize, ci->filesize);
if (!module || (size_t)filesize < (size_t)ci->filesize)
{
DEBUGF("loading error\n");
return CODEC_ERROR;
}
/*Init ASAP */
if (!ASAP_Load(&asap, ci->id3->path, module, filesize))
{
DEBUGF("%s: format not supported",ci->id3->path);
return CODEC_ERROR;
}
/* Make use of 44.1khz */
ci->configure(DSP_SET_FREQUENCY, 44100);
/* Sample depth is 16 bit little endian */
ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
/* Stereo or Mono output ? */
if(asap.module_info.channels ==1)
ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
else
ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
/* reset eleapsed */
ci->set_elapsed(0);
song = asap.module_info.default_song;
duration = asap.module_info.durations[song];
if (duration < 0)
duration = 180 * 1000;
ASAP_PlaySong(&asap, song, duration);
ASAP_MutePokeyChannels(&asap, 0);
/* The main decoder loop */
while (1) {
ci->yield();
if (ci->stop_codec || ci->new_track)
break;
if (ci->seek_time) {
/* New time is ready in ci->seek_time */
/* seek to pos */
ASAP_Seek(&asap,ci->seek_time);
/* update elapsed */
ci->set_elapsed(ci->seek_time);
/* update bytes_done */
bytes_done = ci->seek_time*44.1*2;
/* seek ready */
ci->seek_complete();
}
/* Generate a buffer full of Audio */
#ifdef ROCKBOX_LITTLE_ENDIAN
n_bytes = ASAP_Generate(&asap, samples, sizeof(samples), ASAP_FORMAT_S16_LE);
#else
n_bytes = ASAP_Generate(&asap, samples, sizeof(samples), ASAP_FORMAT_S16_BE);
#endif
ci->pcmbuf_insert(samples, NULL, n_bytes /2);
bytes_done += n_bytes;
ci->set_elapsed((bytes_done / 2) / 44.1);
if(n_bytes != sizeof(samples))
break;
}
if (ci->request_next_track())
goto next_track;
return CODEC_OK;
}

View file

@ -0,0 +1,25 @@
Library: asap-1.2.0
Imported: 2008-26-07 by Dominik Wenger
This directory contains a local version of asap (http://asap.sourceforge.net/) for decoding Atari 8bit .sap
audio streams.
LICENSING INFORMATION
Asap is available under the terms of the GPL v2 or later
license, which is both an open source and free software license.
The Licence is the same as the rest of Rockbox.
IMPORT DETAILS
The .[ch] files in apps/codec/asap are copied from ASAP.
Some #defines were added, so it uses the ci-> Pointer.
A small modification was needed in asap.h Line 120.
(changed the delta buffer to signed char)
Also players.h (contains binarys of players) was generated and copied
into Rockbox.

3
apps/codecs/asap/SOURCES Normal file
View file

@ -0,0 +1,3 @@
acpu.c
asap.c
apokeysnd.c

View file

@ -20,13 +20,14 @@
* along with ASAP; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "codeclib.h"
#if !defined(JAVA) && !defined(CSHARP)
#include <string.h>
#endif
#include "asap_internal.h"
#define memset ci->memset
#define ULTRASOUND_CYCLES 112
#define MUTE_FREQUENCY 1

View file

@ -20,7 +20,7 @@
* along with ASAP; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "codeclib.h"
#if !defined(JAVA) && !defined(CSHARP)
#include <string.h>
#endif
@ -30,6 +30,14 @@
#include "players.h"
#endif
#define memcpy ci->memcpy
#define memcmp ci->memcmp
#define memset ci->memset
#define strcpy ci->strcpy
#define strcmp ci->strcmp
#define strstr ci->strcasestr
#define CMR_BASS_TABLE_OFFSET 0x70f
CONST_LOOKUP(byte, cmr_bass_table) = {
@ -1012,7 +1020,7 @@ FILE_FUNC abool parse_sap_header(ASAP_ModuleInfo PTR module_info,
i = 0;
while (module[module_index] != 0x0d) {
line[i++] = (char) module[module_index++];
if (module_index >= module_len || i >= sizeof(line) - 1)
if (module_index >= module_len || (unsigned)i >= sizeof(line) - 1)
return FALSE;
}
if (++module_index >= module_len || module[module_index++] != 0x0a)
@ -1719,6 +1727,7 @@ int ASAP_SetModuleInfo(const ASAP_ModuleInfo *module_info, const byte ARRAY modu
const char *ASAP_CanConvert(const char *filename, const ASAP_ModuleInfo *module_info,
const byte ARRAY module, int module_len)
{
(void)filename;
switch (module_info->type) {
case 'B':
if (module_info->init == 0x4f3 || module_info->init == 0xf4f3 || module_info->init == 0x4ef)
@ -1755,6 +1764,7 @@ const char *ASAP_CanConvert(const char *filename, const ASAP_ModuleInfo *module_
int ASAP_Convert(const char *filename, const ASAP_ModuleInfo *module_info,
const byte ARRAY module, int module_len, byte ARRAY out_module)
{
(void) filename;
int out_len;
byte *dest;
int addr;

View file

@ -117,7 +117,7 @@ typedef struct {
int delta3;
int delta4;
int skctl;
char delta_buffer[888];
signed char delta_buffer[888];
} PokeyState;
/* Player state.

View file

@ -81,6 +81,7 @@ static const struct filetype inbuilt_filetypes[] = {
{ "spc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "ape", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "mac", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "sap" ,FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
#endif
{ "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
{ "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },

View file

@ -250,6 +250,16 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
break;
case AFMT_SAP:
if (!get_asap_metadata(fd, id3))
{
DEBUGF("get_sap_metadata error\n");
return false;
}
id3->filesize = filesize(fd);
id3->genre_string = id3_get_num_genre(36);
break;
#endif /* CONFIG_CODEC == SWCODEC */
default:

256
apps/metadata/asap.c Normal file
View file

@ -0,0 +1,256 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: asap.c 17847 2008-06-28 18:10:04Z domonoky $
*
* Copyright (C) 2008 Dominik Wenger
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <inttypes.h>
#include "system.h"
#include "id3.h"
#include "metadata_common.h"
#include "metadata_parsers.h"
#include "rbunicode.h"
#include "debug.h"
#define MAX_SONGS 32
struct module_info
{
char name[255];
char author[255];
char date[255];
int numSongs;
int defSong;
int numChannels;
int durations[32];
int loops[32];
};
static bool parse_dec(int *retval, const char *p, int minval, int maxval)
{
int r = 0;
do {
char c = *p;
if (c >= '0' && c <= '9')
r = 10 * r + c - '0';
else
return false;
if (r > maxval)
return false;
} while (*++p != '\0');
if (r < minval)
return false;
*retval = r;
return true;
}
static bool parse_text(char *retval, const char *p)
{
int i;
if (*p != '"')
return false;
p++;
if (p[0] == '<' && p[1] == '?' && p[2] == '>' && p[3] == '"')
return true;
i = 0;
while (*p != '"') {
if (i >= 127)
return false;
if (*p == '\0')
return false;
retval[i++] = *p++;
}
retval[i] = '\0';
return true;
}
static int ASAP_ParseDuration(const char *s)
{
int r;
if (*s < '0' || *s > '9')
return -1;
r = *s++ - '0';
if (*s >= '0' && *s <= '9')
r = 10 * r + *s++ - '0';
if (*s == ':') {
s++;
if (*s < '0' || *s > '5')
return -1;
r = 60 * r + (*s++ - '0') * 10;
if (*s < '0' || *s > '9')
return -1;
r += *s++ - '0';
}
r *= 1000;
if (*s != '.')
return r;
s++;
if (*s < '0' || *s > '9')
return r;
r += 100 * (*s++ - '0');
if (*s < '0' || *s > '9')
return r;
r += 10 * (*s++ - '0');
if (*s < '0' || *s > '9')
return r;
r += *s - '0';
return r;
}
static bool parse_sap_header(int fd,struct module_info* info,int file_len)
{
int module_index = 0;
int sap_signature = -1;
int duration_index = 0;
unsigned char cur_char = 0;
int i;
/* set defaults */
info->numSongs=1;
info->defSong=0;
info->numChannels=1;
for (i = 0; i < MAX_SONGS; i++) {
info->durations[i] = -1;
info->loops[i] = 0;
}
/* parse file */
while (1)
{
char line[256];
char *p;
if (module_index + 8 >= file_len)
return false;
/* read a char */
read(fd,&cur_char,1);
/* end of header */
if (cur_char == 0xff)
break;
i = 0;
while (cur_char != 0x0d)
{
line[i++] = cur_char;
module_index++;
if (module_index >= file_len || (unsigned)i >= sizeof(line) - 1)
return false;
/* read a char */
read(fd,&cur_char,1);
}
if (++module_index >= file_len )
return false;
/* read a char */
read(fd,&cur_char,1);
if ( cur_char != 0x0a)
return false;
line[i] = '\0';
for (p = line; *p != '\0'; p++) {
if (*p == ' ') {
*p++ = '\0';
break;
}
}
/* parse tags */
if(strcmp(line, "SAP") == 0)
sap_signature = 1;
if (sap_signature == -1)
return false;
if (strcmp(line,"AUTHOR") == 0)
{
if (parse_text(info->author, p) == false )
return false;
}
else if(strcmp(line,"NAME")==0)
{
if (parse_text(info->name, p) == false)
return false;
}
else if(strcmp(line,"DATE")==0)
{
if (parse_text(info->date, p) == false)
return false;
}
else if (strcmp(line,"SONGS")==0)
{
if (parse_dec(&info->numSongs, p,1,MAX_SONGS) == false )
return false;
}
else if (strcmp(line,"DEFSONG")==0)
{
if (parse_dec(&info->defSong, p,0,MAX_SONGS) == false)
return false;
}
else if (strcmp(line,"STEREO")==0)
{
info->numChannels = 2;
}
else if (strcmp(line,"TIME") == 0)
{
int duration = ASAP_ParseDuration(p);
if (duration < 0 || duration_index >= MAX_SONGS)
return false;
info->durations[duration_index] = duration;
if (strstr(p, "LOOP") != NULL)
info->loops[duration_index] = 1;
duration_index++;
}
}
lseek(fd,0,SEEK_SET);
return true;
}
bool get_asap_metadata(int fd, struct mp3entry* id3)
{
char *buf = id3->id3v2buf;
int filelength = filesize(fd);
struct module_info *info;
info = (struct module_info *) buf;
if(parse_sap_header(fd,info,filelength) == false)
{
DEBUGF("parse sap header failed.\n");
return false;
}
id3->title = info->name;
id3->artist = info->author;
id3->year_string = info->date;
int length = info->durations[info->defSong];
if (length < 0)
length = 180 * 1000;
id3->length = length;
id3->bitrate = 706;
id3->frequency = 44100;
id3->vbr = false;
id3->filesize = filelength;
return true;
}

View file

@ -34,3 +34,4 @@ bool get_wave_metadata(int fd, struct mp3entry* id3);
bool get_wavpack_metadata(int fd, struct mp3entry* id3);
bool get_a52_metadata(int fd, struct mp3entry* id3);
bool get_asf_metadata(int fd, struct mp3entry* id3);
bool get_asap_metadata(int fd, struct mp3entry* id3);

View file

@ -463,7 +463,7 @@ static void init_ci(void)
ci.memmove = rb->memmove;
ci.memcmp = rb->memcmp;
ci.memchr = rb->memchr;
ci.strcasestr = rb->strcasestr;
#if defined(DEBUG) || defined(SIMULATOR)
ci.debugf = rb->debugf;
#endif

View file

@ -60,6 +60,7 @@ enum
AFMT_APE, /* Monkey's Audio (APE) */
AFMT_WMA, /* WMAV1/V2 in ASF */
AFMT_MOD, /* Amiga MOD File Format */
AFMT_SAP, /* Amiga 8Bit SAP Format */
#endif
/* add new formats at any index above this line to have a sensible order -

View file

@ -117,6 +117,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
/* Amiga MOD File */
[AFMT_MOD] =
AFMT_ENTRY("MOD", "mod", NULL, "mod\0" ),
/* Amiga SAP File */
[AFMT_SAP] =
AFMT_ENTRY("SAP", "asap", NULL, "sap\0" ),
#endif
};