From 4231c2c83f2b5331e3e38b10a308ee3752315f9c Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sat, 26 Sep 2020 17:19:07 -0400 Subject: 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 --- lib/rbcodec/metadata/vtx.c | 150 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 lib/rbcodec/metadata/vtx.c (limited to 'lib/rbcodec/metadata/vtx.c') diff --git a/lib/rbcodec/metadata/vtx.c b/lib/rbcodec/metadata/vtx.c new file mode 100644 index 0000000000..eb06528b29 --- /dev/null +++ b/lib/rbcodec/metadata/vtx.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#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; +} -- cgit v1.2.3