mpeg_audio.cpp/ymz770.cpp: add decode of "AMMSL" type samples for YMZ770B

This commit is contained in:
MetalliC 2024-04-30 17:28:51 +03:00
parent d6b23825bf
commit 0283d112ad
3 changed files with 21 additions and 10 deletions

View File

@ -32,7 +32,7 @@ void mpeg_audio::clear()
}
bool mpeg_audio::decode_buffer(int &pos, int limit, short *output,
int &output_samples, int &sample_rate, int &channels)
int &output_samples, int &sample_rate, int &channels, int atbl)
{
if(limit - pos < 16)
return false;
@ -44,6 +44,7 @@ bool mpeg_audio::decode_buffer(int &pos, int limit, short *output,
current_pos = pos;
current_limit = limit;
cbr_param_index = atbl;
unsigned short sync = do_gb(base, current_pos, 12);
retry_sync:
@ -124,15 +125,24 @@ bool mpeg_audio::decode_buffer(int &pos, int limit, short *output,
void mpeg_audio::read_header_amm(bool layer25)
{
gb(1); // unused
int ammsl = gb(1); // 1 = older AMM variant, CBR and constant frame size
int full_packets_count = gb(4); // max 12
int srate_index = gb(2); // max 2
sampling_rate = srate_index + 4 * layer25;
int last_packet_frame_id = gb(2); // max 2
last_frame_number = 3*full_packets_count + last_packet_frame_id;
int stereo_mode = gb(2);
int stereo_mode_ext = gb(2);
param_index = gb(3);
if (ammsl)
{
last_frame_number = 36;
param_index = cbr_param_index; // CBR, param_index came from sample pointer top bits
gb(3);
}
else
{
last_frame_number = 3*full_packets_count + last_packet_frame_id;
param_index = gb(3);
}
gb(1); // must be zero
channel_count = stereo_mode != 3 ? 2 : 1;

View File

@ -38,6 +38,7 @@ public:
// output_samples = number of samples written to output per channel
// sample_rate = output sample rate
// channels = number of channels written to output (total sample count is output_samples*channels)
// atbl = parameters index for older AMMSL CBR samples
//
// returns true if the buffer was complete and the new position in pos, false otherwise
//
@ -50,7 +51,7 @@ public:
// 1152 in the amm case, <1152 indicating end of stream).
bool decode_buffer(int &pos, int limit, short *output,
int &output_samples, int &sample_rate, int &channels);
int &output_samples, int &sample_rate, int &channels, int atbl = 0);
// Clear audio buffer
@ -80,7 +81,7 @@ private:
int accepted, position_align;
int sampling_rate, last_frame_number;
int param_index;
int param_index, cbr_param_index;
int channel_count, total_bands, joint_bands;

View File

@ -2,17 +2,17 @@
// copyright-holders:Olivier Galibert, R. Belmont, MetalliC
/***************************************************************************
Yamaha YMZ770C "AMMS-A" and YMZ774 "AMMS2C"
Yamaha YMZ770B "AMMSL", YMZ770C "AMMS-A" and YMZ774 "AMMS2C"
Emulation by R. Belmont and MetalliC
AMM decode by Olivier Galibert
-----
TODO:
- What does channel ATBL mean?
- Simple Access mode. SACs is register / data lists same as SEQ. in 770C, when both /SEL and /CS pins goes low - will be run SAC with number set at data bus.
can not be used in CV1K (/SEL pin is NC, internally pulled to VCC), probably not used in PGM2 too.
770:
- Configurable clock (currently hardcoded at 16kHz)
- sequencer timers implemented but seems unused, presumably because of design flaws or bugs, likely due to lack of automatic adding of sequencer # to register offset.
in result sequences uses very long chains of 32-sample wait commands instead, wasting a lot of ROM space.
- sequencer triggers not implemented, not sure how they works (Deathsmiles ending tune starts sequence with TGST = 01h, likely a bug and don't affect tune playback)
@ -23,7 +23,7 @@ TODO:
- sequencer off trigger (not used in games)
known SPUs in this series:
YMZ770B AMMSL Capcom medal hardware (alien.cpp), sample format is not AMM, in other parts looks like 770C
YMZ770B AMMSL Capcom medal hardware (alien.cpp)
YMZ770C AMMS-A Cave CV1000
YMZ771 SSGS3
YMZ773 AMMS2 Cron corp. video slots
@ -236,7 +236,7 @@ retry:
{
// next block
int sample_rate, channel_count;
if (!channel.decoder->decode_buffer(channel.pptr, m_rom.bytes()*8, channel.output_data, channel.output_remaining, sample_rate, channel_count) || channel.output_remaining == 0)
if (!channel.decoder->decode_buffer(channel.pptr, m_rom.bytes()*8, channel.output_data, channel.output_remaining, sample_rate, channel_count, channel.atbl) || channel.output_remaining == 0)
{
channel.is_playing = !channel.last_block; // detect infinite retry loop
channel.last_block = true;