AY: this sucks, part 1
This commit is contained in:
parent
cb67527103
commit
9681f25e54
|
@ -248,40 +248,74 @@ void DivPlatformAY8910::checkWrites() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformAY8910::acquire_mame(short** buf, size_t len) {
|
void DivPlatformAY8910::acquire_mame(blip_buffer_t** bb, size_t len) {
|
||||||
thread_local short ayBuf[3];
|
thread_local short ayBuf[3];
|
||||||
|
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
oscBuf[i]->begin(len);
|
oscBuf[i]->begin(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sunsoft) {
|
for (size_t i=0; i<len; i++) {
|
||||||
for (size_t i=0; i<len; i++) {
|
int advance=len-i;
|
||||||
runDAC();
|
// heuristic
|
||||||
runTFX();
|
for (int j=0; j<3; j++) {
|
||||||
checkWrites();
|
// tone counter
|
||||||
|
const int period=MAX(1,ay->m_tone[j].period)*(ay->m_step_mul<<1);
|
||||||
|
const int remain=period-ay->m_tone[j].count;
|
||||||
|
if (remain<advance) advance=remain;
|
||||||
|
|
||||||
ay->sound_stream_update(ayBuf,1);
|
// envelope
|
||||||
buf[0][i]=ayBuf[0];
|
if (j<1) {
|
||||||
buf[1][i]=buf[0][i];
|
if (ay->m_envelope[j].holding==0) {
|
||||||
|
const int periodEnv=MAX(1,ay->m_envelope[j].period)*ay->m_env_step_mul;
|
||||||
|
const int remainEnv=periodEnv-ay->m_envelope[j].count;
|
||||||
|
if (remainEnv<advance) advance=remainEnv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// noise
|
||||||
|
const int noisePeriod=((int)ay->noise_period())*ay->m_step_mul;
|
||||||
|
const int noiseRemain=noisePeriod-ay->m_count_noise;
|
||||||
|
if (noiseRemain<advance) advance=noiseRemain;
|
||||||
|
|
||||||
|
//runDAC();
|
||||||
|
//runTFX();
|
||||||
|
|
||||||
|
if (!writes.empty() || advance<1) advance=1;
|
||||||
|
checkWrites();
|
||||||
|
|
||||||
|
ay->sound_stream_update(ayBuf,advance);
|
||||||
|
i+=advance-1;
|
||||||
|
|
||||||
|
if (sunsoft) {
|
||||||
|
if (lastOut[0]!=ayBuf[0]) {
|
||||||
|
blip_add_delta(bb[0],i,ayBuf[0]-lastOut[0]);
|
||||||
|
blip_add_delta(bb[1],i,ayBuf[0]-lastOut[0]);
|
||||||
|
lastOut[0]=ayBuf[0];
|
||||||
|
}
|
||||||
|
|
||||||
oscBuf[0]->putSample(i,CLAMP(sunsoftVolTable[31-(ay->lastIndx&31)]<<3,-32768,32767));
|
oscBuf[0]->putSample(i,CLAMP(sunsoftVolTable[31-(ay->lastIndx&31)]<<3,-32768,32767));
|
||||||
oscBuf[1]->putSample(i,CLAMP(sunsoftVolTable[31-((ay->lastIndx>>5)&31)]<<3,-32768,32767));
|
oscBuf[1]->putSample(i,CLAMP(sunsoftVolTable[31-((ay->lastIndx>>5)&31)]<<3,-32768,32767));
|
||||||
oscBuf[2]->putSample(i,CLAMP(sunsoftVolTable[31-((ay->lastIndx>>10)&31)]<<3,-32768,32767));
|
oscBuf[2]->putSample(i,CLAMP(sunsoftVolTable[31-((ay->lastIndx>>10)&31)]<<3,-32768,32767));
|
||||||
}
|
} else {
|
||||||
} else {
|
|
||||||
for (size_t i=0; i<len; i++) {
|
|
||||||
runDAC();
|
|
||||||
runTFX();
|
|
||||||
checkWrites();
|
|
||||||
|
|
||||||
ay->sound_stream_update(ayBuf,1);
|
|
||||||
if (stereo) {
|
if (stereo) {
|
||||||
buf[0][i]=ayBuf[0]+ayBuf[1]+((ayBuf[2]*stereoSep)>>8);
|
int out0=ayBuf[0]+ayBuf[1]+((ayBuf[2]*stereoSep)>>8);
|
||||||
buf[1][i]=((ayBuf[0]*stereoSep)>>8)+ayBuf[1]+ayBuf[2];
|
int out1=((ayBuf[0]*stereoSep)>>8)+ayBuf[1]+ayBuf[2];
|
||||||
|
if (lastOut[0]!=out0) {
|
||||||
|
blip_add_delta(bb[0],i,out0-lastOut[0]);
|
||||||
|
lastOut[0]=out0;
|
||||||
|
}
|
||||||
|
if (lastOut[1]!=out1) {
|
||||||
|
blip_add_delta(bb[1],i,out1-lastOut[1]);
|
||||||
|
lastOut[1]=out1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
buf[0][i]=ayBuf[0]+ayBuf[1]+ayBuf[2];
|
int out=ayBuf[0]+ayBuf[1]+ayBuf[2];
|
||||||
buf[1][i]=buf[0][i];
|
if (lastOut[0]!=out) {
|
||||||
|
blip_add_delta(bb[0],i,out-lastOut[0]);
|
||||||
|
blip_add_delta(bb[1],i,out-lastOut[0]);
|
||||||
|
lastOut[0]=out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oscBuf[0]->putSample(i,ayBuf[0]<<2);
|
oscBuf[0]->putSample(i,ayBuf[0]<<2);
|
||||||
|
@ -330,11 +364,14 @@ void DivPlatformAY8910::acquire_atomic(short** buf, size_t len) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformAY8910::acquireDirect(blip_buffer_t** bb, size_t len) {
|
||||||
|
if (selCore && !intellivision) return;
|
||||||
|
acquire_mame(bb,len);
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformAY8910::acquire(short** buf, size_t len) {
|
void DivPlatformAY8910::acquire(short** buf, size_t len) {
|
||||||
if (selCore && !intellivision) {
|
if (selCore && !intellivision) {
|
||||||
acquire_atomic(buf,len);
|
acquire_atomic(buf,len);
|
||||||
} else {
|
|
||||||
acquire_mame(buf,len);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,6 +1048,8 @@ void DivPlatformAY8910::reset() {
|
||||||
ayEnvSlideLow=0;
|
ayEnvSlideLow=0;
|
||||||
|
|
||||||
delay=0;
|
delay=0;
|
||||||
|
lastOut[0]=0;
|
||||||
|
lastOut[1]=0;
|
||||||
|
|
||||||
ioPortA=false;
|
ioPortA=false;
|
||||||
ioPortB=false;
|
ioPortB=false;
|
||||||
|
@ -1026,6 +1065,10 @@ bool DivPlatformAY8910::keyOffAffectsArp(int ch) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivPlatformAY8910::hasAcquireDirect() {
|
||||||
|
return (!selCore || intellivision);
|
||||||
|
}
|
||||||
|
|
||||||
bool DivPlatformAY8910::getLegacyAlwaysSetVolume() {
|
bool DivPlatformAY8910::getLegacyAlwaysSetVolume() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,7 @@ class DivPlatformAY8910: public DivDispatch {
|
||||||
ssg_t ay_atomic;
|
ssg_t ay_atomic;
|
||||||
|
|
||||||
int delay;
|
int delay;
|
||||||
|
int lastOut[2];
|
||||||
|
|
||||||
bool extMode;
|
bool extMode;
|
||||||
unsigned int extClock;
|
unsigned int extClock;
|
||||||
|
@ -149,7 +150,7 @@ class DivPlatformAY8910: public DivDispatch {
|
||||||
void checkWrites();
|
void checkWrites();
|
||||||
void updateOutSel(bool immediate=false);
|
void updateOutSel(bool immediate=false);
|
||||||
|
|
||||||
void acquire_mame(short** buf, size_t len);
|
void acquire_mame(blip_buffer_t** bb, size_t len);
|
||||||
void acquire_atomic(short** buf, size_t len);
|
void acquire_atomic(short** buf, size_t len);
|
||||||
|
|
||||||
friend void putDispatchChip(void*,int);
|
friend void putDispatchChip(void*,int);
|
||||||
|
@ -160,6 +161,7 @@ class DivPlatformAY8910: public DivDispatch {
|
||||||
void runTFX(int runRate=0);
|
void runTFX(int runRate=0);
|
||||||
void setExtClockDiv(unsigned int eclk=COLOR_NTSC, unsigned char ediv=8);
|
void setExtClockDiv(unsigned int eclk=COLOR_NTSC, unsigned char ediv=8);
|
||||||
void acquire(short** buf, size_t len);
|
void acquire(short** buf, size_t len);
|
||||||
|
void acquireDirect(blip_buffer_t** bb, size_t len);
|
||||||
void fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len);
|
void fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
void* getChanState(int chan);
|
void* getChanState(int chan);
|
||||||
|
@ -177,6 +179,7 @@ class DivPlatformAY8910: public DivDispatch {
|
||||||
void setFlags(const DivConfig& flags);
|
void setFlags(const DivConfig& flags);
|
||||||
int getOutputCount();
|
int getOutputCount();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
|
bool hasAcquireDirect();
|
||||||
DivMacroInt* getChanMacroInt(int ch);
|
DivMacroInt* getChanMacroInt(int ch);
|
||||||
DivSamplePos getSamplePos(int ch);
|
DivSamplePos getSamplePos(int ch);
|
||||||
bool getLegacyAlwaysSetVolume();
|
bool getLegacyAlwaysSetVolume();
|
||||||
|
|
|
@ -1035,167 +1035,165 @@ void ay8910_device::ay8910_write_reg(int r, int v)
|
||||||
// sound_stream_update - handle a stream update
|
// sound_stream_update - handle a stream update
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void ay8910_device::sound_stream_update(short* outputs, int outLen)
|
void ay8910_device::sound_stream_update(short* outputs, int advance)
|
||||||
{
|
{
|
||||||
tone_t *tone;
|
tone_t *tone;
|
||||||
envelope_t *envelope;
|
envelope_t *envelope;
|
||||||
|
|
||||||
int samples = outLen;
|
/* hack to prevent us from hanging when starting filtered outputs */
|
||||||
|
if (!m_ready)
|
||||||
|
{
|
||||||
|
for (int chan = 0; chan < m_streams; chan++)
|
||||||
|
outputs[chan]=0;
|
||||||
|
}
|
||||||
|
|
||||||
/* hack to prevent us from hanging when starting filtered outputs */
|
/* The 8910 has three outputs, each output is the mix of one of the three */
|
||||||
if (!m_ready)
|
/* tone generators and of the (single) noise generator. The two are mixed */
|
||||||
{
|
/* BEFORE going into the DAC. The formula to mix each channel is: */
|
||||||
for (int chan = 0; chan < m_streams; chan++)
|
/* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */
|
||||||
outputs[chan]=0;
|
/* Note that this means that if both tone and noise are disabled, the output */
|
||||||
}
|
/* is 1, not 0, and can be modulated changing the volume. */
|
||||||
|
|
||||||
/* The 8910 has three outputs, each output is the mix of one of the three */
|
/* loop? kill the loop and optimize! */
|
||||||
/* tone generators and of the (single) noise generator. The two are mixed */
|
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
||||||
/* BEFORE going into the DAC. The formula to mix each channel is: */
|
{
|
||||||
/* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */
|
tone = &m_tone[chan];
|
||||||
/* Note that this means that if both tone and noise are disabled, the output */
|
const int period = std::max<int>(1, tone->period) * (m_step_mul << 1);
|
||||||
/* is 1, not 0, and can be modulated changing the volume. */
|
tone->count += advance << (is_expanded_mode() ? 5 : ((m_feature & PSG_HAS_EXPANDED_MODE) ? 0 : 1));
|
||||||
|
if (tone->count>=period) {
|
||||||
|
tone->duty_cycle = (tone->duty_cycle - (tone->count/period)) & 0x1f;
|
||||||
|
tone->output = is_expanded_mode() ? BIT(duty_cycle[tone_duty(tone)], tone->duty_cycle) : BIT(tone->duty_cycle, 0);
|
||||||
|
tone->count = tone->count % period;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* buffering loop */
|
const int period_noise = (int)(noise_period()) * m_step_mul;
|
||||||
for (int sampindex = 0; sampindex < samples; sampindex++)
|
m_count_noise+=advance;
|
||||||
{
|
while (m_count_noise >= period_noise)
|
||||||
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
{
|
||||||
{
|
/* toggle the prescaler output. Noise is no different to
|
||||||
tone = &m_tone[chan];
|
* channels.
|
||||||
const int period = std::max<int>(1, tone->period) * (m_step_mul << 1);
|
*/
|
||||||
tone->count += is_expanded_mode() ? 32 : ((m_feature & PSG_HAS_EXPANDED_MODE) ? 1 : 2);
|
m_count_noise -= period_noise;
|
||||||
if (tone->count>=period) {
|
m_prescale_noise = (m_prescale_noise + 1) & ((m_feature & PSG_HAS_EXPANDED_MODE) ? 3 : 1);
|
||||||
tone->duty_cycle = (tone->duty_cycle - (tone->count/period)) & 0x1f;
|
|
||||||
tone->output = is_expanded_mode() ? BIT(duty_cycle[tone_duty(tone)], tone->duty_cycle) : BIT(tone->duty_cycle, 0);
|
|
||||||
tone->count = tone->count % period;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const int period_noise = (int)(noise_period()) * m_step_mul;
|
if (is_expanded_mode()) // AY8930 noise generator rate is twice? compares as compatibility mode
|
||||||
if ((++m_count_noise) >= period_noise)
|
{
|
||||||
{
|
// This is called "Noise value" on the docs, but is a counter whose period is determined by the LFSR.
|
||||||
/* toggle the prescaler output. Noise is no different to
|
// Using AND/OR gates, specific periods can be "filtered" out.
|
||||||
* channels.
|
// A square wave can be generated through this behavior, which can be used for crude AM pulse width modulation.
|
||||||
*/
|
|
||||||
m_count_noise = 0;
|
|
||||||
m_prescale_noise = (m_prescale_noise + 1) & ((m_feature & PSG_HAS_EXPANDED_MODE) ? 3 : 1);
|
|
||||||
|
|
||||||
if (is_expanded_mode()) // AY8930 noise generator rate is twice? compares as compatibility mode
|
// The period of the noise is determined by this value.
|
||||||
{
|
// The least significant byte of the LFSR is bitwise ANDed with the AND mask, and then bitwise ORed with the OR mask.
|
||||||
// This is called "Noise value" on the docs, but is a counter whose period is determined by the LFSR.
|
if ((++m_noise_value) >= (((unsigned char)(m_rng) & noise_and()) | noise_or())) // Clock the noise value.
|
||||||
// Using AND/OR gates, specific periods can be "filtered" out.
|
{
|
||||||
// A square wave can be generated through this behavior, which can be used for crude AM pulse width modulation.
|
m_noise_value = 0;
|
||||||
|
|
||||||
// The period of the noise is determined by this value.
|
// When everything is finally said and done, a 1bit latch is flipped.
|
||||||
// The least significant byte of the LFSR is bitwise ANDed with the AND mask, and then bitwise ORed with the OR mask.
|
// This is the final output of the noise, to be multiplied by the tone and envelope generators of the channel.
|
||||||
if ((++m_noise_value) >= (((unsigned char)(m_rng) & noise_and()) | noise_or())) // Clock the noise value.
|
m_noise_out ^= 1;
|
||||||
{
|
|
||||||
m_noise_value = 0;
|
|
||||||
|
|
||||||
// When everything is finally said and done, a 1bit latch is flipped.
|
noise_rng_tick();
|
||||||
// This is the final output of the noise, to be multiplied by the tone and envelope generators of the channel.
|
}
|
||||||
m_noise_out ^= 1;
|
}
|
||||||
|
else if (!m_prescale_noise)
|
||||||
|
noise_rng_tick();
|
||||||
|
}
|
||||||
|
|
||||||
noise_rng_tick();
|
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
||||||
}
|
{
|
||||||
}
|
tone = &m_tone[chan];
|
||||||
else if (!m_prescale_noise)
|
m_vol_enabled[chan] = (tone->output | (unsigned char)tone_enable(chan)) & (noise_output() | (unsigned char)noise_enable(chan));
|
||||||
noise_rng_tick();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
/* update envelope */
|
||||||
{
|
// who cares about env 1/2 on 8910
|
||||||
tone = &m_tone[chan];
|
for (int chan = 0; chan < (is_expanded_mode() ? NUM_CHANNELS : 1); chan++)
|
||||||
m_vol_enabled[chan] = (tone->output | (unsigned char)tone_enable(chan)) & (noise_output() | (unsigned char)noise_enable(chan));
|
{
|
||||||
}
|
envelope = &m_envelope[chan];
|
||||||
|
if (envelope->holding == 0)
|
||||||
|
{
|
||||||
|
const int period = std::max<int>(1, envelope->period) * m_env_step_mul;
|
||||||
|
envelope->count += advance;
|
||||||
|
if (envelope->count >= period)
|
||||||
|
{
|
||||||
|
envelope->count %= period;
|
||||||
|
envelope->step--;
|
||||||
|
|
||||||
/* update envelope */
|
/* check envelope current position */
|
||||||
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
if (envelope->step < 0)
|
||||||
{
|
{
|
||||||
envelope = &m_envelope[chan];
|
if (envelope->hold)
|
||||||
if (envelope->holding == 0)
|
{
|
||||||
{
|
if (envelope->alternate)
|
||||||
const int period = std::max<int>(1, envelope->period) * m_env_step_mul;
|
envelope->attack ^= m_env_step_mask;
|
||||||
if ((++envelope->count) >= period)
|
envelope->holding = 1;
|
||||||
{
|
envelope->step = 0;
|
||||||
envelope->count = 0;
|
}
|
||||||
envelope->step--;
|
else
|
||||||
|
{
|
||||||
|
/* if CountEnv has looped an odd number of times (usually 1), */
|
||||||
|
/* invert the output. */
|
||||||
|
if (envelope->alternate && (envelope->step & (m_env_step_mask + 1)))
|
||||||
|
envelope->attack ^= m_env_step_mask;
|
||||||
|
|
||||||
/* check envelope current position */
|
envelope->step &= m_env_step_mask;
|
||||||
if (envelope->step < 0)
|
}
|
||||||
{
|
}
|
||||||
if (envelope->hold)
|
|
||||||
{
|
|
||||||
if (envelope->alternate)
|
|
||||||
envelope->attack ^= m_env_step_mask;
|
|
||||||
envelope->holding = 1;
|
|
||||||
envelope->step = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* if CountEnv has looped an odd number of times (usually 1), */
|
|
||||||
/* invert the output. */
|
|
||||||
if (envelope->alternate && (envelope->step & (m_env_step_mask + 1)))
|
|
||||||
envelope->attack ^= m_env_step_mask;
|
|
||||||
|
|
||||||
envelope->step &= m_env_step_mask;
|
}
|
||||||
}
|
}
|
||||||
}
|
envelope->volume = (envelope->step ^ envelope->attack);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
if (m_streams == 3)
|
||||||
}
|
{
|
||||||
envelope->volume = (envelope->step ^ envelope->attack);
|
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
||||||
}
|
{
|
||||||
|
tone = &m_tone[chan];
|
||||||
if (m_streams == 3)
|
if (tone_envelope(tone) != 0)
|
||||||
{
|
{
|
||||||
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
envelope = &m_envelope[get_envelope_chan(chan)];
|
||||||
{
|
unsigned int env_volume = envelope->volume;
|
||||||
tone = &m_tone[chan];
|
if (m_feature & PSG_HAS_EXPANDED_MODE)
|
||||||
if (tone_envelope(tone) != 0)
|
{
|
||||||
{
|
if (!is_expanded_mode())
|
||||||
envelope = &m_envelope[get_envelope_chan(chan)];
|
{
|
||||||
unsigned int env_volume = envelope->volume;
|
env_volume >>= 1;
|
||||||
if (m_feature & PSG_HAS_EXPANDED_MODE)
|
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
|
||||||
{
|
outputs[chan]=m_vol_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
|
||||||
if (!is_expanded_mode())
|
else
|
||||||
{
|
outputs[chan]=m_vol_table[chan][m_vol_enabled[chan] ? env_volume : 0];
|
||||||
env_volume >>= 1;
|
}
|
||||||
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
|
else
|
||||||
outputs[chan]=m_vol_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
|
{
|
||||||
else
|
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
|
||||||
outputs[chan]=m_vol_table[chan][m_vol_enabled[chan] ? env_volume : 0];
|
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
|
||||||
}
|
else
|
||||||
else
|
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? env_volume : 0];
|
||||||
{
|
}
|
||||||
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
|
}
|
||||||
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
|
else
|
||||||
else
|
{
|
||||||
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? env_volume : 0];
|
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
|
||||||
}
|
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
|
||||||
}
|
else
|
||||||
else
|
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? env_volume : 0];
|
||||||
{
|
}
|
||||||
if (m_feature & PSG_EXTENDED_ENVELOPE) // AY8914 Has a two bit tone_envelope field
|
}
|
||||||
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? env_volume >> (3-tone_envelope(tone)) : 0];
|
else
|
||||||
else
|
{
|
||||||
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? env_volume : 0];
|
if (is_expanded_mode())
|
||||||
}
|
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? tone_volume(tone) : 0];
|
||||||
}
|
else
|
||||||
else
|
outputs[chan]=m_vol_table[chan][m_vol_enabled[chan] ? tone_volume(tone) : 0];
|
||||||
{
|
}
|
||||||
if (is_expanded_mode())
|
}
|
||||||
outputs[chan]=m_env_table[chan][m_vol_enabled[chan] ? tone_volume(tone) : 0];
|
}
|
||||||
else
|
else
|
||||||
outputs[chan]=m_vol_table[chan][m_vol_enabled[chan] ? tone_volume(tone) : 0];
|
{
|
||||||
}
|
outputs[0]=mix_3D();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outputs[0]=mix_3D();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ay8910_device::build_mixer_table()
|
void ay8910_device::build_mixer_table()
|
||||||
|
|
|
@ -164,7 +164,7 @@ public:
|
||||||
unsigned char ay8910_read_ym();
|
unsigned char ay8910_read_ym();
|
||||||
void ay8910_reset_ym();
|
void ay8910_reset_ym();
|
||||||
|
|
||||||
private:
|
public:
|
||||||
static constexpr int NUM_CHANNELS = 3;
|
static constexpr int NUM_CHANNELS = 3;
|
||||||
device_type chip_type;
|
device_type chip_type;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue