mirror of
https://github.com/holub/mame
synced 2025-05-22 05:38:52 +03:00
Not worth mentioning. OKI bugfix. Cleanup.
This commit is contained in:
parent
ea0ccbda32
commit
66511d2ed9
@ -20,7 +20,7 @@ const device_type OKIM9810 = okim9810_device_config::static_alloc_device_config;
|
|||||||
|
|
||||||
// volume lookup table. The manual lists a full 16 steps, 2dB per step.
|
// volume lookup table. The manual lists a full 16 steps, 2dB per step.
|
||||||
// Given the dB values, that seems to map to a 7-bit volume control.
|
// Given the dB values, that seems to map to a 7-bit volume control.
|
||||||
const UINT8 okim9810_device::s_volume_table[16] =
|
const UINT8 okim9810_device::okim_voice::s_volume_table[16] =
|
||||||
{
|
{
|
||||||
0x80, // 0 dB
|
0x80, // 0 dB
|
||||||
0x65, // -2 dB
|
0x65, // -2 dB
|
||||||
@ -132,8 +132,7 @@ okim9810_device::okim9810_device(running_machine &_machine, const okim9810_devic
|
|||||||
m_config(config),
|
m_config(config),
|
||||||
m_stream(NULL),
|
m_stream(NULL),
|
||||||
m_TMP_register(0x00),
|
m_TMP_register(0x00),
|
||||||
m_global_volume_scale(0x00),
|
m_global_volume(0x00),
|
||||||
m_stereo_enabled(false),
|
|
||||||
m_filter_type(OKIM9810_SECONDARY_FILTER),
|
m_filter_type(OKIM9810_SECONDARY_FILTER),
|
||||||
m_output_level(OKIM9810_OUTPUT_TO_DIRECT_DAC)
|
m_output_level(OKIM9810_OUTPUT_TO_DIRECT_DAC)
|
||||||
{
|
{
|
||||||
@ -202,7 +201,7 @@ void okim9810_device::sound_stream_update(sound_stream &stream, stream_sample_t
|
|||||||
|
|
||||||
// iterate over voices and accumulate sample data
|
// iterate over voices and accumulate sample data
|
||||||
for (int voicenum = 0; voicenum < OKIM9810_VOICES; voicenum++)
|
for (int voicenum = 0; voicenum < OKIM9810_VOICES; voicenum++)
|
||||||
m_voice[voicenum].generate_audio(*m_direct, outputs[0], samples, m_global_volume_scale);
|
m_voice[voicenum].generate_audio(*m_direct, outputs[0], samples, m_global_volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -248,8 +247,12 @@ void okim9810_device::write_command(UINT8 data)
|
|||||||
if (channelMask & m_TMP_register)
|
if (channelMask & m_TMP_register)
|
||||||
{
|
{
|
||||||
m_voice[i].m_playing = true;
|
m_voice[i].m_playing = true;
|
||||||
mame_printf_verbose("\t\tPlaying channel %d: type %02x @ %08x for %d samples (looping=%d).\n", i,
|
mame_printf_verbose("\t\tPlaying channel %d: encoder type %d @ %dhz (volume = %d %d). From %08x for %d samples (looping=%d).\n",
|
||||||
m_voice[i].m_startFlags,
|
i,
|
||||||
|
m_voice[i].m_playbackAlgo,
|
||||||
|
m_voice[i].m_samplingFreq,
|
||||||
|
m_voice[i].volume_scale(m_global_volume, m_voice[i].m_channel_volume, m_voice[i].m_pan_volume_left),
|
||||||
|
m_voice[i].volume_scale(m_global_volume, m_voice[i].m_channel_volume, m_voice[i].m_pan_volume_right),
|
||||||
m_voice[i].m_base_offset,
|
m_voice[i].m_base_offset,
|
||||||
m_voice[i].m_count,
|
m_voice[i].m_count,
|
||||||
m_voice[i].m_looping);
|
m_voice[i].m_looping);
|
||||||
@ -293,10 +296,10 @@ void okim9810_device::write_command(UINT8 data)
|
|||||||
case 0x03: // OPT (options)
|
case 0x03: // OPT (options)
|
||||||
{
|
{
|
||||||
mame_printf_verbose("OPT complex data %02x\n", m_TMP_register);
|
mame_printf_verbose("OPT complex data %02x\n", m_TMP_register);
|
||||||
m_global_volume_scale = (m_TMP_register & 0x18) >> 3;
|
m_global_volume = (m_TMP_register & 0x18) >> 3;
|
||||||
m_filter_type = (m_TMP_register & 0x06) >> 1;
|
m_filter_type = (m_TMP_register & 0x06) >> 1;
|
||||||
m_output_level = (m_TMP_register & 0x01);
|
m_output_level = (m_TMP_register & 0x01);
|
||||||
mame_printf_verbose("\tOPT setting main volume scale to Vdd/%d\n", m_global_volume_scale+1);
|
mame_printf_verbose("\tOPT setting main volume scale to Vdd/%d\n", m_global_volume+1);
|
||||||
mame_printf_verbose("\tOPT setting output filter type to %d\n", m_filter_type);
|
mame_printf_verbose("\tOPT setting output filter type to %d\n", m_filter_type);
|
||||||
mame_printf_verbose("\tOPT setting output amp level to %d\n", m_output_level);
|
mame_printf_verbose("\tOPT setting output amp level to %d\n", m_output_level);
|
||||||
break;
|
break;
|
||||||
@ -327,32 +330,34 @@ void okim9810_device::write_command(UINT8 data)
|
|||||||
// Sub-table
|
// Sub-table
|
||||||
if (startFlags & 0x80)
|
if (startFlags & 0x80)
|
||||||
{
|
{
|
||||||
// TODO: Offset (oldStart+0) and (oldStart+4) are currently ignored - can the chaining continue?
|
|
||||||
offs_t oldStart = startAddr;
|
offs_t oldStart = startAddr;
|
||||||
|
// TODO: What does byte (oldStart + 0) refer to?
|
||||||
startAddr = m_direct->read_raw_byte(oldStart + 1) << 16;
|
startAddr = m_direct->read_raw_byte(oldStart + 1) << 16;
|
||||||
startAddr |= m_direct->read_raw_byte(oldStart + 2) << 8;
|
startAddr |= m_direct->read_raw_byte(oldStart + 2) << 8;
|
||||||
startAddr |= m_direct->read_raw_byte(oldStart + 3) << 0;
|
startAddr |= m_direct->read_raw_byte(oldStart + 3) << 0;
|
||||||
|
|
||||||
|
// TODO: What does byte (oldStart + 4) refer to?
|
||||||
endAddr = m_direct->read_raw_byte(oldStart + 5) << 16;
|
endAddr = m_direct->read_raw_byte(oldStart + 5) << 16;
|
||||||
endAddr |= m_direct->read_raw_byte(oldStart + 6) << 8;
|
endAddr |= m_direct->read_raw_byte(oldStart + 6) << 8;
|
||||||
endAddr |= m_direct->read_raw_byte(oldStart + 7) << 0;
|
endAddr |= m_direct->read_raw_byte(oldStart + 7) << 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mame_printf_verbose("FADR channel %d phrase offset %02x => ", channel, m_TMP_register);
|
|
||||||
mame_printf_verbose("\tstartFlags(%02x) startAddr(%06x) endFlags(%02x) endAddr(%06x) bytes(%d)\n", startFlags, startAddr, endFlags, endAddr, endAddr-startAddr);
|
|
||||||
m_voice[channel].m_sample = 0;
|
m_voice[channel].m_sample = 0;
|
||||||
m_voice[channel].m_startFlags = startFlags;
|
m_voice[channel].m_startFlags = startFlags;
|
||||||
m_voice[channel].m_base_offset = startAddr;
|
m_voice[channel].m_base_offset = startAddr;
|
||||||
m_voice[channel].m_endFlags = endFlags;
|
m_voice[channel].m_endFlags = endFlags;
|
||||||
|
m_voice[channel].m_count = (endAddr-startAddr) + 1; // Is there yet another extra byte at the end?
|
||||||
|
|
||||||
m_voice[channel].m_playbackAlgo = (startFlags & 0x30) >> 4; // Guess
|
m_voice[channel].m_playbackAlgo = (startFlags & 0x30) >> 4; // Guess
|
||||||
// debug printf("%02x %d\n", startFlags, m_voice[channel].m_playbackAlgo);
|
m_voice[channel].m_samplingFreq = s_sampling_freq_table[startFlags & 0x0f];
|
||||||
// TODO: Sampling frequency is very likely : (startFlags & 0x0f)
|
|
||||||
m_voice[channel].m_count = (endAddr-startAddr) + 1;
|
|
||||||
if (m_voice[channel].m_playbackAlgo == OKIM9810_ADPCM_PLAYBACK ||
|
if (m_voice[channel].m_playbackAlgo == OKIM9810_ADPCM_PLAYBACK ||
|
||||||
m_voice[channel].m_playbackAlgo == OKIM9810_ADPCM2_PLAYBACK)
|
m_voice[channel].m_playbackAlgo == OKIM9810_ADPCM2_PLAYBACK)
|
||||||
m_voice[channel].m_count *= 2;
|
m_voice[channel].m_count *= 2;
|
||||||
else
|
else
|
||||||
mame_printf_warning("UNIMPLEMENTED PLAYBACK METHOD %d\n", m_voice[channel].m_playbackAlgo);
|
mame_printf_warning("UNIMPLEMENTED PLAYBACK METHOD %d\n", m_voice[channel].m_playbackAlgo);
|
||||||
|
|
||||||
|
mame_printf_verbose("FADR channel %d phrase offset %02x => ", channel, m_TMP_register);
|
||||||
|
mame_printf_verbose("startFlags(%02x) startAddr(%06x) endFlags(%02x) endAddr(%06x) bytes(%d)\n", startFlags, startAddr, endFlags, endAddr, endAddr-startAddr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,16 +369,20 @@ void okim9810_device::write_command(UINT8 data)
|
|||||||
}
|
}
|
||||||
case 0x07: // CVOL (channel volume)
|
case 0x07: // CVOL (channel volume)
|
||||||
{
|
{
|
||||||
mame_printf_verbose("CVOL channel %d volume level %02x\n", channel, m_TMP_register);
|
mame_printf_verbose("CVOL channel %d data %02x\n", channel, m_TMP_register);
|
||||||
mame_printf_verbose("\tChannel %d -> volume %d.\n", channel, s_volume_table[m_TMP_register & 0x0f]);
|
mame_printf_verbose("\tChannel %d -> volume index %d.\n", channel, m_TMP_register & 0x0f);
|
||||||
|
|
||||||
m_voice[channel].m_volume = s_volume_table[m_TMP_register & 0x0f];
|
m_voice[channel].m_channel_volume = m_TMP_register & 0x0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x08: // PAN
|
case 0x08: // PAN
|
||||||
{
|
{
|
||||||
mame_printf_warning("PAN channel %d volume level %02x\n", channel, m_TMP_register);
|
const UINT8 leftVolIndex = (m_TMP_register & 0xf0) >> 4;
|
||||||
mame_printf_warning("MSM9810: UNIMPLEMENTED COMMAND!\n");
|
const UINT8 rightVolIndex = m_TMP_register & 0x0f;
|
||||||
|
mame_printf_verbose("PAN channel %d left index: %02x right index: %02x (%02x)\n", channel, leftVolIndex, rightVolIndex, m_TMP_register);
|
||||||
|
mame_printf_verbose("\tChannel %d left -> %d right -> %d\n", channel, leftVolIndex, rightVolIndex);
|
||||||
|
m_voice[channel].m_pan_volume_left = leftVolIndex;
|
||||||
|
m_voice[channel].m_pan_volume_right = rightVolIndex;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -416,14 +425,17 @@ WRITE8_MEMBER( okim9810_device::write_TMP_register )
|
|||||||
|
|
||||||
okim9810_device::okim_voice::okim_voice()
|
okim9810_device::okim_voice::okim_voice()
|
||||||
: m_playbackAlgo(OKIM9810_ADPCM2_PLAYBACK),
|
: m_playbackAlgo(OKIM9810_ADPCM2_PLAYBACK),
|
||||||
m_playing(false),
|
|
||||||
m_looping(false),
|
m_looping(false),
|
||||||
m_startFlags(0),
|
m_startFlags(0),
|
||||||
m_endFlags(0),
|
m_endFlags(0),
|
||||||
m_base_offset(0),
|
m_base_offset(0),
|
||||||
m_sample(0),
|
|
||||||
m_count(0),
|
m_count(0),
|
||||||
m_volume(0)
|
m_samplingFreq(s_sampling_freq_table[2]),
|
||||||
|
m_playing(false),
|
||||||
|
m_sample(0),
|
||||||
|
m_channel_volume(0x00),
|
||||||
|
m_pan_volume_left(0x00),
|
||||||
|
m_pan_volume_right(0x00)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,16 +447,19 @@ okim9810_device::okim_voice::okim_voice()
|
|||||||
void okim9810_device::okim_voice::generate_audio(direct_read_data &direct,
|
void okim9810_device::okim_voice::generate_audio(direct_read_data &direct,
|
||||||
stream_sample_t *buffer,
|
stream_sample_t *buffer,
|
||||||
int samples,
|
int samples,
|
||||||
const UINT8 global_volume_scale)
|
const UINT8 global_volume)
|
||||||
{
|
{
|
||||||
// skip if not active
|
// skip if not active
|
||||||
if (!m_playing)
|
if (!m_playing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// TODO: Stereo (it's only mono now [left channel])
|
||||||
|
UINT8 volume_scale_left = volume_scale(global_volume, m_channel_volume, m_pan_volume_left);
|
||||||
|
|
||||||
// loop while we still have samples to generate
|
// loop while we still have samples to generate
|
||||||
while (samples-- != 0)
|
while (samples-- != 0)
|
||||||
{
|
{
|
||||||
// fetch the next sample byte
|
// fetch the next sample nibble
|
||||||
int nibble = direct.read_raw_byte(m_base_offset + m_sample / 2) >> (((m_sample & 1) << 2) ^ 4);
|
int nibble = direct.read_raw_byte(m_base_offset + m_sample / 2) >> (((m_sample & 1) << 2) ^ 4);
|
||||||
|
|
||||||
// output to the buffer, scaling by the volume
|
// output to the buffer, scaling by the volume
|
||||||
@ -453,18 +468,16 @@ void okim9810_device::okim_voice::generate_audio(direct_read_data &direct,
|
|||||||
{
|
{
|
||||||
case OKIM9810_ADPCM_PLAYBACK:
|
case OKIM9810_ADPCM_PLAYBACK:
|
||||||
{
|
{
|
||||||
INT32 sample = (INT32)m_adpcm.clock(nibble);
|
INT32 volSample = (INT32)m_adpcm.clock(nibble);
|
||||||
sample = (sample * (INT32)m_volume) / 8; // per-channel volume
|
volSample = (volSample * (INT32)volume_scale_left) / 8;
|
||||||
sample >>= global_volume_scale; // global volume
|
*buffer++ += volSample;
|
||||||
*buffer++ += sample;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OKIM9810_ADPCM2_PLAYBACK:
|
case OKIM9810_ADPCM2_PLAYBACK:
|
||||||
{
|
{
|
||||||
INT32 sample = (INT32)m_adpcm.clock(nibble);
|
INT32 volSample = (INT32)m_adpcm2.clock(nibble);
|
||||||
sample = (sample * (INT32)m_volume) / 8; // per-channel volume
|
volSample = (volSample * (INT32)volume_scale_left) / 8;
|
||||||
sample >>= global_volume_scale; // global volume
|
*buffer++ += volSample;
|
||||||
*buffer++ += sample;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -482,3 +495,25 @@ void okim9810_device::okim_voice::generate_audio(direct_read_data &direct,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// volume_scale - computes the volume equation as
|
||||||
|
// seen on page 29 of the docs.
|
||||||
|
// Returns a value from the volume lookup table.
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
UINT8 okim9810_device::okim_voice::volume_scale(const UINT8 global_volume,
|
||||||
|
const UINT8 channel_volume,
|
||||||
|
const UINT8 pan_volume) const
|
||||||
|
{
|
||||||
|
const UINT8& V = channel_volume;
|
||||||
|
const UINT8& L = pan_volume;
|
||||||
|
const UINT8& O = global_volume;
|
||||||
|
UINT32 index = (V+L) + (O*3);
|
||||||
|
|
||||||
|
if (index > 15)
|
||||||
|
index = 15;
|
||||||
|
|
||||||
|
return s_volume_table[index];
|
||||||
|
}
|
||||||
|
@ -134,22 +134,31 @@ protected:
|
|||||||
void generate_audio(direct_read_data &direct,
|
void generate_audio(direct_read_data &direct,
|
||||||
stream_sample_t *buffer,
|
stream_sample_t *buffer,
|
||||||
int samples,
|
int samples,
|
||||||
const UINT8 global_volume_scale);
|
const UINT8 global_volume);
|
||||||
|
|
||||||
|
// computes volume scale from 3 volume numbers
|
||||||
|
UINT8 volume_scale(const UINT8 global_volume,
|
||||||
|
const UINT8 channel_volume,
|
||||||
|
const UINT8 pan_volume) const;
|
||||||
|
|
||||||
oki_adpcm_state m_adpcm; // current ADPCM state
|
oki_adpcm_state m_adpcm; // current ADPCM state
|
||||||
oki_adpcm2_state m_adpcm2; // current ADPCM2 state
|
oki_adpcm2_state m_adpcm2; // current ADPCM2 state
|
||||||
UINT8 m_playbackAlgo; // current playback method
|
UINT8 m_playbackAlgo; // current playback method
|
||||||
bool m_playing;
|
|
||||||
bool m_looping;
|
bool m_looping;
|
||||||
UINT8 m_startFlags;
|
UINT8 m_startFlags;
|
||||||
UINT8 m_endFlags;
|
UINT8 m_endFlags;
|
||||||
offs_t m_base_offset; // pointer to the base memory location
|
offs_t m_base_offset; // pointer to the base memory location
|
||||||
UINT32 m_sample; // current sample number
|
|
||||||
UINT32 m_count; // total samples to play
|
UINT32 m_count; // total samples to play
|
||||||
|
UINT32 m_samplingFreq; // voice sampling frequency
|
||||||
|
|
||||||
INT8 m_volume; // output volume
|
bool m_playing; // playback state
|
||||||
// TODO: m_volume_left; // stereo volume
|
UINT32 m_sample; // current sample number
|
||||||
// TODO: m_volume_right; // stereo volume
|
|
||||||
|
UINT8 m_channel_volume; // volume set with the CVOL command
|
||||||
|
UINT8 m_pan_volume_left; // volume set with the PAN command
|
||||||
|
UINT8 m_pan_volume_right; // volume set with the PAN command
|
||||||
|
|
||||||
|
static const UINT8 s_volume_table[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -161,15 +170,13 @@ protected:
|
|||||||
|
|
||||||
UINT8 m_TMP_register;
|
UINT8 m_TMP_register;
|
||||||
|
|
||||||
UINT8 m_global_volume_scale;
|
UINT8 m_global_volume; // volume set with the OPT command
|
||||||
bool m_stereo_enabled;
|
|
||||||
UINT8 m_filter_type;
|
UINT8 m_filter_type;
|
||||||
UINT8 m_output_level;
|
UINT8 m_output_level;
|
||||||
|
|
||||||
static const int OKIM9810_VOICES = 8;
|
static const int OKIM9810_VOICES = 8;
|
||||||
okim_voice m_voice[OKIM9810_VOICES];
|
okim_voice m_voice[OKIM9810_VOICES];
|
||||||
|
|
||||||
static const UINT8 s_volume_table[16];
|
|
||||||
static const UINT32 s_sampling_freq_table[16];
|
static const UINT32 s_sampling_freq_table[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user