forked from len0rd/rockbox
codecs: Add support for the 'VTX' ZX Spectrum chiptunes format.
This codec requires floating point. Original author: Peter Sovietov Ported to Rockbox: Roman Skylarov Further integration and bugfixes: Solomon Peachy Change-Id: I781ecd3592dfcdbbc694063334350342534f1d6c
This commit is contained in:
parent
278522f811
commit
4231c2c83f
29 changed files with 1642 additions and 41 deletions
|
@ -43,7 +43,7 @@ static bool get_shn_metadata(int fd, struct mp3entry *id3)
|
|||
}
|
||||
|
||||
static bool get_other_asap_metadata(int fd, struct mp3entry *id3)
|
||||
{
|
||||
{
|
||||
id3->bitrate = 706;
|
||||
id3->frequency = 44100;
|
||||
id3->vbr = false;
|
||||
|
@ -85,7 +85,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
|||
/* Musepack SV7 */
|
||||
[AFMT_MPC_SV7] =
|
||||
AFMT_ENTRY("MPCv7", "mpc", NULL, get_musepack_metadata,"mpc\0"),
|
||||
/* A/52 (aka AC3) audio */
|
||||
/* A/52 (aka AC3) audio */
|
||||
[AFMT_A52] =
|
||||
AFMT_ENTRY("AC3", "a52", NULL, get_a52_metadata, "a52\0ac3\0"),
|
||||
/* WavPack */
|
||||
|
@ -109,7 +109,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
|||
/* NESM (NES Sound Format) */
|
||||
[AFMT_NSF] =
|
||||
AFMT_ENTRY("NSF", "nsf", NULL, get_nsf_metadata, "nsf\0nsfe\0"),
|
||||
/* Speex File Format */
|
||||
/* Speex File Format */
|
||||
[AFMT_SPEEX] =
|
||||
AFMT_ENTRY("Speex", "speex",NULL, get_ogg_metadata, "spx\0"),
|
||||
/* SPC700 Save State */
|
||||
|
@ -162,12 +162,12 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
|||
AFMT_ENTRY("DLT", "asap", NULL, get_other_asap_metadata,"dlt\0"),
|
||||
/* Atari MPT File */
|
||||
[AFMT_MPT] =
|
||||
AFMT_ENTRY("MPT", "asap", NULL, get_other_asap_metadata,"mpt\0"),
|
||||
AFMT_ENTRY("MPT", "asap", NULL, get_other_asap_metadata,"mpt\0"),
|
||||
/* Atari MPD File */
|
||||
[AFMT_MPD] =
|
||||
AFMT_ENTRY("MPD", "asap", NULL, get_other_asap_metadata,"mpd\0"),
|
||||
/* Atari RMT File */
|
||||
[AFMT_RMT] =
|
||||
[AFMT_RMT] =
|
||||
AFMT_ENTRY("RMT", "asap", NULL, get_other_asap_metadata,"rmt\0"),
|
||||
/* Atari TMC File */
|
||||
[AFMT_TMC] =
|
||||
|
@ -177,10 +177,10 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
|||
AFMT_ENTRY("TM8", "asap", NULL, get_other_asap_metadata,"tm8\0"),
|
||||
/* Atari TM2 File */
|
||||
[AFMT_TM2] =
|
||||
AFMT_ENTRY("TM2", "asap", NULL, get_other_asap_metadata,"tm2\0"),
|
||||
AFMT_ENTRY("TM2", "asap", NULL, get_other_asap_metadata,"tm2\0"),
|
||||
/* Atrac3 in Sony OMA Container */
|
||||
[AFMT_OMA_ATRAC3] =
|
||||
AFMT_ENTRY("ATRAC3","atrac3_oma",NULL, get_oma_metadata, "oma\0aa3\0"),
|
||||
AFMT_ENTRY("ATRAC3","atrac3_oma",NULL, get_oma_metadata, "oma\0aa3\0"),
|
||||
/* SMAF (Synthetic music Mobile Application Format) */
|
||||
[AFMT_SMAF] =
|
||||
AFMT_ENTRY("SMAF", "smaf", NULL, get_smaf_metadata, "mmf\0"),
|
||||
|
@ -194,7 +194,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
|||
[AFMT_WAVE64] =
|
||||
AFMT_ENTRY("WAVE64","wav64",NULL, get_wave64_metadata,"w64\0"),
|
||||
/* True Audio */
|
||||
[AFMT_TTA] =
|
||||
[AFMT_TTA] =
|
||||
AFMT_ENTRY("TTA", "tta", NULL, get_tta_metadata, "tta\0"),
|
||||
/* WMA Voice in ASF */
|
||||
[AFMT_WMAVOICE] =
|
||||
|
@ -206,8 +206,13 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
|||
[AFMT_MP4_AAC_HE] =
|
||||
AFMT_ENTRY("AAC-HE","aac", NULL, get_mp4_metadata, "mp4\0"),
|
||||
/* AY (ZX Spectrum, Amstrad CPC Sound Format) */
|
||||
[AFMT_AY] =
|
||||
[AFMT_AY] =
|
||||
AFMT_ENTRY("AY", "ay", NULL, get_ay_metadata, "ay\0"),
|
||||
/* AY (ZX Spectrum Sound Format) */
|
||||
#ifdef HAVE_FPU
|
||||
[AFMT_VTX] =
|
||||
AFMT_ENTRY("VTX", "vtx", NULL, get_vtx_metadata, "vtx\0"),
|
||||
#endif
|
||||
/* GBS (Game Boy Sound Format) */
|
||||
[AFMT_GBS] =
|
||||
AFMT_ENTRY("GBS", "gbs", NULL, get_gbs_metadata, "gbs\0"),
|
||||
|
@ -313,6 +318,9 @@ bool rbcodec_format_is_atomic(int afmt)
|
|||
case AFMT_MOD:
|
||||
case AFMT_SAP:
|
||||
case AFMT_AY:
|
||||
#ifdef HAVE_FPU
|
||||
case AFMT_VTX:
|
||||
#endif
|
||||
case AFMT_GBS:
|
||||
case AFMT_HES:
|
||||
case AFMT_SGC:
|
||||
|
@ -352,17 +360,17 @@ unsigned int probe_file_format(const char *filename)
|
|||
{
|
||||
char *suffix;
|
||||
unsigned int i;
|
||||
|
||||
|
||||
suffix = strrchr(filename, '.');
|
||||
|
||||
if (suffix == NULL)
|
||||
{
|
||||
return AFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
/* skip '.' */
|
||||
suffix++;
|
||||
|
||||
|
||||
for (i = 1; i < AFMT_NUM_CODECS; i++)
|
||||
{
|
||||
/* search extension list for type */
|
||||
|
@ -379,7 +387,7 @@ unsigned int probe_file_format(const char *filename)
|
|||
}
|
||||
while (*ext != '\0');
|
||||
}
|
||||
|
||||
|
||||
return AFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
@ -418,7 +426,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
|
|||
close(logfd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Clear the mp3entry to avoid having bogus pointers appear */
|
||||
wipe_mp3entry(id3);
|
||||
|
||||
|
@ -454,7 +462,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
|
|||
void strip_tags(int handle_id)
|
||||
{
|
||||
static const unsigned char tag[] = "TAG";
|
||||
static const unsigned char apetag[] = "APETAGEX";
|
||||
static const unsigned char apetag[] = "APETAGEX";
|
||||
size_t len, version;
|
||||
void *tail;
|
||||
|
||||
|
@ -502,7 +510,7 @@ void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig)
|
|||
MOVE_ENTRY(entry->artist)
|
||||
MOVE_ENTRY(entry->album)
|
||||
|
||||
if (entry->genre_string > (char*)orig &&
|
||||
if (entry->genre_string > (char*)orig &&
|
||||
entry->genre_string < (char*)orig + sizeof(struct mp3entry))
|
||||
/* Don't adjust that if it points to an entry of the "genres" array */
|
||||
entry->genre_string += offset;
|
||||
|
|
|
@ -83,6 +83,9 @@ enum
|
|||
AFMT_MPC_SV8, /* Musepack SV8 */
|
||||
AFMT_MP4_AAC_HE, /* Advanced Audio Coding (AAC-HE) in M4A container */
|
||||
AFMT_AY, /* AY (ZX Spectrum, Amstrad CPC Sound Format) */
|
||||
#ifdef HAVE_FPU
|
||||
AFMT_VTX, /* VTX (ZX Spectrum Sound Format) */
|
||||
#endif
|
||||
AFMT_GBS, /* GBS (Game Boy Sound Format) */
|
||||
AFMT_HES, /* HES (Hudson Entertainment System Sound Format) */
|
||||
AFMT_SGC, /* SGC (Sega Master System, Game Gear, Coleco Vision Sound Format) */
|
||||
|
@ -140,7 +143,7 @@ enum rec_format_indexes
|
|||
REC_FORMAT_CFG_NUM_BITS = 2
|
||||
};
|
||||
|
||||
#define REC_FORMAT_CFG_VAL_LIST "wave,aiff,wvpk,mpa3"
|
||||
#define REC_FORMAT_CFG_VAL_LIST "wave,aiff,wvpk,mpa3"
|
||||
|
||||
/* get REC_FORMAT_* corresponding AFMT_* */
|
||||
extern const int rec_format_afmt[REC_NUM_FORMATS];
|
||||
|
@ -232,7 +235,7 @@ struct mp3entry {
|
|||
char* comment;
|
||||
char* albumartist;
|
||||
char* grouping;
|
||||
int discnum;
|
||||
int discnum;
|
||||
int tracknum;
|
||||
int layer;
|
||||
int year;
|
||||
|
@ -283,7 +286,7 @@ struct mp3entry {
|
|||
|
||||
#ifdef HAVE_TAGCACHE
|
||||
unsigned char autoresumable; /* caches result of autoresumable() */
|
||||
|
||||
|
||||
/* runtime database fields */
|
||||
long tagcache_idx; /* 0=invalid, otherwise idx+1 */
|
||||
int rating;
|
||||
|
@ -292,7 +295,7 @@ struct mp3entry {
|
|||
long lastplayed;
|
||||
long playtime;
|
||||
#endif
|
||||
|
||||
|
||||
/* replaygain support */
|
||||
long track_level; /* holds the level in dB * (1<<FP_BITS) */
|
||||
long album_level;
|
||||
|
@ -329,5 +332,3 @@ bool rbcodec_format_is_atomic(int afmt);
|
|||
bool format_buffers_with_offset(int afmt);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,9 @@ bool get_vox_metadata(int fd, struct mp3entry* id3);
|
|||
bool get_wave64_metadata(int fd, struct mp3entry* id3);
|
||||
bool get_tta_metadata(int fd, struct mp3entry* id3);
|
||||
bool get_ay_metadata(int fd, struct mp3entry* id3);
|
||||
#ifdef HAVE_FPU
|
||||
bool get_vtx_metadata(int fd, struct mp3entry* id3);
|
||||
#endif
|
||||
bool get_gbs_metadata(int fd, struct mp3entry* id3);
|
||||
bool get_hes_metadata(int fd, struct mp3entry* id3);
|
||||
bool get_sgc_metadata(int fd, struct mp3entry* id3);
|
||||
|
|
150
lib/rbcodec/metadata/vtx.c
Normal file
150
lib/rbcodec/metadata/vtx.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include "platform.h"
|
||||
|
||||
#include "metadata.h"
|
||||
#include "metadata_common.h"
|
||||
#include "metadata_parsers.h"
|
||||
#include "rbunicode.h"
|
||||
#include "string-extra.h"
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
|
||||
typedef enum {
|
||||
VTX_CHIP_AY = 0, /* emulate AY */
|
||||
VTX_CHIP_YM /* emulate YM */
|
||||
} vtx_chiptype_t;
|
||||
|
||||
typedef enum {
|
||||
VTX_LAYOUT_MONO = 0,
|
||||
VTX_LAYOUT_ABC,
|
||||
VTX_LAYOUT_ACB,
|
||||
VTX_LAYOUT_BAC,
|
||||
VTX_LAYOUT_BCA,
|
||||
VTX_LAYOUT_CAB,
|
||||
VTX_LAYOUT_CBA,
|
||||
VTX_LAYOUT_CUSTOM
|
||||
} vtx_layout_t;
|
||||
|
||||
typedef struct {
|
||||
vtx_chiptype_t chiptype; /* Type of sound chip */
|
||||
vtx_layout_t layout; /* stereo layout */
|
||||
uint loop; /* song loop */
|
||||
uint chipfreq; /* AY chip freq (1773400 for ZX) */
|
||||
uint playerfreq; /* 50 Hz for ZX, 60 Hz for yamaha */
|
||||
uint year; /* year song composed */
|
||||
char *title; /* song title */
|
||||
char *author; /* song author */
|
||||
char *from; /* song from */
|
||||
char *tracker; /* tracker */
|
||||
char *comment; /* comment */
|
||||
uint regdata_size; /* size of unpacked data */
|
||||
uint frames; /* number of AY data frames */
|
||||
} vtx_info_t;
|
||||
|
||||
#define VTX_STRING_MAX 254
|
||||
|
||||
static uint Reader_ReadByte(int fd) {
|
||||
unsigned char c;
|
||||
read(fd, &c, sizeof(c));
|
||||
return c;
|
||||
}
|
||||
|
||||
static uint Reader_ReadWord(int fd) {
|
||||
unsigned short s;
|
||||
read(fd, &s, sizeof(s));
|
||||
return letoh16(s);
|
||||
}
|
||||
|
||||
static uint Reader_ReadDWord(int fd) {
|
||||
unsigned int i;
|
||||
read(fd, &i, sizeof(i));
|
||||
return letoh32(i);
|
||||
}
|
||||
|
||||
static char* Reader_ReadString(int fd, char *str) {
|
||||
int i = 0;
|
||||
char c = 1;
|
||||
char *p = str;
|
||||
|
||||
if (str)
|
||||
*str = 0;
|
||||
|
||||
while (i < VTX_STRING_MAX && c) {
|
||||
read(fd, &c, sizeof(c));
|
||||
if (str)
|
||||
*str++ = c;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (str)
|
||||
*str = 0;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* vtx info */
|
||||
|
||||
bool get_vtx_metadata(int fd, struct mp3entry* id3)
|
||||
{
|
||||
vtx_info_t info;
|
||||
char *p = id3->id3v2buf;
|
||||
char buf[VTX_STRING_MAX+1];
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET) < 0)
|
||||
goto exit_bad;
|
||||
|
||||
if (filesize(fd) < 20)
|
||||
goto exit_bad;
|
||||
|
||||
uint hdr = Reader_ReadWord(fd);
|
||||
|
||||
if ((hdr != 0x7961) && (hdr != 0x6d79))
|
||||
goto exit_bad;
|
||||
|
||||
info.layout = (vtx_layout_t)Reader_ReadByte(fd);
|
||||
info.loop = Reader_ReadWord(fd);
|
||||
info.chipfreq = Reader_ReadDWord(fd);
|
||||
info.playerfreq = Reader_ReadByte(fd);
|
||||
info.year = Reader_ReadWord(fd);
|
||||
info.regdata_size = Reader_ReadDWord(fd);
|
||||
info.frames = info.regdata_size / 14;
|
||||
info.title = Reader_ReadString(fd, buf);
|
||||
if (buf[0]) {
|
||||
/* Title */
|
||||
id3->title = p;
|
||||
p += strlcpy(p, info.title, VTX_STRING_MAX) + 1;
|
||||
}
|
||||
info.author = Reader_ReadString(fd, buf);
|
||||
if (buf[0]) {
|
||||
/* Artist */
|
||||
id3->artist = p;
|
||||
p += strlcpy(p, info.author, VTX_STRING_MAX) + 1;
|
||||
}
|
||||
info.from = Reader_ReadString(fd, NULL);
|
||||
info.tracker = Reader_ReadString(fd, NULL);
|
||||
info.comment = Reader_ReadString(fd, buf);
|
||||
if (buf[0]) {
|
||||
/* Comment */
|
||||
id3->comment = p;
|
||||
p += strlcpy(p, info.comment, VTX_STRING_MAX) + 1;
|
||||
}
|
||||
|
||||
id3->vbr = false;
|
||||
id3->bitrate = 706;
|
||||
id3->frequency = 44100; // XXX allow this to be configured?
|
||||
|
||||
id3->filesize = filesize(fd);
|
||||
id3->length = info.frames * 1000 / info.playerfreq;
|
||||
|
||||
return true;
|
||||
|
||||
exit_bad:
|
||||
return false;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue