diff options
author | 2012-10-16 21:18:06 +0000 | |
---|---|---|
committer | 2012-10-16 21:18:06 +0000 | |
commit | 065c06201b36f9fdd0ee7b5b1862cc8a5507b02c (patch) | |
tree | eb8611ed78dcd7a261cce3f032fbc77ceff20b2e /src/emu/sound/t6w28.c | |
parent | 3fcea59977c82a7be8eec192c49e5dc524eb285d (diff) |
t6w28.c: Converted to C++. [Wilbert Pol]
Diffstat (limited to 'src/emu/sound/t6w28.c')
-rw-r--r-- | src/emu/sound/t6w28.c | 291 |
1 files changed, 113 insertions, 178 deletions
diff --git a/src/emu/sound/t6w28.c b/src/emu/sound/t6w28.c index ad83a948593..e42899dbae1 100644 --- a/src/emu/sound/t6w28.c +++ b/src/emu/sound/t6w28.c @@ -37,53 +37,25 @@ Offset 0: #define STEP 0x10000 -struct t6w28_state +WRITE8_MEMBER( t6w28_device::write ) { - sound_stream * Channel; - int SampleRate; - int VolTable[16]; /* volume table */ - INT32 Register[16]; /* registers */ - INT32 LastRegister[2]; /* last register written */ - INT32 Volume[8]; /* volume of voice 0-2 and noise */ - UINT32 RNG[2]; /* noise generator */ - INT32 NoiseMode[2]; /* active noise mode */ - INT32 FeedbackMask; /* mask for feedback */ - INT32 WhitenoiseTaps; /* mask for white noise taps */ - INT32 WhitenoiseInvert; /* white noise invert flag */ - INT32 Period[8]; - INT32 Count[8]; - INT32 Output[8]; -}; - - -INLINE t6w28_state *get_safe_token(device_t *device) -{ - assert(device != NULL); - assert(device->type() == T6W28); - return (t6w28_state *)downcast<t6w28_device *>(device)->token(); -} - - -WRITE8_DEVICE_HANDLER( t6w28_w ) -{ - t6w28_state *R = get_safe_token(device); int n, r, c; /* update the output buffer before changing the registers */ - R->Channel->update(); + m_channel->update(); offset &= 1; if (data & 0x80) { r = (data & 0x70) >> 4; - R->LastRegister[offset] = r; - R->Register[offset * 8 + r] = (R->Register[offset * 8 + r] & 0x3f0) | (data & 0x0f); + m_last_register[offset] = r; + m_register[offset * 8 + r] = (m_register[offset * 8 + r] & 0x3f0) | (data & 0x0f); } else { - r = R->LastRegister[offset]; + r = m_last_register[offset]; } c = r/2; switch (r) @@ -91,34 +63,34 @@ WRITE8_DEVICE_HANDLER( t6w28_w ) case 0: /* tone 0 : frequency */ case 2: /* tone 1 : frequency */ case 4: /* tone 2 : frequency */ - if ((data & 0x80) == 0) R->Register[offset * 8 + r] = (R->Register[offset * 8 + r] & 0x0f) | ((data & 0x3f) << 4); - R->Period[offset * 4 + c] = STEP * R->Register[offset * 8 + r]; - if (R->Period[offset * 4 + c] == 0) R->Period[offset * 4 + c] = STEP; + if ((data & 0x80) == 0) m_register[offset * 8 + r] = (m_register[offset * 8 + r] & 0x0f) | ((data & 0x3f) << 4); + m_period[offset * 4 + c] = STEP * m_register[offset * 8 + r]; + if (m_period[offset * 4 + c] == 0) m_period[offset * 4 + c] = STEP; if (r == 4) { /* update noise shift frequency */ - if ((R->Register[offset * 8 + 6] & 0x03) == 0x03) - R->Period[offset * 4 + 3] = 2 * R->Period[offset * 4 + 2]; + if ((m_register[offset * 8 + 6] & 0x03) == 0x03) + m_period[offset * 4 + 3] = 2 * m_period[offset * 4 + 2]; } break; case 1: /* tone 0 : volume */ case 3: /* tone 1 : volume */ case 5: /* tone 2 : volume */ case 7: /* noise : volume */ - R->Volume[offset * 4 + c] = R->VolTable[data & 0x0f]; - if ((data & 0x80) == 0) R->Register[offset * 8 + r] = (R->Register[offset * 8 + r] & 0x3f0) | (data & 0x0f); + m_volume[offset * 4 + c] = m_vol_table[data & 0x0f]; + if ((data & 0x80) == 0) m_register[offset * 8 + r] = (m_register[offset * 8 + r] & 0x3f0) | (data & 0x0f); break; case 6: /* noise : frequency, mode */ { - if ((data & 0x80) == 0) R->Register[offset * 8 + r] = (R->Register[offset * 8 + r] & 0x3f0) | (data & 0x0f); - n = R->Register[offset * 8 + 6]; - R->NoiseMode[offset] = (n & 4) ? 1 : 0; + if ((data & 0x80) == 0) m_register[offset * 8 + r] = (m_register[offset * 8 + r] & 0x3f0) | (data & 0x0f); + n = m_register[offset * 8 + 6]; + m_noise_mode[offset] = (n & 4) ? 1 : 0; /* N/512,N/1024,N/2048,Tone #3 output */ - R->Period[offset * 4 + 3] = ((n&3) == 3) ? 2 * R->Period[offset * 4 + 2] : (STEP << (5+(n&3))); + m_period[offset * 4 + 3] = ((n&3) == 3) ? 2 * m_period[offset * 4 + 2] : (STEP << (5+(n&3))); /* Reset noise shifter */ - R->RNG[offset] = R->FeedbackMask; /* this is correct according to the smspower document */ - //R->RNG = 0xF35; /* this is not, but sounds better in do run run */ - R->Output[offset * 4 + 3] = R->RNG[offset] & 1; + m_rng[offset] = m_feedback_mask; /* this is correct according to the smspower document */ + //m_rng = 0xF35; /* this is not, but sounds better in do run run */ + m_output[offset * 4 + 3] = m_rng[offset] & 1; } break; } @@ -126,10 +98,13 @@ WRITE8_DEVICE_HANDLER( t6w28_w ) -static STREAM_UPDATE( t6w28_update ) +//------------------------------------------------- +// sound_stream_update - handle a stream update +//------------------------------------------------- + +void t6w28_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { int i; - t6w28_state *R = (t6w28_state *)param; stream_sample_t *buffer0 = outputs[0]; stream_sample_t *buffer1 = outputs[1]; @@ -137,12 +112,12 @@ static STREAM_UPDATE( t6w28_update ) /* If the volume is 0, increase the counter */ for (i = 0;i < 8;i++) { - if (R->Volume[i] == 0) + if (m_volume[i] == 0) { /* note that I do count += samples, NOT count = samples + 1. You might think */ /* it's the same since the volume is 0, but doing the latter could cause */ /* interferencies when the program is rapidly modulating the volume. */ - if (R->Count[i] <= samples*STEP) R->Count[i] += samples*STEP; + if (m_count[i] <= samples*STEP) m_count[i] += samples*STEP; } } @@ -159,56 +134,56 @@ static STREAM_UPDATE( t6w28_update ) for (i = 2;i < 3;i++) { - if (R->Output[i]) vol[i] += R->Count[i]; - R->Count[i] -= STEP; - /* Period[i] is the half period of the square wave. Here, in each */ - /* loop I add Period[i] twice, so that at the end of the loop the */ + if (m_output[i]) vol[i] += m_count[i]; + m_count[i] -= STEP; + /* m_period[i] is the half period of the square wave. Here, in each */ + /* loop I add m_period[i] twice, so that at the end of the loop the */ /* square wave is in the same status (0 or 1) it was at the start. */ - /* vol[i] is also incremented by Period[i], since the wave has been 1 */ + /* vol[i] is also incremented by m_period[i], since the wave has been 1 */ /* exactly half of the time, regardless of the initial position. */ - /* If we exit the loop in the middle, Output[i] has to be inverted */ + /* If we exit the loop in the middle, m_output[i] has to be inverted */ /* and vol[i] incremented only if the exit status of the square */ /* wave is 1. */ - while (R->Count[i] <= 0) + while (m_count[i] <= 0) { - R->Count[i] += R->Period[i]; - if (R->Count[i] > 0) + m_count[i] += m_period[i]; + if (m_count[i] > 0) { - R->Output[i] ^= 1; - if (R->Output[i]) vol[i] += R->Period[i]; + m_output[i] ^= 1; + if (m_output[i]) vol[i] += m_period[i]; break; } - R->Count[i] += R->Period[i]; - vol[i] += R->Period[i]; + m_count[i] += m_period[i]; + vol[i] += m_period[i]; } - if (R->Output[i]) vol[i] -= R->Count[i]; + if (m_output[i]) vol[i] -= m_count[i]; } for (i = 4;i < 7;i++) { - if (R->Output[i]) vol[i] += R->Count[i]; - R->Count[i] -= STEP; - /* Period[i] is the half period of the square wave. Here, in each */ - /* loop I add Period[i] twice, so that at the end of the loop the */ + if (m_output[i]) vol[i] += m_count[i]; + m_count[i] -= STEP; + /* m_period[i] is the half period of the square wave. Here, in each */ + /* loop I add m_period[i] twice, so that at the end of the loop the */ /* square wave is in the same status (0 or 1) it was at the start. */ - /* vol[i] is also incremented by Period[i], since the wave has been 1 */ + /* vol[i] is also incremented by m_period[i], since the wave has been 1 */ /* exactly half of the time, regardless of the initial position. */ - /* If we exit the loop in the middle, Output[i] has to be inverted */ + /* If we exit the loop in the middle, m_output[i] has to be inverted */ /* and vol[i] incremented only if the exit status of the square */ /* wave is 1. */ - while (R->Count[i] <= 0) + while (m_count[i] <= 0) { - R->Count[i] += R->Period[i]; - if (R->Count[i] > 0) + m_count[i] += m_period[i]; + if (m_count[i] > 0) { - R->Output[i] ^= 1; - if (R->Output[i]) vol[i] += R->Period[i]; + m_output[i] ^= 1; + if (m_output[i]) vol[i] += m_period[i]; break; } - R->Count[i] += R->Period[i]; - vol[i] += R->Period[i]; + m_count[i] += m_period[i]; + vol[i] += m_period[i]; } - if (R->Output[i]) vol[i] -= R->Count[i]; + if (m_output[i]) vol[i] -= m_count[i]; } left = STEP; @@ -217,52 +192,52 @@ static STREAM_UPDATE( t6w28_update ) int nextevent; - if (R->Count[3] < left) nextevent = R->Count[3]; + if (m_count[3] < left) nextevent = m_count[3]; else nextevent = left; - if (R->Output[3]) vol[3] += R->Count[3]; - R->Count[3] -= nextevent; - if (R->Count[3] <= 0) + if (m_output[3]) vol[3] += m_count[3]; + m_count[3] -= nextevent; + if (m_count[3] <= 0) { - if (R->NoiseMode[0] == 1) /* White Noise Mode */ + if (m_noise_mode[0] == 1) /* White Noise Mode */ { - if (((R->RNG[0] & R->WhitenoiseTaps) != R->WhitenoiseTaps) && ((R->RNG[0] & R->WhitenoiseTaps) != 0)) /* crappy xor! */ + if (((m_rng[0] & m_whitenoise_taps) != m_whitenoise_taps) && ((m_rng[0] & m_whitenoise_taps) != 0)) /* crappy xor! */ { - R->RNG[0] >>= 1; - R->RNG[0] |= R->FeedbackMask; + m_rng[0] >>= 1; + m_rng[0] |= m_feedback_mask; } else { - R->RNG[0] >>= 1; + m_rng[0] >>= 1; } - R->Output[3] = R->WhitenoiseInvert ? !(R->RNG[0] & 1) : R->RNG[0] & 1; + m_output[3] = m_whitenoise_invert ? !(m_rng[0] & 1) : m_rng[0] & 1; } else /* Periodic noise mode */ { - if (R->RNG[0] & 1) + if (m_rng[0] & 1) { - R->RNG[0] >>= 1; - R->RNG[0] |= R->FeedbackMask; + m_rng[0] >>= 1; + m_rng[0] |= m_feedback_mask; } else { - R->RNG[0] >>= 1; + m_rng[0] >>= 1; } - R->Output[3] = R->RNG[0] & 1; + m_output[3] = m_rng[0] & 1; } - R->Count[3] += R->Period[3]; - if (R->Output[3]) vol[3] += R->Period[3]; + m_count[3] += m_period[3]; + if (m_output[3]) vol[3] += m_period[3]; } - if (R->Output[3]) vol[3] -= R->Count[3]; + if (m_output[3]) vol[3] -= m_count[3]; left -= nextevent; } while (left > 0); - out0 = vol[4] * R->Volume[4] + vol[5] * R->Volume[5] + - vol[6] * R->Volume[6] + vol[3] * R->Volume[7]; + out0 = vol[4] * m_volume[4] + vol[5] * m_volume[5] + + vol[6] * m_volume[6] + vol[3] * m_volume[7]; - out1 = vol[4] * R->Volume[0] + vol[5] * R->Volume[1] + - vol[6] * R->Volume[2] + vol[3] * R->Volume[3]; + out1 = vol[4] * m_volume[0] + vol[5] * m_volume[1] + + vol[6] * m_volume[2] + vol[3] * m_volume[3]; if (out0 > MAX_OUTPUT * STEP) out0 = MAX_OUTPUT * STEP; if (out1 > MAX_OUTPUT * STEP) out1 = MAX_OUTPUT * STEP; @@ -276,12 +251,11 @@ static STREAM_UPDATE( t6w28_update ) -static void t6w28_set_gain(t6w28_state *R,int gain) +void t6w28_device::set_gain(int gain) { int i; double out; - gain &= 0xff; /* increase max output basing on gain (0.2 dB per step) */ @@ -293,75 +267,67 @@ static void t6w28_set_gain(t6w28_state *R,int gain) for (i = 0;i < 15;i++) { /* limit volume to avoid clipping */ - if (out > MAX_OUTPUT / 3) R->VolTable[i] = MAX_OUTPUT / 3; - else R->VolTable[i] = out; + if (out > MAX_OUTPUT / 3) m_vol_table[i] = MAX_OUTPUT / 3; + else m_vol_table[i] = out; out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */ } - R->VolTable[15] = 0; + m_vol_table[15] = 0; } -static int t6w28_init(device_t *device, t6w28_state *R) +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void t6w28_device::device_start() { - int sample_rate = device->clock()/16; int i; - R->Channel = device->machine().sound().stream_alloc(*device,0,2,sample_rate,R,t6w28_update); - - R->SampleRate = sample_rate; + m_sample_rate = clock() / 16; + m_channel = machine().sound().stream_alloc(*this, 0, 2, m_sample_rate, this); - for (i = 0;i < 8;i++) R->Volume[i] = 0; + for (i = 0;i < 8;i++) m_volume[i] = 0; - R->LastRegister[0] = 0; - R->LastRegister[1] = 0; + m_last_register[0] = 0; + m_last_register[1] = 0; for (i = 0;i < 8;i+=2) { - R->Register[i] = 0; - R->Register[i + 1] = 0x0f; /* volume = 0 */ + m_register[i] = 0; + m_register[i + 1] = 0x0f; /* volume = 0 */ } for (i = 0;i < 8;i++) { - R->Output[i] = 0; - R->Period[i] = R->Count[i] = STEP; + m_output[i] = 0; + m_period[i] = m_count[i] = STEP; } /* Default is SN76489 non-A */ - R->FeedbackMask = 0x4000; /* mask for feedback */ - R->WhitenoiseTaps = 0x03; /* mask for white noise taps */ - R->WhitenoiseInvert = 1; /* white noise invert flag */ + m_feedback_mask = 0x4000; /* mask for feedback */ + m_whitenoise_taps = 0x03; /* mask for white noise taps */ + m_whitenoise_invert = 1; /* white noise invert flag */ - R->RNG[0] = R->FeedbackMask; - R->RNG[1] = R->FeedbackMask; - R->Output[3] = R->RNG[0] & 1; + m_rng[0] = m_feedback_mask; + m_rng[1] = m_feedback_mask; + m_output[3] = m_rng[0] & 1; - return 0; -} - - -static DEVICE_START( t6w28 ) -{ - t6w28_state *chip = get_safe_token(device); - - if (t6w28_init(device,chip) != 0) - fatalerror("Error creating t6w28 chip\n"); - t6w28_set_gain(chip, 0); + set_gain(0); /* values from sn76489a */ - chip->FeedbackMask = 0x8000; - chip->WhitenoiseTaps = 0x06; - chip->WhitenoiseInvert = FALSE; - - device->save_item(NAME(chip->Register)); - device->save_item(NAME(chip->LastRegister)); - device->save_item(NAME(chip->Volume)); - device->save_item(NAME(chip->RNG)); - device->save_item(NAME(chip->NoiseMode)); - device->save_item(NAME(chip->Period)); - device->save_item(NAME(chip->Count)); - device->save_item(NAME(chip->Output)); + m_feedback_mask = 0x8000; + m_whitenoise_taps = 0x06; + m_whitenoise_invert = FALSE; + + save_item(NAME(m_register)); + save_item(NAME(m_last_register)); + save_item(NAME(m_volume)); + save_item(NAME(m_rng)); + save_item(NAME(m_noise_mode)); + save_item(NAME(m_period)); + save_item(NAME(m_count)); + save_item(NAME(m_output)); } const device_type T6W28 = &device_creator<t6w28_device>; @@ -370,36 +336,5 @@ t6w28_device::t6w28_device(const machine_config &mconfig, const char *tag, devic : device_t(mconfig, T6W28, "T6W28", tag, owner, clock), device_sound_interface(mconfig, *this) { - m_token = global_alloc_clear(t6w28_state); } -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void t6w28_device::device_config_complete() -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void t6w28_device::device_start() -{ - DEVICE_START_NAME( t6w28 )(this); -} - -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- - -void t6w28_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) -{ - // should never get here - fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); -} - - |