mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 09:35:32 -07:00
AdLib Gold: Everything now outputs to the same 48k source in order to avoid noise caused by the YM7128's resampling which is currently tailored to that frequency.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
/* fc=150Hz */
|
||||
static inline float
|
||||
adgold_highpass_iir(int c, int i, float NewSample)
|
||||
adgold_highpass_iir(int i, float NewSample)
|
||||
{
|
||||
float ACoef[NCoef + 1] = {
|
||||
0.98657437157334349000,
|
||||
@@ -19,76 +19,6 @@ adgold_highpass_iir(int c, int i, float NewSample)
|
||||
0.97261396931534050000
|
||||
};
|
||||
|
||||
static float y[2][2][NCoef + 1]; /* output samples */
|
||||
static float x[2][2][NCoef + 1]; /* input samples */
|
||||
int n;
|
||||
|
||||
/* shift the old samples */
|
||||
for (n = NCoef; n > 0; n--) {
|
||||
x[c][i][n] = x[c][i][n - 1];
|
||||
y[c][i][n] = y[c][i][n - 1];
|
||||
}
|
||||
|
||||
/* Calculate the new output */
|
||||
x[c][i][0] = NewSample;
|
||||
y[c][i][0] = ACoef[0] * x[c][i][0];
|
||||
for (n = 1; n <= NCoef; n++)
|
||||
y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n];
|
||||
|
||||
return y[c][i][0];
|
||||
}
|
||||
|
||||
/* fc=150Hz */
|
||||
static inline float
|
||||
adgold_lowpass_iir(int c, int i, float NewSample)
|
||||
{
|
||||
float ACoef[NCoef + 1] = {
|
||||
0.00009159473951071446,
|
||||
0.00018318947902142891,
|
||||
0.00009159473951071446
|
||||
};
|
||||
|
||||
float BCoef[NCoef + 1] = {
|
||||
1.00000000000000000000,
|
||||
-1.97223372919526560000,
|
||||
0.97261396931306277000
|
||||
};
|
||||
|
||||
static float y[2][2][NCoef + 1]; /* output samples */
|
||||
static float x[2][2][NCoef + 1]; /* input samples */
|
||||
int n;
|
||||
|
||||
/* shift the old samples */
|
||||
for (n = NCoef; n > 0; n--) {
|
||||
x[c][i][n] = x[c][i][n - 1];
|
||||
y[c][i][n] = y[c][i][n - 1];
|
||||
}
|
||||
|
||||
/* Calculate the new output */
|
||||
x[c][i][0] = NewSample;
|
||||
y[c][i][0] = ACoef[0] * x[c][i][0];
|
||||
for (n = 1; n <= NCoef; n++)
|
||||
y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n];
|
||||
|
||||
return y[c][i][0];
|
||||
}
|
||||
|
||||
/* fc=56Hz */
|
||||
static inline float
|
||||
adgold_pseudo_stereo_iir(int i, float NewSample)
|
||||
{
|
||||
float ACoef[NCoef + 1] = {
|
||||
0.00001409030866231767,
|
||||
0.00002818061732463533,
|
||||
0.00001409030866231767
|
||||
};
|
||||
|
||||
float BCoef[NCoef + 1] = {
|
||||
1.00000000000000000000,
|
||||
-1.98733021473466760000,
|
||||
0.98738361004063568000
|
||||
};
|
||||
|
||||
static float y[2][NCoef + 1]; /* output samples */
|
||||
static float x[2][NCoef + 1]; /* input samples */
|
||||
int n;
|
||||
@@ -108,6 +38,76 @@ adgold_pseudo_stereo_iir(int i, float NewSample)
|
||||
return y[i][0];
|
||||
}
|
||||
|
||||
/* fc=150Hz */
|
||||
static inline float
|
||||
adgold_lowpass_iir(int i, float NewSample)
|
||||
{
|
||||
float ACoef[NCoef + 1] = {
|
||||
0.00009159473951071446,
|
||||
0.00018318947902142891,
|
||||
0.00009159473951071446
|
||||
};
|
||||
|
||||
float BCoef[NCoef + 1] = {
|
||||
1.00000000000000000000,
|
||||
-1.97223372919526560000,
|
||||
0.97261396931306277000
|
||||
};
|
||||
|
||||
static float y[2][NCoef + 1]; /* output samples */
|
||||
static float x[2][NCoef + 1]; /* input samples */
|
||||
int n;
|
||||
|
||||
/* shift the old samples */
|
||||
for (n = NCoef; n > 0; n--) {
|
||||
x[i][n] = x[i][n - 1];
|
||||
y[i][n] = y[i][n - 1];
|
||||
}
|
||||
|
||||
/* Calculate the new output */
|
||||
x[i][0] = NewSample;
|
||||
y[i][0] = ACoef[0] * x[i][0];
|
||||
for (n = 1; n <= NCoef; n++)
|
||||
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
|
||||
|
||||
return y[i][0];
|
||||
}
|
||||
|
||||
/* fc=56Hz */
|
||||
static inline float
|
||||
adgold_pseudo_stereo_iir(float NewSample)
|
||||
{
|
||||
float ACoef[NCoef + 1] = {
|
||||
0.00001409030866231767,
|
||||
0.00002818061732463533,
|
||||
0.00001409030866231767
|
||||
};
|
||||
|
||||
float BCoef[NCoef + 1] = {
|
||||
1.00000000000000000000,
|
||||
-1.98733021473466760000,
|
||||
0.98738361004063568000
|
||||
};
|
||||
|
||||
static float y[NCoef + 1]; /* output samples */
|
||||
static float x[NCoef + 1]; /* input samples */
|
||||
int n;
|
||||
|
||||
/* shift the old samples */
|
||||
for (n = NCoef; n > 0; n--) {
|
||||
x[n] = x[n - 1];
|
||||
y[n] = y[n - 1];
|
||||
}
|
||||
|
||||
/* Calculate the new output */
|
||||
x[0] = NewSample;
|
||||
y[0] = ACoef[0] * x[0];
|
||||
for (n = 1; n <= NCoef; n++)
|
||||
y[0] += ACoef[n] * x[n] - BCoef[n] * y[n];
|
||||
|
||||
return y[0];
|
||||
}
|
||||
|
||||
/* fc=3.2kHz - probably incorrect */
|
||||
static inline float
|
||||
dss_iir(float NewSample)
|
||||
|
||||
@@ -49,6 +49,9 @@ enum fm_type {
|
||||
FM_MAX = 26
|
||||
};
|
||||
|
||||
#define FM_TYPE_MASK 255
|
||||
#define FM_FORCE_48K 256
|
||||
|
||||
enum fm_driver {
|
||||
FM_DRV_NUKED = 0,
|
||||
FM_DRV_YMFM = 1,
|
||||
@@ -65,9 +68,11 @@ typedef struct fm_drv_t {
|
||||
void (*generate)(void *priv, int32_t *data, uint32_t num_samples); /* daughterboard only. */
|
||||
} fm_drv_t;
|
||||
|
||||
extern uint8_t fm_driver_get_ex(int chip_id, fm_drv_t *drv, int is_48k);
|
||||
extern uint8_t fm_driver_get(int chip_id, fm_drv_t *drv);
|
||||
|
||||
extern const fm_drv_t nuked_opl_drv;
|
||||
extern const fm_drv_t nuked_opl_drv_48k;
|
||||
extern const fm_drv_t ymfm_drv;
|
||||
extern const fm_drv_t esfmu_opl_drv;
|
||||
extern const fm_drv_t ymfm_opl2board_drv;
|
||||
|
||||
@@ -147,7 +147,7 @@ struct _opl3_chip {
|
||||
typedef struct {
|
||||
opl3_chip opl;
|
||||
int8_t flags;
|
||||
int8_t pad;
|
||||
int8_t is_48k;
|
||||
|
||||
uint16_t port;
|
||||
uint8_t status;
|
||||
@@ -159,6 +159,8 @@ typedef struct {
|
||||
|
||||
int pos;
|
||||
int32_t buffer[MUSICBUFLEN * 2];
|
||||
|
||||
int32_t *(*update)(void *priv);
|
||||
} nuked_drv_t;
|
||||
|
||||
enum {
|
||||
|
||||
@@ -19,18 +19,18 @@ typedef struct ym7128_t {
|
||||
int c1;
|
||||
int t[9];
|
||||
|
||||
int16_t filter_dat[2];
|
||||
int16_t prev_l[2];
|
||||
int16_t prev_r[2];
|
||||
int16_t filter_dat;
|
||||
int16_t prev_l;
|
||||
int16_t prev_r;
|
||||
|
||||
int16_t delay_buffer[2][2400];
|
||||
int delay_pos[2];
|
||||
int16_t delay_buffer[2400];
|
||||
int delay_pos;
|
||||
|
||||
int16_t last_samp;
|
||||
} ym7128_t;
|
||||
|
||||
void ym7128_init(ym7128_t *ym7128);
|
||||
void ym7128_write(ym7128_t *ym7128, uint8_t val);
|
||||
void ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int i, int len);
|
||||
void ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len);
|
||||
|
||||
#endif /*SOUND_YM7128_H*/
|
||||
|
||||
@@ -82,8 +82,6 @@ typedef struct adgold_t {
|
||||
int treble;
|
||||
int bass;
|
||||
|
||||
int16_t samp_buffer[SOUNDBUFLEN * 2];
|
||||
int16_t opl_buffer[MUSICBUFLEN * 2];
|
||||
int16_t mma_buffer[2][SOUNDBUFLEN];
|
||||
|
||||
int pos;
|
||||
@@ -779,30 +777,37 @@ static void
|
||||
adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
{
|
||||
adgold_t *adgold = (adgold_t *) priv;
|
||||
int16_t *adgold_buffer = malloc(sizeof(int16_t) * len * 2);
|
||||
if (adgold_buffer == NULL)
|
||||
fatal("adgold_buffer = NULL");
|
||||
|
||||
int c;
|
||||
|
||||
int32_t *opl_buf = adgold->opl.update(adgold->opl.priv);
|
||||
adgold_update(adgold);
|
||||
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
adgold->samp_buffer[c] = ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4;
|
||||
adgold->samp_buffer[c + 1] = ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4;
|
||||
adgold_buffer[c] = ((opl_buf[c] * adgold->fm_vol_l) >> 7) / 2;
|
||||
adgold_buffer[c] += ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4;
|
||||
adgold_buffer[c + 1] = ((opl_buf[c + 1] * adgold->fm_vol_r) >> 7) / 2;
|
||||
adgold_buffer[c + 1] += ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4;
|
||||
}
|
||||
|
||||
if (adgold->surround_enabled)
|
||||
ym7128_apply(&adgold->ym7128, adgold->samp_buffer, 0, len);
|
||||
ym7128_apply(&adgold->ym7128, adgold_buffer, len);
|
||||
|
||||
switch (adgold->adgold_38x_regs[0x8] & 6) {
|
||||
case 0:
|
||||
for (c = 0; c < len * 2; c++)
|
||||
adgold->samp_buffer[c] = 0;
|
||||
adgold_buffer[c] = 0;
|
||||
break;
|
||||
case 2: /*Left channel only*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold->samp_buffer[c + 1] = adgold->samp_buffer[c];
|
||||
adgold_buffer[c + 1] = adgold_buffer[c];
|
||||
break;
|
||||
case 4: /*Right channel only*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold->samp_buffer[c] = adgold->samp_buffer[c + 1];
|
||||
adgold_buffer[c] = adgold_buffer[c + 1];
|
||||
break;
|
||||
case 6: /*Left and right channels*/
|
||||
break;
|
||||
@@ -814,7 +819,7 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
switch (adgold->adgold_38x_regs[0x8] & 0x18) {
|
||||
case 0x00: /*Forced mono*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold->samp_buffer[c] = adgold->samp_buffer[c + 1] = ((int32_t) adgold->samp_buffer[c] + (int32_t) adgold->samp_buffer[c + 1]) / 2;
|
||||
adgold_buffer[c] = adgold_buffer[c + 1] = ((int32_t) adgold_buffer[c] + (int32_t) adgold_buffer[c + 1]) / 2;
|
||||
break;
|
||||
case 0x08: /*Linear stereo*/
|
||||
break;
|
||||
@@ -822,17 +827,17 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
/*Filter left channel, leave right channel unchanged*/
|
||||
/*Filter cutoff is largely a guess*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold->samp_buffer[c] += adgold_pseudo_stereo_iir(0, adgold->samp_buffer[c]);
|
||||
adgold_buffer[c] += adgold_pseudo_stereo_iir(adgold_buffer[c]);
|
||||
break;
|
||||
case 0x18: /*Spatial stereo*/
|
||||
/*Quite probably wrong, I only have the diagram in the TDA8425 datasheet
|
||||
and a very vague understanding of how op-amps work to go on*/
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
int16_t l = adgold->samp_buffer[c];
|
||||
int16_t r = adgold->samp_buffer[c + 1];
|
||||
int16_t l = adgold_buffer[c];
|
||||
int16_t r = adgold_buffer[c + 1];
|
||||
|
||||
adgold->samp_buffer[c] += (r / 3) + ((l * 2) / 3);
|
||||
adgold->samp_buffer[c + 1] += (l / 3) + ((r * 2) / 3);
|
||||
adgold_buffer[c] += (r / 3) + ((l * 2) / 3);
|
||||
adgold_buffer[c + 1] += (l / 3) + ((r * 2) / 3);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -846,9 +851,9 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
int32_t highpass;
|
||||
|
||||
/*Output is deliberately halved to avoid clipping*/
|
||||
temp = ((int32_t) adgold->samp_buffer[c] * adgold->vol_l) >> 17;
|
||||
lowpass = adgold_lowpass_iir(0, 0, temp);
|
||||
highpass = adgold_highpass_iir(0, 0, temp);
|
||||
temp = ((int32_t) adgold_buffer[c] * adgold->vol_l) >> 17;
|
||||
lowpass = adgold_lowpass_iir(0, temp);
|
||||
highpass = adgold_highpass_iir(0, temp);
|
||||
if (adgold->bass > 6)
|
||||
temp += (lowpass * bass_attenuation[adgold->bass]) >> 14;
|
||||
else if (adgold->bass < 6)
|
||||
@@ -863,118 +868,9 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
temp = 32767;
|
||||
buffer[c] += temp;
|
||||
|
||||
temp = ((int32_t) adgold->samp_buffer[c + 1] * adgold->vol_r) >> 17;
|
||||
lowpass = adgold_lowpass_iir(0, 1, temp);
|
||||
highpass = adgold_highpass_iir(0, 1, temp);
|
||||
if (adgold->bass > 6)
|
||||
temp += (lowpass * bass_attenuation[adgold->bass]) >> 14;
|
||||
else if (adgold->bass < 6)
|
||||
temp = highpass + ((temp * bass_cut[adgold->bass]) >> 14);
|
||||
if (adgold->treble > 6)
|
||||
temp += (highpass * treble_attenuation[adgold->treble]) >> 14;
|
||||
else if (adgold->treble < 6)
|
||||
temp = lowpass + ((temp * treble_cut[adgold->treble]) >> 14);
|
||||
if (temp < -32768)
|
||||
temp = -32768;
|
||||
if (temp > 32767)
|
||||
temp = 32767;
|
||||
buffer[c + 1] += temp;
|
||||
}
|
||||
|
||||
adgold->pos = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
adgold_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||
{
|
||||
adgold_t *adgold = (adgold_t *) priv;
|
||||
int c;
|
||||
|
||||
const int32_t *opl_buf = adgold->opl.update(adgold->opl.priv);
|
||||
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
adgold->opl_buffer[c] = ((opl_buf[c] * adgold->fm_vol_l) >> 7) / 2;
|
||||
adgold->opl_buffer[c + 1] = ((opl_buf[c + 1] * adgold->fm_vol_r) >> 7) / 2;
|
||||
}
|
||||
|
||||
if (adgold->surround_enabled)
|
||||
ym7128_apply(&adgold->ym7128, adgold->opl_buffer, 1, len);
|
||||
|
||||
switch (adgold->adgold_38x_regs[0x8] & 6) {
|
||||
case 0:
|
||||
for (c = 0; c < len * 2; c++)
|
||||
adgold->opl_buffer[c] = 0;
|
||||
break;
|
||||
case 2: /*Left channel only*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold->opl_buffer[c + 1] = adgold->opl_buffer[c];
|
||||
break;
|
||||
case 4: /*Right channel only*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold->opl_buffer[c] = adgold->opl_buffer[c + 1];
|
||||
break;
|
||||
case 6: /*Left and right channels*/
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (adgold->adgold_38x_regs[0x8] & 0x18) {
|
||||
case 0x00: /*Forced mono*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold->opl_buffer[c] = adgold->opl_buffer[c + 1] = ((int32_t) adgold->opl_buffer[c] + (int32_t) adgold->opl_buffer[c + 1]) / 2;
|
||||
break;
|
||||
case 0x08: /*Linear stereo*/
|
||||
break;
|
||||
case 0x10: /*Pseudo stereo*/
|
||||
/*Filter left channel, leave right channel unchanged*/
|
||||
/*Filter cutoff is largely a guess*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold->opl_buffer[c] += adgold_pseudo_stereo_iir(1, adgold->opl_buffer[c]);
|
||||
break;
|
||||
case 0x18: /*Spatial stereo*/
|
||||
/*Quite probably wrong, I only have the diagram in the TDA8425 datasheet
|
||||
and a very vague understanding of how op-amps work to go on*/
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
int16_t l = adgold->opl_buffer[c];
|
||||
int16_t r = adgold->opl_buffer[c + 1];
|
||||
|
||||
adgold->opl_buffer[c] += (r / 3) + ((l * 2) / 3);
|
||||
adgold->opl_buffer[c + 1] += (l / 3) + ((r * 2) / 3);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
int32_t temp;
|
||||
int32_t lowpass;
|
||||
int32_t highpass;
|
||||
|
||||
/*Output is deliberately halved to avoid clipping*/
|
||||
temp = ((int32_t) adgold->opl_buffer[c] * adgold->vol_l) >> 17;
|
||||
lowpass = adgold_lowpass_iir(1, 0, temp);
|
||||
highpass = adgold_highpass_iir(1, 0, temp);
|
||||
if (adgold->bass > 6)
|
||||
temp += (lowpass * bass_attenuation[adgold->bass]) >> 14;
|
||||
else if (adgold->bass < 6)
|
||||
temp = highpass + ((temp * bass_cut[adgold->bass]) >> 14);
|
||||
if (adgold->treble > 6)
|
||||
temp += (highpass * treble_attenuation[adgold->treble]) >> 14;
|
||||
else if (adgold->treble < 6)
|
||||
temp = lowpass + ((temp * treble_cut[adgold->treble]) >> 14);
|
||||
if (temp < -32768)
|
||||
temp = -32768;
|
||||
if (temp > 32767)
|
||||
temp = 32767;
|
||||
buffer[c] += temp;
|
||||
|
||||
temp = ((int32_t) adgold->opl_buffer[c + 1] * adgold->vol_r) >> 17;
|
||||
lowpass = adgold_lowpass_iir(1, 1, temp);
|
||||
highpass = adgold_highpass_iir(1, 1, temp);
|
||||
temp = ((int32_t) adgold_buffer[c + 1] * adgold->vol_r) >> 17;
|
||||
lowpass = adgold_lowpass_iir(1, temp);
|
||||
highpass = adgold_highpass_iir(1, temp);
|
||||
if (adgold->bass > 6)
|
||||
temp += (lowpass * bass_attenuation[adgold->bass]) >> 14;
|
||||
else if (adgold->bass < 6)
|
||||
@@ -991,6 +887,9 @@ adgold_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||
}
|
||||
|
||||
adgold->opl.reset_buffer(adgold->opl.priv);
|
||||
adgold->pos = 0;
|
||||
|
||||
free(adgold_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1058,7 +957,7 @@ adgold_init(UNUSED(const device_t *info))
|
||||
adgold->surround_enabled = device_get_config_int("surround");
|
||||
adgold->gameport_enabled = device_get_config_int("gameport");
|
||||
|
||||
fm_driver_get(FM_YMF289B, &adgold->opl);
|
||||
fm_driver_get_ex(FM_YMF262, &adgold->opl, 1);
|
||||
if (adgold->surround_enabled)
|
||||
ym7128_init(&adgold->ym7128);
|
||||
|
||||
@@ -1149,7 +1048,6 @@ adgold_init(UNUSED(const device_t *info))
|
||||
timer_add(&adgold->adgold_mma_timer_count, adgold_timer_poll, adgold, 1);
|
||||
|
||||
sound_add_handler(adgold_get_buffer, adgold);
|
||||
music_add_handler(adgold_get_music_buffer, adgold);
|
||||
|
||||
sound_set_cd_audio_filter(adgold_filter_cd_audio, adgold);
|
||||
|
||||
|
||||
@@ -36,150 +36,152 @@
|
||||
static uint32_t fm_dev_inst[FM_DRV_MAX][FM_MAX];
|
||||
|
||||
uint8_t
|
||||
fm_driver_get(int chip_id, fm_drv_t *drv)
|
||||
fm_driver_get_ex(int chip_id, fm_drv_t *drv, int is_48k)
|
||||
{
|
||||
void *flag_48k = is_48k ? ((void *) FM_FORCE_48K) : NULL;
|
||||
|
||||
switch (chip_id) {
|
||||
case FM_YM2149: /* SSG */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2149_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2149_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM3526: /* OPL */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym3526_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym3526_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_Y8950: /* MSX-Audio (OPL with ADPCM) */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&y8950_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&y8950_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM3812: /* OPL2 */
|
||||
if (fm_driver == FM_DRV_NUKED) {
|
||||
*drv = nuked_opl_drv;
|
||||
drv->priv = device_add_inst(&ym3812_nuked_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
*drv = is_48k ? nuked_opl_drv_48k : nuked_opl_drv;
|
||||
drv->priv = device_add_inst_params(&ym3812_nuked_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
} else {
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym3812_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym3812_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
}
|
||||
break;
|
||||
|
||||
case FM_YMF262: /* OPL3 */
|
||||
if (fm_driver == FM_DRV_NUKED) {
|
||||
*drv = nuked_opl_drv;
|
||||
drv->priv = device_add_inst(&ymf262_nuked_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
*drv = is_48k ? nuked_opl_drv_48k : nuked_opl_drv;
|
||||
drv->priv = device_add_inst_params(&ymf262_nuked_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
} else {
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ymf262_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ymf262_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
}
|
||||
break;
|
||||
|
||||
case FM_YMF289B: /* OPL3-L */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ymf289b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ymf289b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF278B: /* OPL4 */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ymf278b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ymf278b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2413: /* OPLL */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2413_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2413_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2423: /* OPLL-X */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2423_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2423_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF281: /* OPLLP */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ymf281_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ymf281_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_DS1001: /* Konami VRC7 MMC */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ds1001_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ds1001_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2151: /* OPM */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2151_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2151_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2203: /* OPN */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2203_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2203_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2608: /* OPNA */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2608_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2608_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF288: /* OPN3L */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ymf288_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ymf288_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2610: /* OPNB */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2610_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2610_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2610B: /* OPNB2 */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2610b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2610b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2612: /* OPN2 */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2612_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2612_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM3438: /* OPN2C */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym3438_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym3438_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF276: /* OPN2L */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ymf276_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ymf276_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2164: /* OPP */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2164_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2164_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_YM3806: /* OPQ */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym3806_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym3806_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case FM_YMF271: /* OPX */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ymf271_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ymf271_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FM_YM2414: /* OPZ */
|
||||
*drv = ymfm_drv;
|
||||
drv->priv = device_add_inst(&ym2414_ymfm_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym2414_ymfm_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
case FM_ESFM:
|
||||
*drv = esfmu_opl_drv;
|
||||
drv->priv = device_add_inst(&esfm_esfmu_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&esfm_esfmu_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
|
||||
#ifdef USE_LIBSERIALPORT
|
||||
case FM_OPL2BOARD:
|
||||
*drv = ymfm_opl2board_drv;
|
||||
drv->priv = device_add_inst(&ym_opl2board_device, fm_dev_inst[fm_driver][chip_id]++);
|
||||
drv->priv = device_add_inst_params(&ym_opl2board_device, fm_dev_inst[fm_driver][chip_id]++, flag_48k);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -189,3 +191,9 @@ fm_driver_get(int chip_id, fm_drv_t *drv)
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
uint8_t
|
||||
fm_driver_get(int chip_id, fm_drv_t *drv)
|
||||
{
|
||||
return fm_driver_get_ex(chip_id, drv, 0);
|
||||
}
|
||||
|
||||
@@ -1460,6 +1460,15 @@ OPL3_GenerateStream(opl3_chip *chip, int32_t *sndptr, uint32_t numsamples)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OPL3_GenerateResampledStream(opl3_chip *chip, int32_t *sndptr, uint32_t numsamples)
|
||||
{
|
||||
for (uint_fast32_t i = 0; i < numsamples; i++) {
|
||||
OPL3_GenerateResampled(chip, sndptr);
|
||||
sndptr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nuked_timer_tick(nuked_drv_t *dev, int tmr)
|
||||
{
|
||||
@@ -1525,32 +1534,6 @@ nuked_drv_set_do_cycles(void *priv, int8_t do_cycles)
|
||||
dev->flags &= ~FLAG_CYCLES;
|
||||
}
|
||||
|
||||
static void *
|
||||
nuked_drv_init(const device_t *info)
|
||||
{
|
||||
nuked_drv_t *dev = (nuked_drv_t *) calloc(1, sizeof(nuked_drv_t));
|
||||
dev->flags = FLAG_CYCLES;
|
||||
if (info->local == FM_YMF262)
|
||||
dev->flags |= FLAG_OPL3;
|
||||
else
|
||||
dev->status = 0x06;
|
||||
|
||||
/* Initialize the NukedOPL object. */
|
||||
OPL3_Reset(&dev->opl, FREQ_49716);
|
||||
|
||||
timer_add(&dev->timers[0], nuked_timer_1, dev, 0);
|
||||
timer_add(&dev->timers[1], nuked_timer_2, dev, 0);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void
|
||||
nuked_drv_close(void *priv)
|
||||
{
|
||||
nuked_drv_t *dev = (nuked_drv_t *) priv;
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static int32_t *
|
||||
nuked_drv_update(void *priv)
|
||||
{
|
||||
@@ -1560,8 +1543,8 @@ nuked_drv_update(void *priv)
|
||||
return dev->buffer;
|
||||
|
||||
OPL3_GenerateStream(&dev->opl,
|
||||
&dev->buffer[dev->pos * 2],
|
||||
music_pos_global - dev->pos);
|
||||
&dev->buffer[dev->pos * 2],
|
||||
music_pos_global - dev->pos);
|
||||
|
||||
for (; dev->pos < music_pos_global; dev->pos++) {
|
||||
dev->buffer[dev->pos * 2] /= 2;
|
||||
@@ -1571,6 +1554,26 @@ nuked_drv_update(void *priv)
|
||||
return dev->buffer;
|
||||
}
|
||||
|
||||
static int32_t *
|
||||
nuked_drv_update_48k(void *priv)
|
||||
{
|
||||
nuked_drv_t *dev = (nuked_drv_t *) priv;
|
||||
|
||||
if (dev->pos >= sound_pos_global)
|
||||
return dev->buffer;
|
||||
|
||||
OPL3_GenerateResampledStream(&dev->opl,
|
||||
&dev->buffer[dev->pos * 2],
|
||||
sound_pos_global - dev->pos);
|
||||
|
||||
for (; dev->pos < sound_pos_global; dev->pos++) {
|
||||
dev->buffer[dev->pos * 2] /= 2;
|
||||
dev->buffer[(dev->pos * 2) + 1] /= 2;
|
||||
}
|
||||
|
||||
return dev->buffer;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
nuked_drv_read(uint16_t port, void *priv)
|
||||
{
|
||||
@@ -1579,7 +1582,7 @@ nuked_drv_read(uint16_t port, void *priv)
|
||||
if (dev->flags & FLAG_CYCLES)
|
||||
cycles -= ((int) (isa_timing * 8));
|
||||
|
||||
nuked_drv_update(dev);
|
||||
dev->update(dev);
|
||||
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
@@ -1598,7 +1601,8 @@ static void
|
||||
nuked_drv_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
nuked_drv_t *dev = (nuked_drv_t *) priv;
|
||||
nuked_drv_update(dev);
|
||||
|
||||
dev->update(dev);
|
||||
|
||||
if ((port & 0x0001) == 0x0001) {
|
||||
OPL3_WriteRegBuffered(&dev->opl, dev->port, val);
|
||||
@@ -1649,6 +1653,40 @@ nuked_drv_reset_buffer(void *priv)
|
||||
dev->pos = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nuked_drv_close(void *priv)
|
||||
{
|
||||
nuked_drv_t *dev = (nuked_drv_t *) priv;
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
nuked_drv_init(const device_t *info)
|
||||
{
|
||||
nuked_drv_t *dev = (nuked_drv_t *) calloc(1, sizeof(nuked_drv_t));
|
||||
dev->flags = FLAG_CYCLES;
|
||||
if ((info->local & FM_TYPE_MASK) == FM_YMF262)
|
||||
dev->flags |= FLAG_OPL3;
|
||||
else
|
||||
dev->status = 0x06;
|
||||
|
||||
dev->is_48k = !!(info->local & FM_FORCE_48K);
|
||||
|
||||
/* Initialize the NukedOPL object. */
|
||||
if (dev->is_48k) {
|
||||
dev->update = nuked_drv_update_48k;
|
||||
OPL3_Reset(&dev->opl, FREQ_48000);
|
||||
} else {
|
||||
dev->update = nuked_drv_update;
|
||||
OPL3_Reset(&dev->opl, FREQ_49716);
|
||||
}
|
||||
|
||||
timer_add(&dev->timers[0], nuked_timer_1, dev, 0);
|
||||
timer_add(&dev->timers[1], nuked_timer_2, dev, 0);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t ym3812_nuked_device = {
|
||||
.name = "Yamaha YM3812 OPL2 (NUKED)",
|
||||
.internal_name = "ym3812_nuked",
|
||||
@@ -1686,3 +1724,13 @@ const fm_drv_t nuked_opl_drv = {
|
||||
.priv = NULL,
|
||||
.generate = NULL,
|
||||
};
|
||||
|
||||
const fm_drv_t nuked_opl_drv_48k = {
|
||||
.read = &nuked_drv_read,
|
||||
.write = &nuked_drv_write,
|
||||
.update = &nuked_drv_update_48k,
|
||||
.reset_buffer = &nuked_drv_reset_buffer,
|
||||
.set_do_cycles = &nuked_drv_set_do_cycles,
|
||||
.priv = NULL,
|
||||
.generate = NULL,
|
||||
};
|
||||
|
||||
@@ -56,11 +56,12 @@ enum {
|
||||
|
||||
class YMFMChipBase {
|
||||
public:
|
||||
YMFMChipBase(UNUSED(uint32_t clock), fm_type type, uint32_t samplerate)
|
||||
YMFMChipBase(UNUSED(uint32_t clock), fm_type type, uint32_t samplerate, int is_48k)
|
||||
: m_buf_pos(0)
|
||||
, m_flags(0)
|
||||
, m_type(type)
|
||||
, m_samplerate(samplerate)
|
||||
, m_48k(is_48k)
|
||||
{
|
||||
memset(m_buffer, 0, sizeof(m_buffer));
|
||||
}
|
||||
@@ -74,11 +75,13 @@ public:
|
||||
void set_do_cycles(int8_t do_cycles) { do_cycles ? m_flags |= FLAG_CYCLES : m_flags &= ~FLAG_CYCLES; }
|
||||
int32_t *buffer() const { return (int32_t *) m_buffer; }
|
||||
void reset_buffer() { m_buf_pos = 0; }
|
||||
int is_48k() const { return m_48k; }
|
||||
|
||||
virtual uint32_t sample_rate() const = 0;
|
||||
|
||||
virtual void write(uint16_t addr, uint8_t data) = 0;
|
||||
virtual void generate(int32_t *data, uint32_t num_samples) = 0;
|
||||
virtual void generate_resampled(int32_t *data, uint32_t num_samples) = 0;
|
||||
virtual int32_t *update() = 0;
|
||||
virtual uint8_t read(uint16_t addr) = 0;
|
||||
virtual void set_clock(uint32_t clock) = 0;
|
||||
@@ -90,17 +93,19 @@ protected:
|
||||
int8_t m_flags;
|
||||
fm_type m_type;
|
||||
uint32_t m_samplerate;
|
||||
int m_48k;
|
||||
};
|
||||
|
||||
template <typename ChipType>
|
||||
class YMFMChip : public YMFMChipBase, public ymfm::ymfm_interface {
|
||||
public:
|
||||
YMFMChip(uint32_t clock, fm_type type, uint32_t samplerate)
|
||||
: YMFMChipBase(clock, type, samplerate)
|
||||
YMFMChip(uint32_t clock, fm_type type, uint32_t samplerate, int m_48k)
|
||||
: YMFMChipBase(clock, type, samplerate, m_48k)
|
||||
, m_chip(*this)
|
||||
, m_clock(clock)
|
||||
, m_samplerate(samplerate)
|
||||
, m_samplecnt(0)
|
||||
, m_48k(0)
|
||||
{
|
||||
memset(m_samples, 0, sizeof(m_samples));
|
||||
memset(m_oldsamples, 0, sizeof(m_oldsamples));
|
||||
@@ -109,7 +114,10 @@ public:
|
||||
m_subtract[0] = 80.0;
|
||||
m_subtract[1] = 320.0;
|
||||
m_type = type;
|
||||
m_buf_pos_global = (samplerate == FREQ_49716) ? &music_pos_global : &wavetable_pos_global;
|
||||
if (m_48k)
|
||||
m_buf_pos_global = &sound_pos_global;
|
||||
else
|
||||
m_buf_pos_global = (samplerate == FREQ_49716) ? &music_pos_global : &wavetable_pos_global;
|
||||
|
||||
if (m_type == FM_YMF278B) {
|
||||
if (rom_load_linear("roms/sound/yamaha/yrw801.rom", 0, 0x200000, 0, m_yrw801) == 0) {
|
||||
@@ -176,14 +184,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
virtual void generate_resampled(int32_t *data, uint32_t num_samples) override
|
||||
{
|
||||
if ((m_samplerate == FREQ_49716) || (m_samplerate == FREQ_44100)) {
|
||||
generate(data, num_samples);
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < num_samples; i++) {
|
||||
while (m_samplecnt >= m_rateratio) {
|
||||
m_oldsamples[0] = m_samples[0];
|
||||
@@ -217,14 +219,16 @@ public:
|
||||
m_samplecnt += 1 << RSM_FRAC;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual int32_t *update() override
|
||||
{
|
||||
if (m_buf_pos >= *m_buf_pos_global)
|
||||
return m_buffer;
|
||||
|
||||
generate(&m_buffer[m_buf_pos * 2], *m_buf_pos_global - m_buf_pos);
|
||||
if (m_48k)
|
||||
generate_resampled(&m_buffer[m_buf_pos * 2], *m_buf_pos_global - m_buf_pos);
|
||||
else
|
||||
generate(&m_buffer[m_buf_pos * 2], *m_buf_pos_global - m_buf_pos);
|
||||
|
||||
for (; m_buf_pos < *m_buf_pos_global; m_buf_pos++) {
|
||||
m_buffer[m_buf_pos * 2] /= 2;
|
||||
@@ -287,6 +291,8 @@ private:
|
||||
int32_t m_samplecnt;
|
||||
int32_t m_oldsamples[2];
|
||||
int32_t m_samples[2];
|
||||
|
||||
int m_48k;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
@@ -325,127 +331,128 @@ static void *
|
||||
ymfm_drv_init(const device_t *info)
|
||||
{
|
||||
YMFMChipBase *fm;
|
||||
int is_48k = !!(info->local & FM_FORCE_48K);
|
||||
|
||||
switch (info->local) {
|
||||
switch (info->local & FM_TYPE_MASK) {
|
||||
case FM_YM2149: /* OPL */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2149>(14318181, FM_YM2149, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2149>(14318181, FM_YM2149, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM3526: /* OPL */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym3526>(14318181, FM_YM3526, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym3526>(14318181, FM_YM3526, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_Y8950: /* MSX-Audio (OPL with ADPCM) */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::y8950>(14318181, FM_Y8950, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::y8950>(14318181, FM_Y8950, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
default:
|
||||
case FM_YM3812: /* OPL2 */
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym3812>(3579545, FM_YM3812, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym3812>(3579545, FM_YM3812, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF262: /* OPL3 */
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf262>(14318181, FM_YMF262, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf262>(14318181, FM_YMF262, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF289B: /* OPL3-L */
|
||||
/* According to the datasheet, we should be using 33868800, but YMFM appears
|
||||
to cheat and does it using the same values as the YMF262. */
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf289b>(14318181, FM_YMF289B, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf289b>(14318181, FM_YMF289B, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF278B: /* OPL4 */
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf278b>(33868800, FM_YMF278B, FREQ_44100);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf278b>(33868800, FM_YMF278B, FREQ_44100, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2413: /* OPLL */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2413>(14318181, FM_YM2413, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2413>(14318181, FM_YM2413, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2423: /* OPLL-X */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2423>(14318181, FM_YM2423, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2423>(14318181, FM_YM2423, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF281: /* OPLLP */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf281>(14318181, FM_YMF281, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf281>(14318181, FM_YMF281, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_DS1001: /* Konami VRC7 MMC */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ds1001>(14318181, FM_DS1001, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ds1001>(14318181, FM_DS1001, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2151: /* OPM */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2151>(14318181, FM_YM2151, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2151>(14318181, FM_YM2151, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2203: /* OPN */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2203>(14318181, FM_YM2203, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2203>(14318181, FM_YM2203, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2608: /* OPNA */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2608>(14318181, FM_YM2608, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2608>(14318181, FM_YM2608, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF288: /* OPN3L */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf288>(14318181, FM_YMF288, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf288>(14318181, FM_YMF288, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2610: /* OPNB */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2610>(14318181, FM_YM2610, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2610>(14318181, FM_YM2610, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2610B: /* OPNB2 */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2610b>(14318181, FM_YM2610B, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2610b>(14318181, FM_YM2610B, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2612: /* OPN2 */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2612>(14318181, FM_YM2612, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2612>(14318181, FM_YM2612, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM3438: /* OPN2C */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym3438>(14318181, FM_YM3438, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym3438>(14318181, FM_YM3438, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YMF276: /* OPN2L */
|
||||
// TODO: Check function call, rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf276>(14318181, FM_YMF276, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf276>(14318181, FM_YMF276, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM2164: /* OPP */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2164>(14318181, FM_YM2164, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2164>(14318181, FM_YM2164, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
case FM_YM3806: /* OPQ */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym3806>(14318181, FM_YM3806, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym3806>(14318181, FM_YM3806, FREQ_49716, is_48k);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case FM_YMF271: /* OPX */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf271>(14318181, FM_YMF271, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ymf271>(14318181, FM_YMF271, FREQ_49716, is_48k);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FM_YM2414: /* OPZ */
|
||||
// TODO: Check rates and frequency
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2414>(14318181, FM_YM2414, FREQ_49716);
|
||||
fm = (YMFMChipBase *) new YMFMChip<ymfm::ym2414>(14318181, FM_YM2414, FREQ_49716, is_48k);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -523,8 +530,10 @@ ymfm_drv_generate(void *priv, int32_t *data, uint32_t num_samples)
|
||||
{
|
||||
YMFMChipBase *drv = (YMFMChipBase *) priv;
|
||||
|
||||
// drv->generate_resampled(data, num_samples);
|
||||
drv->generate(data, num_samples);
|
||||
if (drv->is_48k())
|
||||
drv->generate_resampled(data, num_samples);
|
||||
else
|
||||
drv->generate(data, num_samples);
|
||||
}
|
||||
|
||||
const device_t ym2149_ymfm_device = {
|
||||
|
||||
@@ -111,10 +111,10 @@ ym7128_write(ym7128_t *ym7128, uint8_t val)
|
||||
ym7128->a0 = new_a0;
|
||||
}
|
||||
|
||||
#define GET_DELAY_SAMPLE(ym7128, offset) (((ym7128->delay_pos[i] - offset) < 0) ? ym7128->delay_buffer[i][(ym7128->delay_pos[i] - offset) + 2400] : ym7128->delay_buffer[i][ym7128->delay_pos[i] - offset])
|
||||
#define GET_DELAY_SAMPLE(ym7128, offset) (((ym7128->delay_pos - offset) < 0) ? ym7128->delay_buffer[(ym7128->delay_pos - offset) + 2400] : ym7128->delay_buffer[ym7128->delay_pos - offset])
|
||||
|
||||
void
|
||||
ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int i, int len)
|
||||
ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len)
|
||||
{
|
||||
for (int c = 0; c < len * 2; c += 4) {
|
||||
/*YM7128 samples a mono stream at ~24 kHz, so downsample*/
|
||||
@@ -125,13 +125,13 @@ ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int i, int len)
|
||||
int32_t samp_r = 0;
|
||||
|
||||
filter_temp = GET_DELAY_SAMPLE(ym7128, ym7128->t[0]);
|
||||
filter_out = ((filter_temp * ym7128->c0) >> 11) + ((ym7128->filter_dat[i] * ym7128->c1) >> 11);
|
||||
filter_out = ((filter_temp * ym7128->c0) >> 11) + ((ym7128->filter_dat * ym7128->c1) >> 11);
|
||||
filter_out = (filter_out * ym7128->vc) >> 16;
|
||||
|
||||
samp = (samp * ym7128->vm) >> 16;
|
||||
samp += filter_out;
|
||||
|
||||
ym7128->delay_buffer[i][ym7128->delay_pos[i]] = samp;
|
||||
ym7128->delay_buffer[ym7128->delay_pos] = samp;
|
||||
|
||||
for (uint8_t d = 0; d < 8; d++) {
|
||||
samp_l += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d + 1]) * ym7128->gl[d]) >> 16;
|
||||
@@ -141,17 +141,17 @@ ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int i, int len)
|
||||
samp_l = (samp_l * ym7128->vl * 2) >> 16;
|
||||
samp_r = (samp_r * ym7128->vr * 2) >> 16;
|
||||
|
||||
buffer[c] += (samp_l + (int32_t) ym7128->prev_l[i]) / 2;
|
||||
buffer[c + 1] += (samp_r + (int32_t) ym7128->prev_r[i]) / 2;
|
||||
buffer[c] += (samp_l + (int32_t) ym7128->prev_l) / 2;
|
||||
buffer[c + 1] += (samp_r + (int32_t) ym7128->prev_r) / 2;
|
||||
buffer[c + 2] += samp_l;
|
||||
buffer[c + 3] += samp_r;
|
||||
|
||||
ym7128->delay_pos[i]++;
|
||||
if (ym7128->delay_pos[i] >= 2400)
|
||||
ym7128->delay_pos[i] = 0;
|
||||
ym7128->delay_pos++;
|
||||
if (ym7128->delay_pos >= 2400)
|
||||
ym7128->delay_pos = 0;
|
||||
|
||||
ym7128->filter_dat[i] = filter_temp;
|
||||
ym7128->prev_l[i] = samp_l;
|
||||
ym7128->prev_r[i] = samp_r;
|
||||
ym7128->filter_dat = filter_temp;
|
||||
ym7128->prev_l = samp_l;
|
||||
ym7128->prev_r = samp_r;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user