mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -04:00
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
|
@ -104,6 +104,7 @@ static const struct filetype inbuilt_filetypes[] = {
|
||||||
{ "w64", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
{ "w64", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
{ "tta", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
{ "tta", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
{ "ay", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
{ "ay", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
|
{ "vtx", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
{ "gbs", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
{ "gbs", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
{ "hes", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
{ "hes", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
{ "sgc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
{ "sgc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
|
|
|
@ -39,11 +39,6 @@ SDLFLAGS = -I$(SDL_SRCDIR)/include $(filter-out -O%,$(PLUGINFLAGS)) \
|
||||||
#-ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations \
|
#-ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations \
|
||||||
#-D_GNU_SOURCE=1 -D_REENTRANT -DSDL -DELF
|
#-D_GNU_SOURCE=1 -D_REENTRANT -DSDL -DELF
|
||||||
|
|
||||||
# use FPU on ARMv6
|
|
||||||
ifeq ($(ARCH_VERSION),6)
|
|
||||||
SDLFLAGS += -mfloat-abi=softfp
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef APP_TYPE
|
ifndef APP_TYPE
|
||||||
### no target has a big enough plugin buffer
|
### no target has a big enough plugin buffer
|
||||||
ROCKS += $(SDL_OBJDIR)/duke3d.ovl
|
ROCKS += $(SDL_OBJDIR)/duke3d.ovl
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#define CONFIG_PLATFORM (PLATFORM_HOSTED)
|
#define CONFIG_PLATFORM (PLATFORM_HOSTED)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
#define HAVE_LCD_COLOR
|
#define HAVE_LCD_COLOR
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
/* We don't run on hardware directly */
|
/* We don't run on hardware directly */
|
||||||
#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
|
#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
/* For Rolo and boot loader */
|
/* For Rolo and boot loader */
|
||||||
#define MODEL_NUMBER 100
|
#define MODEL_NUMBER 100
|
||||||
|
@ -12,9 +13,6 @@
|
||||||
|
|
||||||
#define USB_NONE
|
#define USB_NONE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
#define HAVE_LCD_COLOR
|
#define HAVE_LCD_COLOR
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,8 @@
|
||||||
|
|
||||||
#define CONFIG_CPU IMX31L
|
#define CONFIG_CPU IMX31L
|
||||||
|
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
/* Define this if you want to use imx31l's i2c interface */
|
/* Define this if you want to use imx31l's i2c interface */
|
||||||
#define CONFIG_I2C I2C_IMX31L
|
#define CONFIG_I2C I2C_IMX31L
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
/* We don't run on hardware directly */
|
/* We don't run on hardware directly */
|
||||||
#define CONFIG_PLATFORM PLATFORM_HOSTED
|
#define CONFIG_PLATFORM PLATFORM_HOSTED
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
/* For Rolo and boot loader */
|
/* For Rolo and boot loader */
|
||||||
#define MODEL_NUMBER 94
|
#define MODEL_NUMBER 94
|
||||||
|
@ -33,9 +34,6 @@
|
||||||
|
|
||||||
#define USB_NONE
|
#define USB_NONE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
#define HAVE_LCD_COLOR
|
#define HAVE_LCD_COLOR
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
/* We don't run on hardware directly */
|
/* We don't run on hardware directly */
|
||||||
#define CONFIG_PLATFORM PLATFORM_HOSTED
|
#define CONFIG_PLATFORM PLATFORM_HOSTED
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
/* For Rolo and boot loader */
|
/* For Rolo and boot loader */
|
||||||
#define MODEL_NUMBER 95
|
#define MODEL_NUMBER 95
|
||||||
|
@ -33,9 +34,6 @@
|
||||||
|
|
||||||
#define USB_NONE
|
#define USB_NONE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
#define HAVE_LCD_COLOR
|
#define HAVE_LCD_COLOR
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#define USB_NONE
|
#define USB_NONE
|
||||||
|
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
|
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
|
|
||||||
#define USB_NONE
|
#define USB_NONE
|
||||||
|
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
|
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
#define HAVE_LCD_COLOR
|
#define HAVE_LCD_COLOR
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
/* We don't run on hardware directly */
|
/* We don't run on hardware directly */
|
||||||
#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_SDL)
|
#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_SDL)
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
/* For Rolo and boot loader */
|
/* For Rolo and boot loader */
|
||||||
#define MODEL_NUMBER 100
|
#define MODEL_NUMBER 100
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#define CONFIG_PLATFORM (PLATFORM_HOSTED)
|
#define CONFIG_PLATFORM (PLATFORM_HOSTED)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
#define HAVE_LCD_COLOR
|
#define HAVE_LCD_COLOR
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#define CONFIG_PLATFORM (PLATFORM_HOSTED)
|
#define CONFIG_PLATFORM (PLATFORM_HOSTED)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_FPU
|
||||||
|
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
#define HAVE_LCD_COLOR
|
#define HAVE_LCD_COLOR
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,9 @@ metadata/asap.c
|
||||||
metadata/asf.c
|
metadata/asf.c
|
||||||
metadata/au.c
|
metadata/au.c
|
||||||
metadata/ay.c
|
metadata/ay.c
|
||||||
|
#ifdef HAVE_FPU
|
||||||
|
metadata/vtx.c
|
||||||
|
#endif
|
||||||
metadata/flac.c
|
metadata/flac.c
|
||||||
metadata/gbs.c
|
metadata/gbs.c
|
||||||
metadata/hes.c
|
metadata/hes.c
|
||||||
|
|
|
@ -34,6 +34,9 @@ wav64.c
|
||||||
tta.c
|
tta.c
|
||||||
wmapro.c
|
wmapro.c
|
||||||
ay.c
|
ay.c
|
||||||
|
#ifdef HAVE_FPU
|
||||||
|
vtx.c
|
||||||
|
#endif
|
||||||
gbs.c
|
gbs.c
|
||||||
hes.c
|
hes.c
|
||||||
nsf.c
|
nsf.c
|
||||||
|
|
|
@ -39,6 +39,7 @@ include $(RBCODECLIB_DIR)/codecs/liba52/liba52.make
|
||||||
include $(RBCODECLIB_DIR)/codecs/libalac/libalac.make
|
include $(RBCODECLIB_DIR)/codecs/libalac/libalac.make
|
||||||
include $(RBCODECLIB_DIR)/codecs/libasap/libasap.make
|
include $(RBCODECLIB_DIR)/codecs/libasap/libasap.make
|
||||||
include $(RBCODECLIB_DIR)/codecs/libasf/libasf.make
|
include $(RBCODECLIB_DIR)/codecs/libasf/libasf.make
|
||||||
|
include $(RBCODECLIB_DIR)/codecs/libayumi/libayumi.make
|
||||||
include $(RBCODECLIB_DIR)/codecs/libfaad/libfaad.make
|
include $(RBCODECLIB_DIR)/codecs/libfaad/libfaad.make
|
||||||
include $(RBCODECLIB_DIR)/codecs/libffmpegFLAC/libffmpegFLAC.make
|
include $(RBCODECLIB_DIR)/codecs/libffmpegFLAC/libffmpegFLAC.make
|
||||||
include $(RBCODECLIB_DIR)/codecs/libm4a/libm4a.make
|
include $(RBCODECLIB_DIR)/codecs/libm4a/libm4a.make
|
||||||
|
@ -74,6 +75,7 @@ $(ASAPLIB) : CODECFLAGS += -O1
|
||||||
$(ASFLIB) : CODECFLAGS += -O2
|
$(ASFLIB) : CODECFLAGS += -O2
|
||||||
$(ATRACLIB) : CODECFLAGS += -O1
|
$(ATRACLIB) : CODECFLAGS += -O1
|
||||||
$(AYLIB) : CODECFLAGS += -O2
|
$(AYLIB) : CODECFLAGS += -O2
|
||||||
|
$(AYUMILIB) : CODECFLAGS += -O3
|
||||||
$(COOKLIB): CODECFLAGS += -O1
|
$(COOKLIB): CODECFLAGS += -O1
|
||||||
$(DEMACLIB) : CODECFLAGS += -O3
|
$(DEMACLIB) : CODECFLAGS += -O3
|
||||||
$(FAADLIB) : CODECFLAGS += -O2
|
$(FAADLIB) : CODECFLAGS += -O2
|
||||||
|
@ -181,6 +183,7 @@ $(CODECDIR)/vox.codec : $(CODECDIR)/libpcm.a
|
||||||
$(CODECDIR)/wav64.codec : $(CODECDIR)/libpcm.a
|
$(CODECDIR)/wav64.codec : $(CODECDIR)/libpcm.a
|
||||||
$(CODECDIR)/tta.codec : $(CODECDIR)/libtta.a
|
$(CODECDIR)/tta.codec : $(CODECDIR)/libtta.a
|
||||||
$(CODECDIR)/ay.codec : $(CODECDIR)/libay.a
|
$(CODECDIR)/ay.codec : $(CODECDIR)/libay.a
|
||||||
|
$(CODECDIR)/vtx.codec : $(CODECDIR)/libayumi.a
|
||||||
$(CODECDIR)/gbs.codec : $(CODECDIR)/libgbs.a
|
$(CODECDIR)/gbs.codec : $(CODECDIR)/libgbs.a
|
||||||
$(CODECDIR)/hes.codec : $(CODECDIR)/libhes.a
|
$(CODECDIR)/hes.codec : $(CODECDIR)/libhes.a
|
||||||
$(CODECDIR)/nsf.codec : $(CODECDIR)/libnsf.a $(CODECDIR)/libemu2413.a
|
$(CODECDIR)/nsf.codec : $(CODECDIR)/libnsf.a $(CODECDIR)/libemu2413.a
|
||||||
|
|
5
lib/rbcodec/codecs/libayumi/SOURCES
Normal file
5
lib/rbcodec/codecs/libayumi/SOURCES
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#ifdef HAVE_FPU
|
||||||
|
ayumi_render.c
|
||||||
|
ayumi.c
|
||||||
|
lzh.c
|
||||||
|
#endif
|
361
lib/rbcodec/codecs/libayumi/ayumi.c
Normal file
361
lib/rbcodec/codecs/libayumi/ayumi.c
Normal file
|
@ -0,0 +1,361 @@
|
||||||
|
/* Author: Peter Sovietov */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "ayumi.h"
|
||||||
|
|
||||||
|
static const double AY_dac_table[] = {
|
||||||
|
0.0, 0.0,
|
||||||
|
0.00999465934234, 0.00999465934234,
|
||||||
|
0.0144502937362, 0.0144502937362,
|
||||||
|
0.0210574502174, 0.0210574502174,
|
||||||
|
0.0307011520562, 0.0307011520562,
|
||||||
|
0.0455481803616, 0.0455481803616,
|
||||||
|
0.0644998855573, 0.0644998855573,
|
||||||
|
0.107362478065, 0.107362478065,
|
||||||
|
0.126588845655, 0.126588845655,
|
||||||
|
0.20498970016, 0.20498970016,
|
||||||
|
0.292210269322, 0.292210269322,
|
||||||
|
0.372838941024, 0.372838941024,
|
||||||
|
0.492530708782, 0.492530708782,
|
||||||
|
0.635324635691, 0.635324635691,
|
||||||
|
0.805584802014, 0.805584802014,
|
||||||
|
1.0, 1.0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const double YM_dac_table[] = {
|
||||||
|
0.0, 0.0,
|
||||||
|
0.00465400167849, 0.00772106507973,
|
||||||
|
0.0109559777218, 0.0139620050355,
|
||||||
|
0.0169985503929, 0.0200198367285,
|
||||||
|
0.024368657969, 0.029694056611,
|
||||||
|
0.0350652323186, 0.0403906309606,
|
||||||
|
0.0485389486534, 0.0583352407111,
|
||||||
|
0.0680552376593, 0.0777752346075,
|
||||||
|
0.0925154497597, 0.111085679408,
|
||||||
|
0.129747463188, 0.148485542077,
|
||||||
|
0.17666895552, 0.211551079576,
|
||||||
|
0.246387426566, 0.281101701381,
|
||||||
|
0.333730067903, 0.400427252613,
|
||||||
|
0.467383840696, 0.53443198291,
|
||||||
|
0.635172045472, 0.75800717174,
|
||||||
|
0.879926756695, 1.0
|
||||||
|
};
|
||||||
|
|
||||||
|
static void reset_segment(struct ayumi* ay);
|
||||||
|
|
||||||
|
double sqrt(double n)
|
||||||
|
{
|
||||||
|
double x0 = n;
|
||||||
|
double x1;
|
||||||
|
for (;;) {
|
||||||
|
x1 = x0 - (x0 * x0 - n) / (2 * x0);
|
||||||
|
double delta = (x1 - x0) / x0;
|
||||||
|
if (delta < .000001 && delta > -.000001)
|
||||||
|
return x1;
|
||||||
|
x0 = x1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int update_tone(struct ayumi* ay, int index) {
|
||||||
|
struct tone_channel* ch = &ay->channels[index];
|
||||||
|
ch->tone_counter += 1;
|
||||||
|
if (ch->tone_counter >= ch->tone_period) {
|
||||||
|
ch->tone_counter = 0;
|
||||||
|
ch->tone ^= 1;
|
||||||
|
}
|
||||||
|
return ch->tone;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int update_noise(struct ayumi* ay) {
|
||||||
|
int bit0x3;
|
||||||
|
ay->noise_counter += 1;
|
||||||
|
if (ay->noise_counter >= (ay->noise_period << 1)) {
|
||||||
|
ay->noise_counter = 0;
|
||||||
|
bit0x3 = ((ay->noise ^ (ay->noise >> 3)) & 1);
|
||||||
|
ay->noise = (ay->noise >> 1) | (bit0x3 << 16);
|
||||||
|
}
|
||||||
|
return ay->noise & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void slide_up(struct ayumi* ay) {
|
||||||
|
ay->envelope += 1;
|
||||||
|
if (ay->envelope > 31) {
|
||||||
|
ay->envelope_segment ^= 1;
|
||||||
|
reset_segment(ay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void slide_down(struct ayumi* ay) {
|
||||||
|
ay->envelope -= 1;
|
||||||
|
if (ay->envelope < 0) {
|
||||||
|
ay->envelope_segment ^= 1;
|
||||||
|
reset_segment(ay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hold_top(struct ayumi* ay) {
|
||||||
|
(void) ay;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hold_bottom(struct ayumi* ay) {
|
||||||
|
(void) ay;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void (* const Envelopes[][2])(struct ayumi*) = {
|
||||||
|
{slide_down, hold_bottom},
|
||||||
|
{slide_down, hold_bottom},
|
||||||
|
{slide_down, hold_bottom},
|
||||||
|
{slide_down, hold_bottom},
|
||||||
|
{slide_up, hold_bottom},
|
||||||
|
{slide_up, hold_bottom},
|
||||||
|
{slide_up, hold_bottom},
|
||||||
|
{slide_up, hold_bottom},
|
||||||
|
{slide_down, slide_down},
|
||||||
|
{slide_down, hold_bottom},
|
||||||
|
{slide_down, slide_up},
|
||||||
|
{slide_down, hold_top},
|
||||||
|
{slide_up, slide_up},
|
||||||
|
{slide_up, hold_top},
|
||||||
|
{slide_up, slide_down},
|
||||||
|
{slide_up, hold_bottom}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void reset_segment(struct ayumi* ay) {
|
||||||
|
if (Envelopes[ay->envelope_shape][ay->envelope_segment] == slide_down
|
||||||
|
|| Envelopes[ay->envelope_shape][ay->envelope_segment] == hold_top) {
|
||||||
|
ay->envelope = 31;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ay->envelope = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int update_envelope(struct ayumi* ay) {
|
||||||
|
ay->envelope_counter += 1;
|
||||||
|
if (ay->envelope_counter >= ay->envelope_period) {
|
||||||
|
ay->envelope_counter = 0;
|
||||||
|
Envelopes[ay->envelope_shape][ay->envelope_segment](ay);
|
||||||
|
}
|
||||||
|
return ay->envelope;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_mixer(struct ayumi* ay) {
|
||||||
|
int i;
|
||||||
|
int out;
|
||||||
|
int noise = update_noise(ay);
|
||||||
|
int envelope = update_envelope(ay);
|
||||||
|
ay->left = 0;
|
||||||
|
ay->right = 0;
|
||||||
|
for (i = 0; i < TONE_CHANNELS; i += 1) {
|
||||||
|
out = (update_tone(ay, i) | ay->channels[i].t_off) & (noise | ay->channels[i].n_off);
|
||||||
|
out *= ay->channels[i].e_on ? envelope : ay->channels[i].volume * 2 + 1;
|
||||||
|
ay->left += ay->dac_table[out] * ay->channels[i].pan_left;
|
||||||
|
ay->right += ay->dac_table[out] * ay->channels[i].pan_right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ayumi_configure(struct ayumi* ay, int is_ym, double clock_rate, int sr) {
|
||||||
|
int i;
|
||||||
|
memset(ay, 0, sizeof(struct ayumi));
|
||||||
|
ay->step = clock_rate / (sr * 8 * DECIMATE_FACTOR);
|
||||||
|
ay->dac_table = is_ym ? YM_dac_table : AY_dac_table;
|
||||||
|
ay->noise = 1;
|
||||||
|
ayumi_set_envelope(ay, 1);
|
||||||
|
for (i = 0; i < TONE_CHANNELS; i += 1) {
|
||||||
|
ayumi_set_tone(ay, i, 1);
|
||||||
|
}
|
||||||
|
return ay->step < 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_set_pan(struct ayumi* ay, int index, double pan, int is_eqp) {
|
||||||
|
if (is_eqp) {
|
||||||
|
ay->channels[index].pan_left = sqrt(1 - pan);
|
||||||
|
ay->channels[index].pan_right = sqrt(pan);
|
||||||
|
} else {
|
||||||
|
ay->channels[index].pan_left = 1 - pan;
|
||||||
|
ay->channels[index].pan_right = pan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_set_tone(struct ayumi* ay, int index, int period) {
|
||||||
|
period &= 0xfff;
|
||||||
|
ay->channels[index].tone_period = (period == 0) | period;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_set_noise(struct ayumi* ay, int period) {
|
||||||
|
ay->noise_period = period & 0x1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_set_mixer(struct ayumi* ay, int index, int t_off, int n_off, int e_on) {
|
||||||
|
ay->channels[index].t_off = t_off & 1;
|
||||||
|
ay->channels[index].n_off = n_off & 1;
|
||||||
|
ay->channels[index].e_on = e_on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_set_volume(struct ayumi* ay, int index, int volume) {
|
||||||
|
ay->channels[index].volume = volume & 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_set_envelope(struct ayumi* ay, int period) {
|
||||||
|
period &= 0xffff;
|
||||||
|
ay->envelope_period = (period == 0) | period;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_set_envelope_shape(struct ayumi* ay, int shape) {
|
||||||
|
ay->envelope_shape = shape & 0xf;
|
||||||
|
ay->envelope_counter = 0;
|
||||||
|
ay->envelope_segment = 0;
|
||||||
|
reset_segment(ay);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double decimate(double* x) {
|
||||||
|
double y = -0.0000046183113992051936 * (x[1] + x[191]) +
|
||||||
|
-0.00001117761640887225 * (x[2] + x[190]) +
|
||||||
|
-0.000018610264502005432 * (x[3] + x[189]) +
|
||||||
|
-0.000025134586135631012 * (x[4] + x[188]) +
|
||||||
|
-0.000028494281690666197 * (x[5] + x[187]) +
|
||||||
|
-0.000026396828793275159 * (x[6] + x[186]) +
|
||||||
|
-0.000017094212558802156 * (x[7] + x[185]) +
|
||||||
|
0.000023798193576966866 * (x[9] + x[183]) +
|
||||||
|
0.000051281160242202183 * (x[10] + x[182]) +
|
||||||
|
0.00007762197826243427 * (x[11] + x[181]) +
|
||||||
|
0.000096759426664120416 * (x[12] + x[180]) +
|
||||||
|
0.00010240229300393402 * (x[13] + x[179]) +
|
||||||
|
0.000089344614218077106 * (x[14] + x[178]) +
|
||||||
|
0.000054875700118949183 * (x[15] + x[177]) +
|
||||||
|
-0.000069839082210680165 * (x[17] + x[175]) +
|
||||||
|
-0.0001447966132360757 * (x[18] + x[174]) +
|
||||||
|
-0.00021158452917708308 * (x[19] + x[173]) +
|
||||||
|
-0.00025535069106550544 * (x[20] + x[172]) +
|
||||||
|
-0.00026228714374322104 * (x[21] + x[171]) +
|
||||||
|
-0.00022258805927027799 * (x[22] + x[170]) +
|
||||||
|
-0.00013323230495695704 * (x[23] + x[169]) +
|
||||||
|
0.00016182578767055206 * (x[25] + x[167]) +
|
||||||
|
0.00032846175385096581 * (x[26] + x[166]) +
|
||||||
|
0.00047045611576184863 * (x[27] + x[165]) +
|
||||||
|
0.00055713851457530944 * (x[28] + x[164]) +
|
||||||
|
0.00056212565121518726 * (x[29] + x[163]) +
|
||||||
|
0.00046901918553962478 * (x[30] + x[162]) +
|
||||||
|
0.00027624866838952986 * (x[31] + x[161]) +
|
||||||
|
-0.00032564179486838622 * (x[33] + x[159]) +
|
||||||
|
-0.00065182310286710388 * (x[34] + x[158]) +
|
||||||
|
-0.00092127787309319298 * (x[35] + x[157]) +
|
||||||
|
-0.0010772534348943575 * (x[36] + x[156]) +
|
||||||
|
-0.0010737727700273478 * (x[37] + x[155]) +
|
||||||
|
-0.00088556645390392634 * (x[38] + x[154]) +
|
||||||
|
-0.00051581896090765534 * (x[39] + x[153]) +
|
||||||
|
0.00059548767193795277 * (x[41] + x[151]) +
|
||||||
|
0.0011803558710661009 * (x[42] + x[150]) +
|
||||||
|
0.0016527320270369871 * (x[43] + x[149]) +
|
||||||
|
0.0019152679330965555 * (x[44] + x[148]) +
|
||||||
|
0.0018927324805381538 * (x[45] + x[147]) +
|
||||||
|
0.0015481870327877937 * (x[46] + x[146]) +
|
||||||
|
0.00089470695834941306 * (x[47] + x[145]) +
|
||||||
|
-0.0010178225878206125 * (x[49] + x[143]) +
|
||||||
|
-0.0020037400552054292 * (x[50] + x[142]) +
|
||||||
|
-0.0027874356824117317 * (x[51] + x[141]) +
|
||||||
|
-0.003210329988021943 * (x[52] + x[140]) +
|
||||||
|
-0.0031540624117984395 * (x[53] + x[139]) +
|
||||||
|
-0.0025657163651900345 * (x[54] + x[138]) +
|
||||||
|
-0.0014750752642111449 * (x[55] + x[137]) +
|
||||||
|
0.0016624165446378462 * (x[57] + x[135]) +
|
||||||
|
0.0032591192839069179 * (x[58] + x[134]) +
|
||||||
|
0.0045165685815867747 * (x[59] + x[133]) +
|
||||||
|
0.0051838984346123896 * (x[60] + x[132]) +
|
||||||
|
0.0050774264697459933 * (x[61] + x[131]) +
|
||||||
|
0.0041192521414141585 * (x[62] + x[130]) +
|
||||||
|
0.0023628575417966491 * (x[63] + x[129]) +
|
||||||
|
-0.0026543507866759182 * (x[65] + x[127]) +
|
||||||
|
-0.0051990251084333425 * (x[66] + x[126]) +
|
||||||
|
-0.0072020238234656924 * (x[67] + x[125]) +
|
||||||
|
-0.0082672928192007358 * (x[68] + x[124]) +
|
||||||
|
-0.0081033739572956287 * (x[69] + x[123]) +
|
||||||
|
-0.006583111539570221 * (x[70] + x[122]) +
|
||||||
|
-0.0037839040415292386 * (x[71] + x[121]) +
|
||||||
|
0.0042781252851152507 * (x[73] + x[119]) +
|
||||||
|
0.0084176358598320178 * (x[74] + x[118]) +
|
||||||
|
0.01172566057463055 * (x[75] + x[117]) +
|
||||||
|
0.013550476647788672 * (x[76] + x[116]) +
|
||||||
|
0.013388189369997496 * (x[77] + x[115]) +
|
||||||
|
0.010979501242341259 * (x[78] + x[114]) +
|
||||||
|
0.006381274941685413 * (x[79] + x[113]) +
|
||||||
|
-0.007421229604153888 * (x[81] + x[111]) +
|
||||||
|
-0.01486456304340213 * (x[82] + x[110]) +
|
||||||
|
-0.021143584622178104 * (x[83] + x[109]) +
|
||||||
|
-0.02504275058758609 * (x[84] + x[108]) +
|
||||||
|
-0.025473530942547201 * (x[85] + x[107]) +
|
||||||
|
-0.021627310017882196 * (x[86] + x[106]) +
|
||||||
|
-0.013104323383225543 * (x[87] + x[105]) +
|
||||||
|
0.017065133989980476 * (x[89] + x[103]) +
|
||||||
|
0.036978919264451952 * (x[90] + x[102]) +
|
||||||
|
0.05823318062093958 * (x[91] + x[101]) +
|
||||||
|
0.079072012081405949 * (x[92] + x[100]) +
|
||||||
|
0.097675998716952317 * (x[93] + x[99]) +
|
||||||
|
0.11236045936950932 * (x[94] + x[98]) +
|
||||||
|
0.12176343577287731 * (x[95] + x[97]) +
|
||||||
|
0.125 * x[96];
|
||||||
|
memcpy(&x[FIR_SIZE - DECIMATE_FACTOR], x, DECIMATE_FACTOR * sizeof(double));
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_process(struct ayumi* ay) {
|
||||||
|
int i;
|
||||||
|
double y1;
|
||||||
|
double* c_left = ay->interpolator_left.c;
|
||||||
|
double* y_left = ay->interpolator_left.y;
|
||||||
|
double* c_right = ay->interpolator_right.c;
|
||||||
|
double* y_right = ay->interpolator_right.y;
|
||||||
|
double* fir_left = &ay->fir_left[FIR_SIZE - ay->fir_index * DECIMATE_FACTOR];
|
||||||
|
double* fir_right = &ay->fir_right[FIR_SIZE - ay->fir_index * DECIMATE_FACTOR];
|
||||||
|
ay->fir_index = (ay->fir_index + 1) % (FIR_SIZE / DECIMATE_FACTOR - 1);
|
||||||
|
for (i = DECIMATE_FACTOR - 1; i >= 0; i -= 1) {
|
||||||
|
ay->x += ay->step;
|
||||||
|
if (ay->x >= 1) {
|
||||||
|
ay->x -= 1;
|
||||||
|
y_left[0] = y_left[1];
|
||||||
|
y_left[1] = y_left[2];
|
||||||
|
y_left[2] = y_left[3];
|
||||||
|
y_right[0] = y_right[1];
|
||||||
|
y_right[1] = y_right[2];
|
||||||
|
y_right[2] = y_right[3];
|
||||||
|
update_mixer(ay);
|
||||||
|
y_left[3] = ay->left;
|
||||||
|
y_right[3] = ay->right;
|
||||||
|
y1 = y_left[2] - y_left[0];
|
||||||
|
c_left[0] = 0.5 * y_left[1] + 0.25 * (y_left[0] + y_left[2]);
|
||||||
|
c_left[1] = 0.5 * y1;
|
||||||
|
c_left[2] = 0.25 * (y_left[3] - y_left[1] - y1);
|
||||||
|
y1 = y_right[2] - y_right[0];
|
||||||
|
c_right[0] = 0.5 * y_right[1] + 0.25 * (y_right[0] + y_right[2]);
|
||||||
|
c_right[1] = 0.5 * y1;
|
||||||
|
c_right[2] = 0.25 * (y_right[3] - y_right[1] - y1);
|
||||||
|
}
|
||||||
|
fir_left[i] = (c_left[2] * ay->x + c_left[1]) * ay->x + c_left[0];
|
||||||
|
fir_right[i] = (c_right[2] * ay->x + c_right[1]) * ay->x + c_right[0];
|
||||||
|
}
|
||||||
|
ay->left = decimate(fir_left);
|
||||||
|
ay->right = decimate(fir_right);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_seek(struct ayumi* ay) {
|
||||||
|
int i;
|
||||||
|
for (i = DECIMATE_FACTOR - 1; i >= 0; i -= 1) {
|
||||||
|
ay->x += ay->step;
|
||||||
|
if (ay->x >= 1) {
|
||||||
|
ay->x -= 1;
|
||||||
|
update_mixer(ay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static double dc_filter(struct dc_filter* dc, int index, double x) {
|
||||||
|
dc->sum += -dc->delay[index] + x;
|
||||||
|
dc->delay[index] = x;
|
||||||
|
return x - dc->sum / DC_FILTER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayumi_remove_dc(struct ayumi* ay) {
|
||||||
|
ay->left = dc_filter(&ay->dc_left, ay->dc_index, ay->left);
|
||||||
|
ay->right = dc_filter(&ay->dc_right, ay->dc_index, ay->right);
|
||||||
|
ay->dc_index = (ay->dc_index + 1) & (DC_FILTER_SIZE - 1);
|
||||||
|
}
|
72
lib/rbcodec/codecs/libayumi/ayumi.h
Normal file
72
lib/rbcodec/codecs/libayumi/ayumi.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/* Author: Peter Sovietov */
|
||||||
|
|
||||||
|
#ifndef AYUMI_H
|
||||||
|
#define AYUMI_H
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TONE_CHANNELS = 3,
|
||||||
|
DECIMATE_FACTOR = 8,
|
||||||
|
FIR_SIZE = 192,
|
||||||
|
DC_FILTER_SIZE = 1024
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tone_channel {
|
||||||
|
int tone_period;
|
||||||
|
int tone_counter;
|
||||||
|
int tone;
|
||||||
|
int t_off;
|
||||||
|
int n_off;
|
||||||
|
int e_on;
|
||||||
|
int volume;
|
||||||
|
double pan_left;
|
||||||
|
double pan_right;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct interpolator {
|
||||||
|
double c[4];
|
||||||
|
double y[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dc_filter {
|
||||||
|
double sum;
|
||||||
|
double delay[DC_FILTER_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ayumi {
|
||||||
|
struct tone_channel channels[TONE_CHANNELS];
|
||||||
|
int noise_period;
|
||||||
|
int noise_counter;
|
||||||
|
int noise;
|
||||||
|
int envelope_counter;
|
||||||
|
int envelope_period;
|
||||||
|
int envelope_shape;
|
||||||
|
int envelope_segment;
|
||||||
|
int envelope;
|
||||||
|
const double* dac_table;
|
||||||
|
double step;
|
||||||
|
double x;
|
||||||
|
struct interpolator interpolator_left;
|
||||||
|
struct interpolator interpolator_right;
|
||||||
|
double fir_left[FIR_SIZE * 2];
|
||||||
|
double fir_right[FIR_SIZE * 2];
|
||||||
|
int fir_index;
|
||||||
|
struct dc_filter dc_left;
|
||||||
|
struct dc_filter dc_right;
|
||||||
|
int dc_index;
|
||||||
|
double left;
|
||||||
|
double right;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ayumi_configure(struct ayumi* ay, int is_ym, double clock_rate, int sr);
|
||||||
|
void ayumi_set_pan(struct ayumi* ay, int index, double pan, int is_eqp);
|
||||||
|
void ayumi_set_tone(struct ayumi* ay, int index, int period);
|
||||||
|
void ayumi_set_noise(struct ayumi* ay, int period);
|
||||||
|
void ayumi_set_mixer(struct ayumi* ay, int index, int t_off, int n_off, int e_on);
|
||||||
|
void ayumi_set_volume(struct ayumi* ay, int index, int volume);
|
||||||
|
void ayumi_set_envelope(struct ayumi* ay, int period);
|
||||||
|
void ayumi_set_envelope_shape(struct ayumi* ay, int shape);
|
||||||
|
void ayumi_process(struct ayumi* ay);
|
||||||
|
void ayumi_seek(struct ayumi* ay);
|
||||||
|
void ayumi_remove_dc(struct ayumi* ay);
|
||||||
|
|
||||||
|
#endif
|
328
lib/rbcodec/codecs/libayumi/ayumi_render.c
Normal file
328
lib/rbcodec/codecs/libayumi/ayumi_render.c
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
#include "ayumi_render.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "ayumi.h"
|
||||||
|
#include "lzh.h"
|
||||||
|
#include "codeclib.h"
|
||||||
|
|
||||||
|
ayumi_render_t ay;
|
||||||
|
|
||||||
|
/* default panning settings, 7 stereo types */
|
||||||
|
static const double default_pan[7][3] = {
|
||||||
|
/* A, B, C */
|
||||||
|
|
||||||
|
{0.50, 0.50, 0.50}, /* MONO */
|
||||||
|
{0.10, 0.50, 0.90}, /* ABC */
|
||||||
|
{0.10, 0.90, 0.50}, /* ACB */
|
||||||
|
{0.50, 0.10, 0.90}, /* BAC */
|
||||||
|
{0.90, 0.10, 0.50}, /* BCA */
|
||||||
|
{0.50, 0.90, 0.10}, /* CAB */
|
||||||
|
{0.90, 0.50, 0.10} /* CBA */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *chiptype_name[3] = {
|
||||||
|
"AY-3-8910",
|
||||||
|
"YM2149",
|
||||||
|
"Unknown"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *layout_name[9] = {
|
||||||
|
"Mono",
|
||||||
|
"ABC Stereo",
|
||||||
|
"ACB Stereo",
|
||||||
|
"BAC Stereo",
|
||||||
|
"BCA Stereo",
|
||||||
|
"CAB Stereo",
|
||||||
|
"CBA Stereo",
|
||||||
|
"Custom",
|
||||||
|
"Unknown"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* reader */
|
||||||
|
|
||||||
|
#define VTX_STRING_MAX 254
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uchar *ptr;
|
||||||
|
uint size;
|
||||||
|
} reader_t;
|
||||||
|
|
||||||
|
reader_t reader;
|
||||||
|
|
||||||
|
void Reader_Init(void *pBlock) {
|
||||||
|
reader.ptr = (uchar *) pBlock;
|
||||||
|
reader.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Reader_ReadByte(void) {
|
||||||
|
uint res;
|
||||||
|
res = *reader.ptr++;
|
||||||
|
reader.size += 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Reader_ReadWord(void) {
|
||||||
|
uint res;
|
||||||
|
res = *reader.ptr++;
|
||||||
|
res += *reader.ptr++ << 8;
|
||||||
|
reader.size += 2;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Reader_ReadDWord(void) {
|
||||||
|
uint res;
|
||||||
|
res = *reader.ptr++;
|
||||||
|
res += *reader.ptr++ << 8;
|
||||||
|
res += *reader.ptr++ << 16;
|
||||||
|
res += *reader.ptr++ << 24;
|
||||||
|
reader.size += 4;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Reader_ReadString(void) {
|
||||||
|
char *res;
|
||||||
|
if (reader.ptr == NULL)
|
||||||
|
return NULL;
|
||||||
|
int len = strlen((const char *)reader.ptr);
|
||||||
|
if (len > VTX_STRING_MAX)
|
||||||
|
return NULL;
|
||||||
|
res = reader.ptr;
|
||||||
|
reader.ptr += len + 1;
|
||||||
|
reader.size += len + 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar *Reader_GetPtr(void) {
|
||||||
|
return reader.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Reader_GetSize(void) {
|
||||||
|
return reader.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ayumi_render */
|
||||||
|
|
||||||
|
static int AyumiRender_LoadInfo(void *pBlock, uint size)
|
||||||
|
{
|
||||||
|
if (size < 20)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Reader_Init(pBlock);
|
||||||
|
|
||||||
|
uint hdr = Reader_ReadWord();
|
||||||
|
|
||||||
|
if (hdr == 0x7961)
|
||||||
|
ay.info.chiptype = VTX_CHIP_AY;
|
||||||
|
else if (hdr == 0x6d79)
|
||||||
|
ay.info.chiptype = VTX_CHIP_YM;
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ay.info.layout = (vtx_layout_t)
|
||||||
|
Reader_ReadByte();
|
||||||
|
ay.info.loop = Reader_ReadWord();
|
||||||
|
ay.info.chipfreq = Reader_ReadDWord();
|
||||||
|
ay.info.playerfreq = Reader_ReadByte();
|
||||||
|
ay.info.year = Reader_ReadWord();
|
||||||
|
ay.data.regdata_size = Reader_ReadDWord();
|
||||||
|
ay.info.frames = ay.data.regdata_size / 14;
|
||||||
|
ay.info.title = Reader_ReadString();
|
||||||
|
ay.info.author = Reader_ReadString();
|
||||||
|
ay.info.from = Reader_ReadString();
|
||||||
|
ay.info.tracker = Reader_ReadString();
|
||||||
|
ay.info.comment = Reader_ReadString();
|
||||||
|
|
||||||
|
ay.data.lzhdata_size = size - Reader_GetSize();
|
||||||
|
ay.data.lzhdata = (uchar *)codec_malloc(ay.data.lzhdata_size);
|
||||||
|
memcpy(ay.data.lzhdata, Reader_GetPtr(), ay.data.lzhdata_size);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AyumiRender_LoadFile(void *pBlock, uint size)
|
||||||
|
{
|
||||||
|
if (!AyumiRender_LoadInfo(pBlock, size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ay.data.regdata = (uchar *)codec_malloc(ay.data.regdata_size);
|
||||||
|
if (ay.data.regdata == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int bRet = LzUnpack(ay.data.lzhdata, ay.data.lzhdata_size,
|
||||||
|
ay.data.regdata, ay.data.regdata_size);
|
||||||
|
|
||||||
|
if (bRet)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *AyumiRender_GetChipTypeName(vtx_chiptype_t chiptype)
|
||||||
|
{
|
||||||
|
if (chiptype > VTX_CHIP_YM)
|
||||||
|
chiptype = (vtx_chiptype_t) (VTX_CHIP_YM + 1);
|
||||||
|
return chiptype_name[chiptype];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *AyumiRender_GetLayoutName(vtx_layout_t layout)
|
||||||
|
{
|
||||||
|
if (layout > VTX_LAYOUT_CUSTOM)
|
||||||
|
layout = (vtx_layout_t) (VTX_LAYOUT_CUSTOM + 1);
|
||||||
|
return layout_name[layout];
|
||||||
|
}
|
||||||
|
|
||||||
|
int AyumiRender_AyInit(vtx_chiptype_t chiptype, uint samplerate,
|
||||||
|
uint chipfreq, double playerfreq, uint dcfilter)
|
||||||
|
{
|
||||||
|
if (chiptype > VTX_CHIP_YM)
|
||||||
|
return 0;
|
||||||
|
if ((samplerate < 8000) || (samplerate > 768000))
|
||||||
|
return 0;
|
||||||
|
if ((chipfreq < 1000000) || (chipfreq > 2000000))
|
||||||
|
return 0;
|
||||||
|
if ((playerfreq < 1) || (playerfreq > 100))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ay.is_ym = (chiptype == VTX_CHIP_YM) ? 1 : 0;
|
||||||
|
ay.clock_rate = chipfreq;
|
||||||
|
ay.sr = samplerate;
|
||||||
|
|
||||||
|
ay.dc_filter_on = dcfilter ? 1 : 0;
|
||||||
|
|
||||||
|
ay.frame = 0;
|
||||||
|
ay.isr_counter = 1;
|
||||||
|
ay.isr_step = playerfreq / samplerate;
|
||||||
|
|
||||||
|
if (!ayumi_configure(&ay.ay, ay.is_ym, ay.clock_rate, ay.sr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AyumiRender_SetLayout(vtx_layout_t layout, uint eqpower)
|
||||||
|
{
|
||||||
|
if (layout > VTX_LAYOUT_CUSTOM)
|
||||||
|
return 0;
|
||||||
|
ay.is_eqp = eqpower ? 1 : 0;
|
||||||
|
|
||||||
|
switch (layout) {
|
||||||
|
case VTX_LAYOUT_MONO:
|
||||||
|
case VTX_LAYOUT_ABC:
|
||||||
|
case VTX_LAYOUT_ACB:
|
||||||
|
case VTX_LAYOUT_BAC:
|
||||||
|
case VTX_LAYOUT_BCA:
|
||||||
|
case VTX_LAYOUT_CAB:
|
||||||
|
case VTX_LAYOUT_CBA:
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
ay.pan[i] = default_pan[layout][i];
|
||||||
|
break;
|
||||||
|
case VTX_LAYOUT_CUSTOM:
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
ay.pan[i] = 0; // no custom layout
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
ayumi_set_pan(&ay.ay, i, ay.pan[i], ay.is_eqp);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint AyumiRender_GetPos(void)
|
||||||
|
{
|
||||||
|
return ay.frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint AyumiRender_GetMaxPos(void)
|
||||||
|
{
|
||||||
|
return ay.info.frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AyumiRender_UpdateAyumiState(void)
|
||||||
|
{
|
||||||
|
int r[16];
|
||||||
|
|
||||||
|
if (ay.frame < ay.info.frames) {
|
||||||
|
uchar *ptr = ay.data.regdata + ay.frame;
|
||||||
|
for (int n = 0; n < 14; n++) {
|
||||||
|
r[n] = *ptr;
|
||||||
|
ptr += ay.info.frames;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int n = 0; n < 14; n++) {
|
||||||
|
r[n] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ayumi_set_tone(&ay.ay, 0, (r[1] << 8) | r[0]);
|
||||||
|
ayumi_set_tone(&ay.ay, 1, (r[3] << 8) | r[2]);
|
||||||
|
ayumi_set_tone(&ay.ay, 2, (r[5] << 8) | r[4]);
|
||||||
|
ayumi_set_noise(&ay.ay, r[6]);
|
||||||
|
ayumi_set_mixer(&ay.ay, 0, r[7] & 1, (r[7] >> 3) & 1, r[8] >> 4);
|
||||||
|
ayumi_set_mixer(&ay.ay, 1, (r[7] >> 1) & 1, (r[7] >> 4) & 1, r[9] >> 4);
|
||||||
|
ayumi_set_mixer(&ay.ay, 2, (r[7] >> 2) & 1, (r[7] >> 5) & 1, r[10] >> 4);
|
||||||
|
ayumi_set_volume(&ay.ay, 0, r[8] & 0xf);
|
||||||
|
ayumi_set_volume(&ay.ay, 1, r[9] & 0xf);
|
||||||
|
ayumi_set_volume(&ay.ay, 2, r[10] & 0xf);
|
||||||
|
ayumi_set_envelope(&ay.ay, (r[12] << 8) | r[11]);
|
||||||
|
if (r[13] != 255) {
|
||||||
|
ayumi_set_envelope_shape(&ay.ay, r[13]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AyumiRender_Seek(ulong nSample)
|
||||||
|
{
|
||||||
|
ulong samples = 0;
|
||||||
|
|
||||||
|
ay.frame = 0;
|
||||||
|
ay.isr_counter = 1;
|
||||||
|
|
||||||
|
ayumi_configure(&ay.ay, ay.is_ym, ay.clock_rate, ay.sr);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
ayumi_set_pan(&ay.ay, i, ay.pan[i], ay.is_eqp);
|
||||||
|
|
||||||
|
while (samples < nSample) {
|
||||||
|
ay.isr_counter += ay.isr_step;
|
||||||
|
if (ay.isr_counter >= 1) {
|
||||||
|
ay.isr_counter -= 1;
|
||||||
|
AyumiRender_UpdateAyumiState();
|
||||||
|
ay.frame += 1;
|
||||||
|
}
|
||||||
|
ayumi_seek(&ay.ay);
|
||||||
|
samples++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong AyumiRender_AySynth(void *pBuffer, ulong nSamples)
|
||||||
|
{
|
||||||
|
ulong samples = 0;
|
||||||
|
short *out = (int16_t *) pBuffer;
|
||||||
|
|
||||||
|
for (ulong i = 0; i < nSamples; i++) {
|
||||||
|
ay.isr_counter += ay.isr_step;
|
||||||
|
if (ay.isr_counter >= 1) {
|
||||||
|
ay.isr_counter -= 1;
|
||||||
|
AyumiRender_UpdateAyumiState();
|
||||||
|
ay.frame += 1;
|
||||||
|
}
|
||||||
|
ayumi_process(&ay.ay);
|
||||||
|
if (ay.dc_filter_on) {
|
||||||
|
ayumi_remove_dc(&ay.ay);
|
||||||
|
}
|
||||||
|
out[0] = (int16_t)(ay.ay.left * 16383);
|
||||||
|
out[1] = (int16_t)(ay.ay.right * 16383);
|
||||||
|
out += 2;
|
||||||
|
samples++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return samples;
|
||||||
|
}
|
84
lib/rbcodec/codecs/libayumi/ayumi_render.h
Normal file
84
lib/rbcodec/codecs/libayumi/ayumi_render.h
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#ifndef AYUMI_RENDER_H
|
||||||
|
#define AYUMI_RENDER_H
|
||||||
|
|
||||||
|
#include "ayumi.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 frames; /* number of AY data frames */
|
||||||
|
} vtx_info_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uchar *lzhdata; /* packed song data */
|
||||||
|
uint lzhdata_size; /* size of packed data */
|
||||||
|
uchar *regdata; /* unpacked song data */
|
||||||
|
uint regdata_size; /* size of unpacked data */
|
||||||
|
} vtx_data_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint frame; /* current frame position */
|
||||||
|
double isr_step;
|
||||||
|
double isr_counter;
|
||||||
|
|
||||||
|
int dc_filter_on;
|
||||||
|
|
||||||
|
int is_ym;
|
||||||
|
double clock_rate;
|
||||||
|
int sr;
|
||||||
|
|
||||||
|
double pan[3];
|
||||||
|
int is_eqp;
|
||||||
|
|
||||||
|
struct ayumi ay; /* ayumi structure */
|
||||||
|
vtx_data_t data; /* packed & unpacked vtx data */
|
||||||
|
vtx_info_t info; /* vtx info */
|
||||||
|
} ayumi_render_t;
|
||||||
|
|
||||||
|
int AyumiRender_LoadFile(void *pBlock, uint size);
|
||||||
|
|
||||||
|
const char *AyumiRender_GetChipTypeName(vtx_chiptype_t chiptype);
|
||||||
|
const char *AyumiRender_GetLayoutName(vtx_layout_t layout);
|
||||||
|
|
||||||
|
uint AyumiRender_GetPos(void);
|
||||||
|
uint AyumiRender_GetMaxPos(void);
|
||||||
|
|
||||||
|
int AyumiRender_AyInit(vtx_chiptype_t chiptype, uint samplerate, uint chipfreq,
|
||||||
|
double playerfreq, uint dcfilter);
|
||||||
|
int AyumiRender_SetLayout(vtx_layout_t layout, uint eqpower);
|
||||||
|
|
||||||
|
int AyumiRender_Seek(ulong nSample);
|
||||||
|
|
||||||
|
ulong AyumiRender_AySynth(void *pBuffer, ulong nSamples);
|
||||||
|
|
||||||
|
#endif /* ifndef AYUMI_RENDER_H */
|
18
lib/rbcodec/codecs/libayumi/libayumi.make
Normal file
18
lib/rbcodec/codecs/libayumi/libayumi.make
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# __________ __ ___.
|
||||||
|
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
# \/ \/ \/ \/ \/
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
|
||||||
|
# libayumi
|
||||||
|
AYUMILIB := $(CODECDIR)/libayumi.a
|
||||||
|
AYUMILIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libayumi/SOURCES)
|
||||||
|
AYUMILIB_OBJ := $(call c2obj, $(AYUMILIB_SRC))
|
||||||
|
OTHER_SRC += $(AYUMILIB_SRC)
|
||||||
|
|
||||||
|
$(AYUMILIB): $(AYUMILIB_OBJ)
|
||||||
|
$(SILENT)$(shell rm -f $@)
|
||||||
|
$(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
|
420
lib/rbcodec/codecs/libayumi/lzh.c
Normal file
420
lib/rbcodec/codecs/libayumi/lzh.c
Normal file
|
@ -0,0 +1,420 @@
|
||||||
|
#include "lzh.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define BUFSIZE (1024 * 4)
|
||||||
|
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
typedef unsigned short ushort;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
|
||||||
|
#ifndef CHAR_BIT
|
||||||
|
#define CHAR_BIT 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UCHAR_MAX
|
||||||
|
#define UCHAR_MAX 255
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef ushort BITBUFTYPE;
|
||||||
|
|
||||||
|
#define BITBUFSIZ (CHAR_BIT * sizeof(BITBUFTYPE))
|
||||||
|
#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */
|
||||||
|
#define DICSIZ (1U << DICBIT)
|
||||||
|
#define MAXMATCH 256 /* formerly F (not more than UCHAR_MAX + 1) */
|
||||||
|
#define THRESHOLD 3 /* choose optimal value */
|
||||||
|
#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD) /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||||
|
#define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */
|
||||||
|
#define CODE_BIT 16 /* codeword length */
|
||||||
|
|
||||||
|
#define MAX_HASH_VAL (3 * DICSIZ + (DICSIZ / 512 + 1) * UCHAR_MAX)
|
||||||
|
|
||||||
|
#define NP (DICBIT + 1)
|
||||||
|
#define NT (CODE_BIT + 3)
|
||||||
|
#define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */
|
||||||
|
#define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */
|
||||||
|
#if NT > NP
|
||||||
|
#define NPT NT
|
||||||
|
#else
|
||||||
|
#define NPT NP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uchar *m_pSrc;
|
||||||
|
int m_srcSize;
|
||||||
|
uchar *m_pDst;
|
||||||
|
int m_dstSize;
|
||||||
|
|
||||||
|
int DataIn(void *pBuffer, int nBytes);
|
||||||
|
int DataOut(void *pOut, int nBytes);
|
||||||
|
|
||||||
|
void fillbuf(int n);
|
||||||
|
ushort getbits(int n);
|
||||||
|
void init_getbits(void);
|
||||||
|
int make_table(int nchar, uchar *bitlen, int tablebits, ushort *table);
|
||||||
|
void read_pt_len(int nn, int nbit, int i_special);
|
||||||
|
void read_c_len(void);
|
||||||
|
ushort decode_c(void);
|
||||||
|
ushort decode_p(void);
|
||||||
|
void huf_decode_start(void);
|
||||||
|
void decode_start(void);
|
||||||
|
void decode(uint count, uchar buffer[]);
|
||||||
|
|
||||||
|
int fillbufsize;
|
||||||
|
uchar buf[BUFSIZE];
|
||||||
|
uchar outbuf[DICSIZ];
|
||||||
|
ushort left[2 * NC - 1];
|
||||||
|
ushort right[2 * NC - 1];
|
||||||
|
BITBUFTYPE bitbuf;
|
||||||
|
uint subbitbuf;
|
||||||
|
int bitcount;
|
||||||
|
int decode_j; /* remaining bytes to copy */
|
||||||
|
uchar c_len[NC];
|
||||||
|
uchar pt_len[NPT];
|
||||||
|
uint blocksize;
|
||||||
|
ushort c_table[4096];
|
||||||
|
ushort pt_table[256];
|
||||||
|
int with_error;
|
||||||
|
|
||||||
|
uint fillbuf_i; /* NOTE: these ones are not initialized at constructor time but inside the fillbuf and decode func. */
|
||||||
|
uint decode_i;
|
||||||
|
|
||||||
|
/* Additions */
|
||||||
|
|
||||||
|
int DataIn(void *pBuffer, int nBytes)
|
||||||
|
{
|
||||||
|
const int np = (nBytes <= m_srcSize) ? nBytes : m_srcSize;
|
||||||
|
if (np > 0) {
|
||||||
|
memcpy(pBuffer, m_pSrc, np);
|
||||||
|
m_pSrc += np;
|
||||||
|
m_srcSize -= np;
|
||||||
|
}
|
||||||
|
return np;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataOut(void *pBuffer, int nBytes)
|
||||||
|
{
|
||||||
|
const int np = (nBytes <= m_dstSize) ? nBytes : m_dstSize;
|
||||||
|
if (np > 0) {
|
||||||
|
memcpy(m_pDst, pBuffer, np);
|
||||||
|
m_pDst += np;
|
||||||
|
m_dstSize -= np;
|
||||||
|
}
|
||||||
|
return np;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* io.c */
|
||||||
|
|
||||||
|
/* Shift bitbuf n bits left, read n bits */
|
||||||
|
void fillbuf(int n)
|
||||||
|
{
|
||||||
|
bitbuf = (bitbuf << n) & 0xffff;
|
||||||
|
while (n > bitcount) {
|
||||||
|
bitbuf |= subbitbuf << (n -= bitcount);
|
||||||
|
if (fillbufsize == 0) {
|
||||||
|
fillbuf_i = 0;
|
||||||
|
fillbufsize = DataIn(buf, BUFSIZE - 32);
|
||||||
|
}
|
||||||
|
if (fillbufsize > 0)
|
||||||
|
fillbufsize--, subbitbuf = buf[fillbuf_i++];
|
||||||
|
else
|
||||||
|
subbitbuf = 0;
|
||||||
|
bitcount = CHAR_BIT;
|
||||||
|
}
|
||||||
|
bitbuf |= subbitbuf >> (bitcount -= n);
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort getbits(int n)
|
||||||
|
{
|
||||||
|
ushort x;
|
||||||
|
x = bitbuf >> (BITBUFSIZ - n);
|
||||||
|
fillbuf(n);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_getbits(void)
|
||||||
|
{
|
||||||
|
bitbuf = 0;
|
||||||
|
subbitbuf = 0;
|
||||||
|
bitcount = 0;
|
||||||
|
fillbuf(BITBUFSIZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* maketbl.c */
|
||||||
|
|
||||||
|
int make_table(int nchar, uchar * bitlen, int tablebits, ushort * table)
|
||||||
|
{
|
||||||
|
ushort count[17], weight[17], start[18], *p;
|
||||||
|
uint jutbits, avail, mask;
|
||||||
|
int i, ch, len, nextcode;
|
||||||
|
|
||||||
|
for (i = 1; i <= 16; i++)
|
||||||
|
count[i] = 0;
|
||||||
|
for (i = 0; i < nchar; i++)
|
||||||
|
count[bitlen[i]]++;
|
||||||
|
|
||||||
|
start[1] = 0;
|
||||||
|
for (i = 1; i <= 16; i++)
|
||||||
|
start[i + 1] = start[i] + (count[i] << (16 - i));
|
||||||
|
if (start[17] != (ushort) (1U << 16))
|
||||||
|
return (1); /* error: bad table */
|
||||||
|
|
||||||
|
jutbits = 16 - tablebits;
|
||||||
|
for (i = 1; i <= tablebits; i++) {
|
||||||
|
start[i] >>= jutbits;
|
||||||
|
weight[i] = 1U << (tablebits - i);
|
||||||
|
}
|
||||||
|
while (i <= 16) {
|
||||||
|
weight[i] = 1U << (16 - i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = start[tablebits + 1] >> jutbits;
|
||||||
|
if (i != (ushort) (1U << 16)) {
|
||||||
|
int k = 1U << tablebits;
|
||||||
|
while (i != k)
|
||||||
|
table[i++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
avail = nchar;
|
||||||
|
mask = 1U << (15 - tablebits);
|
||||||
|
for (ch = 0; ch < nchar; ch++) {
|
||||||
|
if ((len = bitlen[ch]) == 0)
|
||||||
|
continue;
|
||||||
|
nextcode = start[len] + weight[len];
|
||||||
|
if (len <= tablebits) {
|
||||||
|
for (i = start[len]; i < nextcode; i++)
|
||||||
|
table[i] = ch;
|
||||||
|
} else {
|
||||||
|
uint k = start[len];
|
||||||
|
p = &table[k >> jutbits];
|
||||||
|
i = len - tablebits;
|
||||||
|
while (i != 0) {
|
||||||
|
if (*p == 0) {
|
||||||
|
right[avail] = left[avail] = 0;
|
||||||
|
*p = avail++;
|
||||||
|
}
|
||||||
|
if (k & mask)
|
||||||
|
p = &right[*p];
|
||||||
|
else
|
||||||
|
p = &left[*p];
|
||||||
|
k <<= 1;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
*p = ch;
|
||||||
|
}
|
||||||
|
start[len] = nextcode;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* huf.c */
|
||||||
|
|
||||||
|
void read_pt_len(int nn, int nbit, int i_special)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
short c;
|
||||||
|
ushort mask;
|
||||||
|
|
||||||
|
n = getbits(nbit);
|
||||||
|
if (n == 0) {
|
||||||
|
c = getbits(nbit);
|
||||||
|
for (i = 0; i < nn; i++)
|
||||||
|
pt_len[i] = 0;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
pt_table[i] = c;
|
||||||
|
} else {
|
||||||
|
i = 0;
|
||||||
|
while (i < n) {
|
||||||
|
c = bitbuf >> (BITBUFSIZ - 3);
|
||||||
|
if (c == 7) {
|
||||||
|
mask = 1U << (BITBUFSIZ - 1 - 3);
|
||||||
|
while (mask & bitbuf) {
|
||||||
|
mask >>= 1;
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fillbuf((c < 7) ? 3 : c - 3);
|
||||||
|
pt_len[i++] = (unsigned char) (c);
|
||||||
|
if (i == i_special) {
|
||||||
|
c = getbits(2);
|
||||||
|
while (--c >= 0)
|
||||||
|
pt_len[i++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (i < nn)
|
||||||
|
pt_len[i++] = 0;
|
||||||
|
make_table(nn, pt_len, 8, pt_table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_c_len(void)
|
||||||
|
{
|
||||||
|
short i, c, n;
|
||||||
|
ushort mask;
|
||||||
|
|
||||||
|
n = getbits(CBIT);
|
||||||
|
if (n == 0) {
|
||||||
|
c = getbits(CBIT);
|
||||||
|
for (i = 0; i < NC; i++)
|
||||||
|
c_len[i] = 0;
|
||||||
|
for (i = 0; i < 4096; i++)
|
||||||
|
c_table[i] = c;
|
||||||
|
} else {
|
||||||
|
i = 0;
|
||||||
|
while (i < n) {
|
||||||
|
c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
|
||||||
|
if (c >= NT) {
|
||||||
|
mask = 1U << (BITBUFSIZ - 1 - 8);
|
||||||
|
do {
|
||||||
|
if (bitbuf & mask)
|
||||||
|
c = right[c];
|
||||||
|
else
|
||||||
|
c = left[c];
|
||||||
|
mask >>= 1;
|
||||||
|
} while (c >= NT);
|
||||||
|
}
|
||||||
|
fillbuf(pt_len[c]);
|
||||||
|
if (c <= 2) {
|
||||||
|
if (c == 0)
|
||||||
|
c = 1;
|
||||||
|
else if (c == 1)
|
||||||
|
c = getbits(4) + 3;
|
||||||
|
else
|
||||||
|
c = getbits(CBIT) + 20;
|
||||||
|
while (--c >= 0)
|
||||||
|
c_len[i++] = 0;
|
||||||
|
} else
|
||||||
|
c_len[i++] = c - 2;
|
||||||
|
}
|
||||||
|
while (i < NC)
|
||||||
|
c_len[i++] = 0;
|
||||||
|
make_table(NC, c_len, 12, c_table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort decode_c(void)
|
||||||
|
{
|
||||||
|
ushort j, mask;
|
||||||
|
|
||||||
|
if (blocksize == 0) {
|
||||||
|
blocksize = getbits(16);
|
||||||
|
read_pt_len(NT, TBIT, 3);
|
||||||
|
read_c_len();
|
||||||
|
read_pt_len(NP, PBIT, -1);
|
||||||
|
}
|
||||||
|
blocksize--;
|
||||||
|
j = c_table[bitbuf >> (BITBUFSIZ - 12)];
|
||||||
|
if (j >= NC) {
|
||||||
|
mask = 1U << (BITBUFSIZ - 1 - 12);
|
||||||
|
do {
|
||||||
|
if (bitbuf & mask)
|
||||||
|
j = right[j];
|
||||||
|
else
|
||||||
|
j = left[j];
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
while (j >= NC);
|
||||||
|
}
|
||||||
|
fillbuf(c_len[j]);
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort decode_p(void)
|
||||||
|
{
|
||||||
|
ushort j, mask;
|
||||||
|
|
||||||
|
j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
|
||||||
|
if (j >= NP) {
|
||||||
|
mask = 1U << (BITBUFSIZ - 1 - 8);
|
||||||
|
do {
|
||||||
|
if (bitbuf & mask)
|
||||||
|
j = right[j];
|
||||||
|
else
|
||||||
|
j = left[j];
|
||||||
|
mask >>= 1;
|
||||||
|
} while (j >= NP);
|
||||||
|
}
|
||||||
|
fillbuf(pt_len[j]);
|
||||||
|
if (j != 0)
|
||||||
|
j = (1U << (j - 1)) + getbits(j - 1);
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
void huf_decode_start(void)
|
||||||
|
{
|
||||||
|
init_getbits();
|
||||||
|
blocksize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decode.c */
|
||||||
|
|
||||||
|
void decode_start(void)
|
||||||
|
{
|
||||||
|
fillbufsize = 0;
|
||||||
|
huf_decode_start();
|
||||||
|
decode_j = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The calling function must keep the number of bytes to be processed. This
|
||||||
|
* function decodes either 'count' bytes or 'DICSIZ' bytes, whichever is
|
||||||
|
* smaller, into the array 'buffer[]' of size 'DICSIZ' or more. Call
|
||||||
|
* decode_start() once for each new file before calling this function.
|
||||||
|
*/
|
||||||
|
void decode(uint count, uchar buffer[])
|
||||||
|
{
|
||||||
|
uint r, c;
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
while (--decode_j >= 0) {
|
||||||
|
buffer[r] = buffer[decode_i];
|
||||||
|
decode_i = (decode_i + 1) & (DICSIZ - 1);
|
||||||
|
if (++r == count)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
c = decode_c();
|
||||||
|
if (c <= UCHAR_MAX) {
|
||||||
|
buffer[r] = c;
|
||||||
|
if (++r == count)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
decode_j = c - (UCHAR_MAX + 1 - THRESHOLD);
|
||||||
|
decode_i = (r - decode_p() - 1) & (DICSIZ - 1);
|
||||||
|
while (--decode_j >= 0) {
|
||||||
|
buffer[r] = buffer[decode_i];
|
||||||
|
decode_i = (decode_i + 1) & (DICSIZ - 1);
|
||||||
|
if (++r == count)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int LzUnpack(void *pSrc, int srcSize, void *pDst, int dstSize)
|
||||||
|
{
|
||||||
|
with_error = 0;
|
||||||
|
|
||||||
|
m_pSrc = (uchar *) pSrc;
|
||||||
|
m_srcSize = srcSize;
|
||||||
|
m_pDst = (uchar *) pDst;
|
||||||
|
m_dstSize = dstSize;
|
||||||
|
|
||||||
|
decode_start();
|
||||||
|
|
||||||
|
unsigned int origsize = dstSize;
|
||||||
|
while (origsize != 0) {
|
||||||
|
int n = (uint) ((origsize > DICSIZ) ? DICSIZ : origsize);
|
||||||
|
decode(n, outbuf);
|
||||||
|
if (with_error)
|
||||||
|
break;
|
||||||
|
|
||||||
|
DataOut(outbuf, n);
|
||||||
|
origsize -= n;
|
||||||
|
if (with_error)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (with_error);
|
||||||
|
}
|
6
lib/rbcodec/codecs/libayumi/lzh.h
Normal file
6
lib/rbcodec/codecs/libayumi/lzh.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef LZH_H
|
||||||
|
#define LZH_H
|
||||||
|
|
||||||
|
int LzUnpack(void *pSrc, int srcSize, void *pDst, int dstSize);
|
||||||
|
|
||||||
|
#endif /* ifndef LZH_H */
|
138
lib/rbcodec/codecs/vtx.c
Normal file
138
lib/rbcodec/codecs/vtx.c
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* VTX Codec for rockbox based on the Ayumi engine
|
||||||
|
*
|
||||||
|
* Ayumi engine Written by Peter Sovietov in 2015
|
||||||
|
* Ported to rockbox '2019 by Roman Stolyarov
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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 <codecs/lib/codeclib.h>
|
||||||
|
#include "libayumi/ayumi_render.h"
|
||||||
|
|
||||||
|
CODEC_HEADER
|
||||||
|
|
||||||
|
#define VTX_SAMPLE_RATE 44100
|
||||||
|
|
||||||
|
/* Maximum number of bytes to process in one iteration */
|
||||||
|
#define CHUNK_SIZE (1024*2)
|
||||||
|
|
||||||
|
static int16_t samples[CHUNK_SIZE] IBSS_ATTR;
|
||||||
|
extern ayumi_render_t ay;
|
||||||
|
|
||||||
|
/****************** rockbox interface ******************/
|
||||||
|
|
||||||
|
/* this is the codec entry point */
|
||||||
|
enum codec_status codec_main(enum codec_entry_call_reason reason)
|
||||||
|
{
|
||||||
|
if (reason == CODEC_LOAD) {
|
||||||
|
/* we only render 16 bits */
|
||||||
|
ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
|
||||||
|
|
||||||
|
/* 44 Khz, Interleaved stereo */
|
||||||
|
ci->configure(DSP_SET_FREQUENCY, VTX_SAMPLE_RATE);
|
||||||
|
ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CODEC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is called for each file to process */
|
||||||
|
enum codec_status codec_run(void)
|
||||||
|
{
|
||||||
|
uint8_t *buf;
|
||||||
|
size_t n;
|
||||||
|
intptr_t param;
|
||||||
|
uint32_t elapsed_time;
|
||||||
|
long smp;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* reset values */
|
||||||
|
elapsed_time = 0;
|
||||||
|
param = ci->id3->elapsed;
|
||||||
|
|
||||||
|
DEBUGF("VTX: next_track\n");
|
||||||
|
if (codec_init()) {
|
||||||
|
return CODEC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
codec_set_replaygain(ci->id3);
|
||||||
|
|
||||||
|
/* Read the entire file */
|
||||||
|
DEBUGF("VTX: request file\n");
|
||||||
|
ci->seek_buffer(0);
|
||||||
|
buf = ci->request_buffer(&n, ci->filesize);
|
||||||
|
if (!buf || n < (size_t)ci->filesize) {
|
||||||
|
DEBUGF("VTX: file load failed\n");
|
||||||
|
return CODEC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = AyumiRender_LoadFile((void *)buf, ci->filesize);
|
||||||
|
if (!res) {
|
||||||
|
DEBUGF("VTX: AyumiRender_LoadFile failed\n");
|
||||||
|
return CODEC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = AyumiRender_AyInit(ay.info.chiptype, VTX_SAMPLE_RATE, ay.info.chipfreq, ay.info.playerfreq, 1);
|
||||||
|
if (!res) {
|
||||||
|
DEBUGF("VTX: AyumiRender_AyInit failed\n");
|
||||||
|
return CODEC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = AyumiRender_SetLayout(ay.info.layout, 0);
|
||||||
|
if (!res) {
|
||||||
|
DEBUGF("VTX: AyumiRender_SetLayout failed\n");
|
||||||
|
return CODEC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param) {
|
||||||
|
goto resume_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The main decoder loop */
|
||||||
|
while (1) {
|
||||||
|
long action = ci->get_command(¶m);
|
||||||
|
|
||||||
|
if (action == CODEC_ACTION_HALT)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (action == CODEC_ACTION_SEEK_TIME) {
|
||||||
|
resume_start:
|
||||||
|
ci->set_elapsed(param);
|
||||||
|
elapsed_time = param;
|
||||||
|
ulong sample = ((ulong)elapsed_time * 441) / 10;
|
||||||
|
AyumiRender_Seek(sample);
|
||||||
|
ci->seek_complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate audio buffer */
|
||||||
|
smp = AyumiRender_AySynth((void *)&samples[0], CHUNK_SIZE >> 1);
|
||||||
|
|
||||||
|
ci->pcmbuf_insert(samples, NULL, smp);
|
||||||
|
|
||||||
|
/* Set elapsed time for one track files */
|
||||||
|
elapsed_time += smp * 10 / 441;
|
||||||
|
ci->set_elapsed(elapsed_time);
|
||||||
|
|
||||||
|
if (AyumiRender_GetPos() >= AyumiRender_GetMaxPos())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CODEC_OK;
|
||||||
|
}
|
|
@ -208,6 +208,11 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
||||||
/* AY (ZX Spectrum, Amstrad CPC Sound Format) */
|
/* AY (ZX Spectrum, Amstrad CPC Sound Format) */
|
||||||
[AFMT_AY] =
|
[AFMT_AY] =
|
||||||
AFMT_ENTRY("AY", "ay", NULL, get_ay_metadata, "ay\0"),
|
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) */
|
/* GBS (Game Boy Sound Format) */
|
||||||
[AFMT_GBS] =
|
[AFMT_GBS] =
|
||||||
AFMT_ENTRY("GBS", "gbs", NULL, get_gbs_metadata, "gbs\0"),
|
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_MOD:
|
||||||
case AFMT_SAP:
|
case AFMT_SAP:
|
||||||
case AFMT_AY:
|
case AFMT_AY:
|
||||||
|
#ifdef HAVE_FPU
|
||||||
|
case AFMT_VTX:
|
||||||
|
#endif
|
||||||
case AFMT_GBS:
|
case AFMT_GBS:
|
||||||
case AFMT_HES:
|
case AFMT_HES:
|
||||||
case AFMT_SGC:
|
case AFMT_SGC:
|
||||||
|
|
|
@ -83,6 +83,9 @@ enum
|
||||||
AFMT_MPC_SV8, /* Musepack SV8 */
|
AFMT_MPC_SV8, /* Musepack SV8 */
|
||||||
AFMT_MP4_AAC_HE, /* Advanced Audio Coding (AAC-HE) in M4A container */
|
AFMT_MP4_AAC_HE, /* Advanced Audio Coding (AAC-HE) in M4A container */
|
||||||
AFMT_AY, /* AY (ZX Spectrum, Amstrad CPC Sound Format) */
|
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_GBS, /* GBS (Game Boy Sound Format) */
|
||||||
AFMT_HES, /* HES (Hudson Entertainment System Sound Format) */
|
AFMT_HES, /* HES (Hudson Entertainment System Sound Format) */
|
||||||
AFMT_SGC, /* SGC (Sega Master System, Game Gear, Coleco Vision Sound Format) */
|
AFMT_SGC, /* SGC (Sega Master System, Game Gear, Coleco Vision Sound Format) */
|
||||||
|
@ -329,5 +332,3 @@ bool rbcodec_format_is_atomic(int afmt);
|
||||||
bool format_buffers_with_offset(int afmt);
|
bool format_buffers_with_offset(int afmt);
|
||||||
|
|
||||||
#endif
|
#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_wave64_metadata(int fd, struct mp3entry* id3);
|
||||||
bool get_tta_metadata(int fd, struct mp3entry* id3);
|
bool get_tta_metadata(int fd, struct mp3entry* id3);
|
||||||
bool get_ay_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_gbs_metadata(int fd, struct mp3entry* id3);
|
||||||
bool get_hes_metadata(int fd, struct mp3entry* id3);
|
bool get_hes_metadata(int fd, struct mp3entry* id3);
|
||||||
bool get_sgc_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;
|
||||||
|
}
|
4
tools/configure
vendored
4
tools/configure
vendored
|
@ -556,7 +556,7 @@ arm926ejscc () {
|
||||||
|
|
||||||
arm1136jfscc () {
|
arm1136jfscc () {
|
||||||
findarmgcc
|
findarmgcc
|
||||||
GCCOPTS="$CCOPTS -mcpu=arm1136jf-s"
|
GCCOPTS="$CCOPTS -mcpu=arm1136jf-s -mfloat-abi=softfp"
|
||||||
GCCOPTIMIZE="-fomit-frame-pointer"
|
GCCOPTIMIZE="-fomit-frame-pointer"
|
||||||
endian="little"
|
endian="little"
|
||||||
}
|
}
|
||||||
|
@ -890,7 +890,7 @@ androidndkcc()
|
||||||
|
|
||||||
mipsellinuxcc () {
|
mipsellinuxcc () {
|
||||||
GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib//`
|
GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib//`
|
||||||
GCCOPTS="$GCCOPTS -march=mips32r2 -mno-mips16 -mno-long-calls -Umips -fPIC"
|
GCCOPTS="$GCCOPTS -march=mips32r2 -mhard-float -mno-mips16 -mno-long-calls -Umips -fPIC"
|
||||||
GCCOPTIMIZE=''
|
GCCOPTIMIZE=''
|
||||||
LDOPTS="-lasound -lpthread -lm -ldl -lrt $LDOPTS"
|
LDOPTS="-lasound -lpthread -lm -ldl -lrt $LDOPTS"
|
||||||
GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-z,defs"
|
GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-z,defs"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue