#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_CONFIG_OPTION68_H
# include <config_option68.h>
#else
# include "default_option68.h"
#endif
#include "ymemul.h"
#include "emu68/assert68.h"
#include <sc68/msg68.h>
#include <sc68/string68.h>
#include <sc68/option68.h>
extern int ym_cat;
#ifndef INTMSB
# define INTMSB (sizeof(int)*8-1)
#endif
#define YM_PULS_FILTER 1
#define YM_OUT_MSK(C,B,A) \
(((((C)&0x1F)<<10)) \
|((((B)&0x1F)<< 5)) \
|((((A)&0x1F) )))
const int ym_smsk_table[8] = {
YM_OUT_MSK(00,00,00),
YM_OUT_MSK(00,00,-1),
YM_OUT_MSK(00,-1,00),
YM_OUT_MSK(00,-1,-1),
YM_OUT_MSK(-1,00,00),
YM_OUT_MSK(-1,00,-1),
YM_OUT_MSK(-1,-1,00),
YM_OUT_MSK(-1,-1,-1)
};
static void filter_none(ym_t * const);
static void filter_1pole(ym_t * const);
static void filter_2pole(ym_t * const);
static void filter_mixed(ym_t * const);
static void filter_boxcar(ym_t * const);
static struct {
const char * name;
ym_puls_filter_t filter;
} filters[] = {
{ "2-poles", filter_2pole },
{ "none", filter_none },
{ "boxcar", filter_boxcar},
{ "1-pole", filter_1pole },
{ "mixed", filter_mixed }
};
static const int n_filters = sizeof(filters) / sizeof(*filters);
static int default_filter = 0;
static int reset(ym_t * const ym, const cycle68_t ymcycle)
{
ym_puls_t * const puls = &ym->emu.puls;
puls->env_bit = 0;
puls->env_ct = 0;
puls->noise_gen = 1;
puls->noise_ct = 0;
puls->voice_ctA = 0;
puls->voice_ctB = 0;
puls->voice_ctC = 0;
puls->levels = 0;
puls->hipass_inp1 = 0;
puls->hipass_out1 = 0;
puls->lopass_out1 = 0;
puls->btw.x[0] = puls->btw.x[1] = 0;
puls->btw.y[0] = puls->btw.y[1] = 0;
puls->btw.a[0] = 0x01eac69f;
puls->btw.a[1] = 0x03d58d3f;
puls->btw.a[2] = 0x01eac69f;
puls->btw.b[0] = -0x5d1253b0;
puls->btw.b[1] = 0x24bd6e2f;
return 0;
}
static int noise_generator(ym_t * const ym, int ymcycles)
{
ym_puls_t * const puls = &ym->emu.puls;
int rem_cycles;
int v, noise_gen, ct, per, msk;
s32 * b;
rem_cycles = ymcycles & 7;
if(!(ymcycles >>= 3)) goto finish;
ct = puls->noise_ct;
noise_gen = puls->noise_gen;
per = ym->reg.name.per_noise & 0x1F;
per <<= 1;
msk = ym_smsk_table[7 & (ym->reg.name.ctl_mixer >> 3)];
v = (u16)(-(noise_gen & 1) | msk);
b = puls->noiptr;
do {
if (++ct >= per) {
ct = 0;
noise_gen |= ((noise_gen^(noise_gen>>2)) & 1)<<17;
noise_gen >>= 1;
v = (u16)(-(noise_gen & 1) | msk);
}
*b++ = v;
} while (--ymcycles);
puls->noiptr = b;
puls->noise_gen = noise_gen;
puls->noise_ct = ct;
finish:
return rem_cycles;
}
static void do_noise(ym_t * const ym, cycle68_t ymcycle)
{
ym_puls_t * const puls = &ym->emu.puls;
ym_waccess_t * access;
ym_waccess_list_t * const regs = &ym->noi_regs;
cycle68_t lastcycle;
puls->noiptr = ym->outbuf;
if (!ymcycle) {
return;
}
for (access=regs->head, lastcycle=0; access; access=access->link) {
int ymcycles = access->ymcycle-lastcycle;
assert(access->ymcycle <= ymcycle);
if (ymcycles) {
lastcycle = access->ymcycle - noise_generator(ym,ymcycles);
}
ym->reg.index[access->reg] = access->val;
}
lastcycle = ymcycle - noise_generator(ym, ymcycle-lastcycle);
regs->head = regs->tail = 0;
}
#if YM_ENV_TABLE
#undef V
#define V(X) YM_OUT_MSK(X,X,X)
static const int env_uplo[64] = {
V(000),V(001),V(002),V(003),V(004),V(005),V(006),V(007),
V(010),V(011),V(012),V(013),V(014),V(015),V(016),V(017),
V(020),V(021),V(022),V(023),V(024),V(025),V(026),V(027),
V(030),V(031),V(032),V(033),V(034),V(035),V(036),V(037),
V(000),V(000),V(000),V(000),V(000),V(000),V(000),V(000),
V(000),V(000),V(000),V(000),V(000),V(000),V(000),V(000),
V(000),V(000),V(000),V(000),V(000),V(000),V(000),V(000),
V(000),V(000),V(000),V(000),V(000),V(000),V(000),V(000),
};
static const int env_uphi[64] = {
V(000),V(001),V(002),V(003),V(004),V(005),V(006),V(007),
V(010),V(011),V(012),V(013),V(014),V(015),V(016),V(017),
V(020),V(021),V(022),V(023),V(024),V(025),V(026),V(027),
V(030),V(031),V(032),V(033),V(034),V(035),V(036),V(037),
V(037),V(037),V(037),V(037),V(037),V(037),V(037),V(037),
V(037),V(037),V(037),V(037),V(037),V(037),V(037),V(037),
V(037),V(037),V(037),V(037),V(037),V(037),V(037),V(037),
V(037),V(037),V(037),V(037),V(037),V(037),V(037),V(037),
};
static const int env_upup[64] = {
V(000),V(001),V(002),V(003),V(004),V(005),V(006),V(007),
V(010),V(011),V(012),V(013),V(014),V(015),V(016),V(017),
V(020),V(021),V(022),V(023),V(024),V(025),V(026),V(027),
V(030),V(031),V(032),V(033),V(034),V(035),V(036),V(037),
V(000),V(001),V(002),V(003),V(004),V(005),V(006),V(007),
V(010),V(011),V(012),V(013),V(014),V(015),V(016),V(017),
V(020),V(021),V(022),V(023),V(024),V(025),V(026),V(027),
V(030),V(031),V(032),V(033),V(034),V(035),V(036),V(037)
};
static const int env_updw[64] = {
V(000),V(001),V(002),V(003),V(004),V(005),V(006),V(007),
V(010),V(011),V(012),V(013),V(014),V(015),V(016),V(017),
V(020),V(021),V(022),V(023),V(024),V(025),V(026),V(027),
V(030),V(031),V(032),V(033),V(034),V(035),V(036),V(037),
V(037),V(036),V(035),V(034),V(033),V(032),V(031),V(030),
V(027),V(026),V(025),V(024),V(023),V(022),V(021),V(020),
V(017),V(016),V(015),V(014),V(013),V(012),V(011),V(010),
V(007),V(006),V(005),V(004),V(003),V(002),V(001),V(000)
};
static const int env_dwlo[64] = {
V(037),V(036),V(035),V(034),V(033),V(032),V(031),V(030),
V(027),V(026),V(025),V(024),V(023),V(022),V(021),V(020),
V(017),V(016),V(015),V(014),V(013),V(012),V(011),V(010),
V(007),V(006),V(005),V(004),V(003),V(002),V(001),V(000),
V(000),V(000),V(000),V(000),V(000),V(000),V(000),V(000),
V(000),V(000),V(000),V(000),V(000),V(000),V(000),V(000),
V(000),V(000),V(000),V(000),V(000),V(000),V(000),V(000),
V(000),V(000),V(000),V(000),V(000),V(000),V(000),V(000),
};
static const int env_dwhi[64] = {
V(037),V(036),V(035),V(034),V(033),V(032),V(031),V(030),
V(027),V(026),V(025),V(024),V(023),V(022),V(021),V(020),
V(017),V(016),V(015),V(014),V(013),V(012),V(011),V(010),
V(007),V(006),V(005),V(004),V(003),V(002),V(001),V(000),
V(037),V(037),V(037),V(037),V(037),V(037),V(037),V(037),
V(037),V(037),V(037),V(037),V(037),V(037),V(037),V(037),
V(037),V(037),V(037),V(037),V(037),V(037),V(037),V(037),
V(037),V(037),V(037),V(037),V(037),V(037),V(037),V(037),
};
static const int env_dwup[64] = {
V(037),V(036),V(035),V(034),V(033),V(032),V(031),V(030),
V(027),V(026),V(025),V(024),V(023),V(022),V(021),V(020),
V(017),V(016),V(015),V(014),V(013),V(012),V(011),V(010),
V(007),V(006),V(005),V(004),V(003),V(002),V(001),V(000),
V(000),V(001),V(002),V(003),V(004),V(005),V(006),V(007),
V(010),V(011),V(012),V(013),V(014),V(015),V(016),V(017),
V(020),V(021),V(022),V(023),V(024),V(025),V(026),V(027),
V(030),V(031),V(032),V(033),V(034),V(035),V(036),V(037)
};
static const int env_dwdw[64] = {
V(037),V(036),V(035),V(034),V(033),V(032),V(031),V(030),
V(027),V(026),V(025),V(024),V(023),V(022),V(021),V(020),
V(017),V(016),V(015),V(014),V(013),V(012),V(011),V(010),
V(007),V(006),V(005),V(004),V(003),V(002),V(001),V(000),
V(037),V(036),V(035),V(034),V(033),V(032),V(031),V(030),
V(027),V(026),V(025),V(024),V(023),V(022),V(021),V(020),
V(017),V(016),V(015),V(014),V(013),V(012),V(011),V(010),
V(007),V(006),V(005),V(004),V(003),V(002),V(001),V(000)
};
#undef V
static const int * waveforms[16] = {
env_dwlo,
env_dwlo,
env_dwlo,
env_dwlo,
env_uplo,
env_uplo,
env_uplo,
env_uplo,
env_dwdw,
env_dwlo,
env_dwup,
env_dwhi,
env_upup,
env_uphi,
env_updw,
env_uplo
};
#endif
static int envelop_generator(ym_t * const ym, int ymcycles)
#if YM_ENV_TABLE
{
ym_puls_t * const puls = &ym->emu.puls;
int rem_cycle = ymcycles & 7;
if((ymcycles >>= 3)) {
const int shape = ym->reg.name.env_shape & 15;
const int * const waveform = waveforms[shape];
const int dnr = 1 & ~((shape>>3)&~shape);
s32 *b = puls->envptr;
int ct = puls->env_ct;
int bit = puls->env_bit;
int per = ym->reg.name.per_env_lo | (ym->reg.name.per_env_hi<<8);
do {
int t = ++ct >= per;
bit += t;
ct &= ~-t;
bit |= -((bit >> 6) & dnr);
bit &= 63;
*b++ |= waveform[bit]<<16;
} while (--ymcycles);
puls->envptr = b;
puls->env_ct = ct;
puls->env_bit = bit;
}
return rem_cycle;
}
#else
{
unsigned int ncycle = ymcycles;
int rem_cycle;
int *b;
int ct, per;
unsigned int bit, bitstp, restp;
unsigned int cont, recont;
unsigned int alt, altalt;
int shape;
#ifdef _DEBUG
if (ncycle < 0) {
BREAKPOINT68;
return 0;
}
#endif
rem_cycle = ncycle & 7;
if(!(ncycle >>= 3)) return rem_cycle;
b = ym->envptr;
ct = ym->env_ct;
per = ym->reg.index[YM_ENVL] | (ym->reg.index[YM_ENVH]<<8);
per |= !per;
shape = ym->reg.index[YM_ENVTYPE];
bit = ym->env_bit;
bitstp = ym->env_bitstp;
restp = (shape & 1) ^ 1;
cont = ym->env_cont;
recont = (-((shape>>3) & 0x1)) & 0x1F;
alt = ym->env_alt;
altalt = (-((shape ^ (shape>>1)) & 0x1)) & 0x1F;
do {
int n;
n = per - ct;
if (n <= 0) {
int prev_bit;
ct = 0;
n = per;
prev_bit = bit;
bit += bitstp;
if ((bit^prev_bit) & 32) {
bitstp = restp;
cont = recont;
alt ^= altalt;
}
}
int v = (bit ^ alt) & cont;
v |= v<<5;
v |= v<<5;
v <<= 16;
if (n > ncycle) {
n = ncycle;
}
ncycle -= n;
ct += n;
do {
*b++ |= v;
} while (--n);
} while (ncycle);
ym->envptr = b;
ym->env_ct = ct;
ym->env_bit = bit;
ym->env_bitstp = bitstp;
ym->env_cont = cont;
ym->env_alt = alt;
return rem_cycle;
}
#endif
static void do_envelop(ym_t * const ym, cycle68_t ymcycle)
{
ym_puls_t * const puls = &ym->emu.puls;
ym_waccess_t * access;
ym_waccess_list_t * const regs = &ym->env_regs;
cycle68_t lastcycle;
puls->envptr = ym->outbuf;
if (!ymcycle) {
return;
}
for (access=regs->head, lastcycle=0; access; access=access->link) {
int ymcycles = access->ymcycle-lastcycle;
if (access->ymcycle > ymcycle) {
TRACE68(ym_cat,"%s access reg %X out of frame!! (%u>%u %u)\n",
regs->name, access->reg, access->ymcycle, ymcycle,
access->ymcycle/ymcycle);
break;
}
if (ymcycles) {
lastcycle = access->ymcycle - envelop_generator(ym,ymcycles);
}
ym->reg.index[access->reg] = access->val;
if(access->reg == YM_ENVTYPE) {
#if YM_ENV_TABLE
puls->env_bit = 0;
puls->env_ct = 0;
#else
int shape = access->val & 15;
puls->env_alt = (~((shape << (INTMSB-2)) >> INTMSB)) & 0x1F;
puls->env_bit = 0;
puls->env_bitstp = 1;
puls->env_cont = 0x1f;
puls->env_ct = 0;
#endif
}
}
envelop_generator(ym, ymcycle-lastcycle);
regs->head = regs->tail = 0;
}
static int tone_generator(ym_t * const ym, int ymcycles)
{
ym_puls_t * const puls = &ym->emu.puls;
int ctA, ctB, ctC;
int perA, perB, perC;
int smsk, emsk, vols;
s32 * b;
int rem_cycles, v;
int levels;
int mute;
rem_cycles = ymcycles & 7;
ymcycles >>= 3;
if(!ymcycles) goto finish;
b = puls->tonptr;
mute = ym->voice_mute & YM_OUT_MSK_ALL;
smsk = ym_smsk_table[7 & ym->reg.name.ctl_mixer];
emsk = vols = 0;
v = ym->reg.name.vol_a & 0x1F;
if(v&0x10) emsk |= YM_OUT_MSK_A;
else vols |= (v<<1)+1;
v = ym->reg.name.vol_b & 0x1F;
if(v&0x10) emsk |= YM_OUT_MSK_B;
else vols |= (v<<6)+(1<<5);
v = ym->reg.name.vol_c & 0x1F;
if(v&0x10) emsk |= YM_OUT_MSK_C;
else vols |= (v<<11)+(1<<10);
ctA = puls->voice_ctA;
ctB = puls->voice_ctB;
ctC = puls->voice_ctC;
perA = ym->reg.name.per_a_lo | ((ym->reg.name.per_a_hi&0xF)<<8);
perB = ym->reg.name.per_b_lo | ((ym->reg.name.per_b_hi&0xF)<<8);
perC = ym->reg.name.per_c_lo | ((ym->reg.name.per_c_hi&0xF)<<8);
levels = puls->levels;
do {
int sq;
sq = -(++ctA >= perA);
levels ^= YM_OUT_MSK_A & sq;
ctA &= ~sq;
sq = -(++ctB >= perB);
levels ^= YM_OUT_MSK_B & sq;
ctB &= ~sq;
sq = -(++ctC >= perC);
levels ^= YM_OUT_MSK_C & sq;
ctC &= ~sq;
sq = levels;
sq |= smsk;
{
unsigned int eo = *b;
sq &= eo; eo >>= 16;
sq &= (eo&emsk) | vols;
}
sq &= mute;
sq = (int) ym->ymout5[sq];
*b++ = sq;
} while (--ymcycles);
puls->tonptr = b;
puls->voice_ctA = ctA;
puls->voice_ctB = ctB;
puls->voice_ctC = ctC;
puls->levels = levels;
finish:
return rem_cycles;
}
static void do_tone_and_mixer(ym_t * const ym, cycle68_t ymcycle)
{
ym_puls_t * const puls = &ym->emu.puls;
ym_waccess_t * access;
ym_waccess_list_t * const regs = &ym->ton_regs;
cycle68_t lastcycle;
puls->tonptr = ym->outbuf;
if (!ymcycle) {
return;
}
for (access=regs->head, lastcycle=0; access; access=access->link) {
const int ymcycles = access->ymcycle - lastcycle;
if (access->ymcycle > ymcycle) {
TRACE68(ym_cat,"%s access reg %X out of frame!! (%u>%u %u)\n",
regs->name, access->reg, access->ymcycle, ymcycle,
access->ymcycle/ymcycle);
break;
}
if (ymcycles) {
lastcycle = access->ymcycle - tone_generator(ym, ymcycles);
}
ym->reg.index[access->reg] = access->val;
}
tone_generator(ym, ymcycle-lastcycle);
regs->head = regs->tail = 0;
}
#if 0#else
# define REVOL(V) ((V) >> 1)
# define CLIP3(V,A,B) ( V < A ? A : ( V > B ? B : V ) )
#endif
#define CLIP(V) CLIP3(V,-32768,32767)
static inline int clip(int o)
{
#ifdef DEBUG
static int max, min;
if ( o < min ) {
min = o;
msg68(ym_cat,"ym-2149: pulse -- pcm min -- %d\n", o);
}
if ( o > max ) {
max = o;
msg68(ym_cat,"ym-2149: pulse -- pcm max -- %d\n", o);
}
if (o < -32768) {
msg68(ym_cat,"ym-2149: pulse -- pcm clip -- %d < -32768\n", o);
o = -32768;
}
if (o > 32767) {
msg68(ym_cat,"ym-2149: pulse -- pcm clip -- %d > 32767\n", o);
o = 32767;
}
#endif
return CLIP(o);
}
static s32 * resampling(s32 * dst, const int n,
const uint68_t irate, const uint68_t orate)
{
s32 * const src = dst;
const int68_t stp = (irate << 14) / orate;
if ( 0 == (stp & ((1<<14)-1)) ) {
const int istp = stp >> 14;
const int iend = n;
int idx = 0;
do {
int o = REVOL(src[idx]);
*dst++ = clip(o);
} while ((idx += istp) < iend);
} else {
const int68_t end = n << 14;
int68_t idx = 0;
if (stp >= 1<<14) {
do {
int o = REVOL(src[(int)(idx>>14)]);
*dst++ = clip(o);
} while ((idx += stp) < end);
} else {
const int m = (n * orate + irate - 1) / irate;
dst = src + m - 1;
idx = end;
do {
int o = REVOL(src[(int)((idx -= stp)>>14)]);
*dst = clip(o);
} while (--dst != src);
dst = src+m;
}
}
return dst;
}
static void filter_none(ym_t * const ym)
{
ym_puls_t * const puls = &ym->emu.puls;
const int n = (puls->tonptr - ym->outbuf);
if (n > 0) {
ym->outptr =
resampling(ym->outbuf, n, ym->clock>>3, ym->hz);
}
}
static void filter_boxcar2(ym_t * const ym)
{
ym_puls_t * const puls = &ym->emu.puls;
const int n = (puls->tonptr - ym->outbuf) >> 1;
if (n > 0) {
int m = n;
s32 * src = ym->outbuf, * dst = ym->outbuf;
do {
*dst++ = ( src[0] + src[1] ) >> 1;
src += 2;
} while (--m);
ym->outptr =
resampling(ym->outbuf, n, ym->clock>>(3+1), ym->hz);
}
}
static void filter_boxcar4(ym_t * const ym)
{
ym_puls_t * const puls = &ym->emu.puls;
const int n = (puls->tonptr - ym->outbuf) >> 2;
if (n > 0) {
int m = n;
s32 * src = ym->outbuf, * dst = ym->outbuf;
do {
*dst++ = ( src[0] + src[1] + src[2] + src[3] ) >> 2;
src += 4;
} while (--m);
ym->outptr =
resampling(ym->outbuf, n, ym->clock>>(3+2), ym->hz);
}
}
static void filter_boxcar(ym_t * const ym) {
if (ym->hz > (ym->clock >> (3+2)))
filter_boxcar2(ym);
else
filter_boxcar4(ym);
}
static void filter_mixed(ym_t * const ym)
{
ym_puls_t * const puls = &ym->emu.puls;
const int n = (puls->tonptr - ym->outbuf) >> 2;
if (n > 0) {
s32 * src = ym->outbuf, * dst = src;
int68_t h_i1 = puls->hipass_inp1;
int68_t h_o1 = puls->hipass_out1;
int68_t l_o1 = puls->lopass_out1;
int m = n;
do {
int68_t i0,o0;
i0 = ( src[0] + src[1] + src[2] + src[3] ) >> 2;
src += 4;
if (1) {
const int68_t B = 0x1a9c;
const int68_t A = (1<<15)-B;
l_o1 = ( (i0 * A) + l_o1 * B ) >> 15;
} else {
l_o1 = i0;
}
if (1) {
const int A0 = 0x7FD7;
const int B1 = 0x7FAE;
o0 = h_o1 = ( (l_o1 - h_i1) * A0 + (h_o1 * B1) ) >> 15;
h_i1 = l_o1;
} else {
o0 = i0;
}
*dst++ = o0;
} while (--m);
puls->hipass_inp1 = h_i1;
puls->hipass_out1 = h_o1;
puls->lopass_out1 = l_o1;
ym->outptr =
resampling(ym->outbuf, n, ym->clock>>(3+2), ym->hz);
}
}
static void filter_1pole(ym_t * const ym)
{
ym_puls_t * const puls = &ym->emu.puls;
const int n = puls->tonptr - ym->outbuf;
if (n > 0) {
s32 * src = ym->outbuf, * dst = src;
int68_t h_i1 = puls->hipass_inp1;
int68_t h_o1 = puls->hipass_out1;
int68_t l_o1 = puls->lopass_out1;
int m = n;
do {
int68_t i0,o0;
i0 = *src++;
{
const int68_t B = 0x7408;
const int68_t A = (1<<15)-B;
l_o1 = ( (i0 * A) + l_o1 * B ) >> 15;
}
{
const int68_t A0 = 0x7FF6;
const int68_t B1 = 0x7FEB;
o0 = h_o1 = ( (l_o1 - h_i1) * A0 + (h_o1 * B1) ) >> 15;
h_i1 = l_o1;
}
*dst++ = o0;
} while (--m);
puls->hipass_inp1 = h_i1;
puls->hipass_out1 = h_o1;
puls->lopass_out1 = l_o1;
ym->outptr =
resampling(ym->outbuf, n, ym->clock>>(3+0), ym->hz);
}
}
static void filter_2pole(ym_t * const ym)
{
ym_puls_t * const puls = &ym->emu.puls;
const int n = puls->tonptr - ym->outbuf;
if (n > 0) {
s32 * src = ym->outbuf, * dst = src;
int m = n;
int68_t h_i1 = puls->hipass_inp1;
int68_t h_o1 = puls->hipass_out1;
const int68_t a0 = puls->btw.a[0] >> 15;
const int68_t a1 = puls->btw.a[1] >> 15;
const int68_t a2 = puls->btw.a[2] >> 15;
const int68_t b0 = puls->btw.b[0] >> 15;
const int68_t b1 = puls->btw.b[1] >> 15;
int68_t x0 = puls->btw.x[0];
int68_t x1 = puls->btw.x[1];
int68_t y0 = puls->btw.y[0];
int68_t y1 = puls->btw.y[1];
do {
int68_t i0,o0;
i0 = *src++;
{
const int68_t A0 = 0x7FF6;
const int68_t B1 = 0x7FEB;
h_o1 = (((i0 - h_i1) * A0) + (h_o1 * B1)) >> 15;
h_i1 = i0;
i0 = h_o1;
}
{
o0 = (
a0 * i0 + a1 * x0 + a2 * x1 -
b0 * y0 - b1 * y1 ) >> 15;
x1 = x0; x0 = i0;
y1 = y0; y0 = o0;
}
*dst++ = o0;
} while (--m);
puls->btw.x[0] = x0;
puls->btw.x[1] = x1;
puls->btw.y[0] = y0;
puls->btw.y[1] = y1;
puls->hipass_inp1 = h_i1;
puls->hipass_out1 = h_o1;
ym->outptr =
resampling(ym->outbuf, n, ym->clock>>3, ym->hz);
}
}
static
int run(ym_t * const ym, s32 * output, const cycle68_t ymcycles)
{
ym->outbuf = ym->outptr = output;
do_noise(ym,ymcycles);
do_envelop(ym,ymcycles);
do_tone_and_mixer(ym,ymcycles);
ym->waccess = ym->static_waccess;
ym->waccess_nxt = ym->waccess;
filters[ym->emu.puls.ifilter].filter(ym);
return ym->outptr - ym->outbuf;
}
static
int buffersize(const ym_t * ym, const cycle68_t ymcycles)
{
return ((ymcycles+7u) >> 3);
}
static
void cleanup(ym_t * const ym)
{
}
int ym_puls_setup(ym_t * const ym)
{
ym_puls_t * const puls = &ym->emu.puls;
int err = 0;
ym->cb_cleanup = cleanup;
ym->cb_reset = reset;
ym->cb_run = run;
ym->cb_buffersize = buffersize;
ym->cb_sampling_rate = 0;
puls->ifilter = default_filter;
msg68_notice("ym-2149: filter -- *%s*\n", filters[puls->ifilter].name);
return err;
}
static const char prefix[] = "sc68-";
static const char engcat[] = "ym-puls";
static option68_t opts[] = {
{ option68_STR, prefix, "ym-filter", engcat,
"set ym-2149 filter [none|boxcar|mixed|1-pole|2-pole*]" },
};
int ym_puls_options(int argc, char ** argv)
{
option68_t * opt;
const int n_opts = sizeof(opts) / sizeof(*opts);
option68_append(opts, n_opts);
argc = option68_parse(argc,argv,0);
opt = option68_get("ym-filter",1);
if (opt) {
int i;
for (i=0; i<n_filters; ++i) {
if (!strcmp68(opt->val.str, filters[i].name)) {
default_filter = i;
break;
}
}
if (i == n_filters) {
msg68_warning("ym-2149: invalid filter -- *%s*\n", opt->val.str);
}
}
msg68_notice("ym-2149: default filter -- *%s* \n",
filters[default_filter].name);
return argc;
}