diff options
author | 2012-12-31 22:04:28 +0000 | |
---|---|---|
committer | 2012-12-31 22:04:28 +0000 | |
commit | fd0960a746f5a42760548d1467536940f9307040 (patch) | |
tree | 3c34b0aebd318eb11447c1de615c53e1cb75d34c /src | |
parent | 7e652d13c538f96ee0d43207cd373e4f53d06805 (diff) |
Split AMM decoder from YMZ770 and add MPEG layer 1/2 support [O. Galibert]
De-skeletonized Sega Z80 type Digital Sound Board, hooked up to swa [R. Belmont, O. Galibert]
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/sound/mpeg_audio.c | 752 | ||||
-rw-r--r-- | src/emu/sound/mpeg_audio.h | 129 | ||||
-rw-r--r-- | src/emu/sound/sound.mak | 2 | ||||
-rw-r--r-- | src/emu/sound/ymz770.c | 729 | ||||
-rw-r--r-- | src/emu/sound/ymz770.h | 8 | ||||
-rw-r--r-- | src/mame/audio/dsbz80.c | 127 | ||||
-rw-r--r-- | src/mame/audio/dsbz80.h | 11 | ||||
-rw-r--r-- | src/mame/drivers/model1.c | 23 | ||||
-rw-r--r-- | src/mame/includes/model1.h | 2 |
9 files changed, 1041 insertions, 742 deletions
diff --git a/src/emu/sound/mpeg_audio.c b/src/emu/sound/mpeg_audio.c new file mode 100644 index 00000000000..94f11c72842 --- /dev/null +++ b/src/emu/sound/mpeg_audio.c @@ -0,0 +1,752 @@ +/*************************************************************************** + + MPEG audio support. Only layer2 and variants for now. + +***************************************************************************/ + +#include "emu.h" +#include "mpeg_audio.h" + +mpeg_audio::mpeg_audio(const void *_base, unsigned int _accepted, bool lsb_first, int _position_align) +{ + base = (const UINT8 *)_base; + accepted = _accepted; + do_gb = lsb_first ? do_gb_lsb : do_gb_msb; + position_align = _position_align ? _position_align - 1 : 0; + + memset(audio_buffer, 0, sizeof(audio_buffer)); + audio_buffer_pos[0] = 16*32; + audio_buffer_pos[1] = 16*32; +} + + +bool mpeg_audio::decode_buffer(int &pos, int limit, short *output, + int &output_samples, int &sample_rate, int &channels) +{ + if(limit - pos < 16) + return false; + + // Scan for the sync mark + // + // Avoid the exception dance at the point where going out of bound + // is the most probable and easily avoidable + + current_pos = pos; + current_limit = limit; + unsigned short sync = do_gb(base, current_pos, 12); + + retry_sync: + while(sync != 0xfff && current_pos < limit) + sync = ((sync << 1) | do_gb(base, current_pos, 1)) & 0xfff; + + if(limit - current_pos < 4) + return false; + + int layer = 0; + int variant = do_gb(base, current_pos, 3); + switch(variant) { + case 2: + if(accepted & L2_5) + layer = 2; + else if(accepted & AMM) + layer = 4; + break; + + case 5: + if(accepted & L3) + layer = 3; + break; + + case 6: + if(accepted & (L2|L2_5)) + layer = 2; + else if(accepted & AMM) + layer = 4; + break; + + case 7: + if(accepted & L1) + layer = 1; + break; + } + + if(!layer) { + current_pos -= 3; + sync = ((sync << 1) | do_gb(base, current_pos, 1)) & 0xfff; + goto retry_sync; + } + + switch(layer) { + case 1: + abort(); + case 2: + try { + read_header_mpeg2(variant == 2); + read_data_mpeg2(); + decode_mpeg2(output, output_samples); + } catch(limit_hit) { + return false; + } + break; + case 3: + abort(); + case 4: + try { + read_header_amm(variant == 2); + read_data_mpeg2(); + decode_mpeg2(output, output_samples); + } catch(limit_hit) { + return false; + } + break; + } + + if(position_align) + current_pos = (current_pos + position_align) & ~position_align; + + pos = current_pos; + sample_rate = sample_rates[sampling_rate]; + channels = channel_count; + return true; +} + +void mpeg_audio::read_header_amm(bool layer25) +{ + gb(1); // unused + 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); + gb(1); // must be zero + + channel_count = stereo_mode != 3 ? 2 : 1; + + total_bands = total_band_counts[param_index]; + joint_bands = total_bands; + if(stereo_mode == 1) // joint stereo + joint_bands = joint_band_counts[stereo_mode_ext]; + if(joint_bands > total_bands ) + joint_bands = total_bands; +} + +void mpeg_audio::read_header_mpeg2(bool layer25) +{ + int prot = gb(1); + int bitrate_index = gb(4); + sampling_rate = gb(2); + gb(1); // padding + gb(1); + last_frame_number = 36; + int stereo_mode = gb(2); + int stereo_mode_ext = gb(2); + gb(2); // copyright, original + gb(2); // emphasis + if(!prot) + gb(16); // crc + + channel_count = stereo_mode != 3 ? 2 : 1; + + param_index = layer2_param_index[channel_count-1][sampling_rate][bitrate_index]; + assert(param_index != -1); + + total_bands = total_band_counts[param_index]; + joint_bands = total_bands; + if(stereo_mode == 1) // joint stereo + joint_bands = joint_band_counts[stereo_mode_ext]; + if(joint_bands > total_bands ) + joint_bands = total_bands; +} + +void mpeg_audio::read_data_mpeg2() +{ + read_band_params(); + read_scfci(); + read_band_amplitude_params(); +} + +void mpeg_audio::decode_mpeg2(short *output, int &output_samples) +{ + output_samples = 0; + build_amplitudes(); + + // Supposed to stop at last_frame_number when it's not 12*3+2 = 38 + int frame_number = 0; + for(int upper_step = 0; upper_step<3; upper_step++) + for(int middle_step = 0; middle_step < 4; middle_step++) { + build_next_segments(upper_step); + for(int lower_step = 0; lower_step < 3; lower_step++) { + retrieve_subbuffer(lower_step); + + for(int chan=0; chan<channel_count; chan++) { + double resynthesis_buffer[32]; + idct32(subbuffer[chan], audio_buffer[chan] + audio_buffer_pos[chan]); + resynthesis(audio_buffer[chan] + audio_buffer_pos[chan] + 16, resynthesis_buffer); + scale_and_clamp(resynthesis_buffer, output + chan, channel_count); + audio_buffer_pos[chan] -= 32; + if(audio_buffer_pos[chan]<0) { + memmove(audio_buffer[chan]+17*32, audio_buffer[chan], 15*32*sizeof(audio_buffer[chan][0])); + audio_buffer_pos[chan] = 16*32; + } + } + output += 32*channel_count; + output_samples += 32; + frame_number++; + if(frame_number == last_frame_number) + return; + } + } +} + +const int mpeg_audio::sample_rates[8] = { 44100, 48000, 32000, 0, 22050, 24000, 16000, 0 }; + +const int mpeg_audio::layer2_param_index[2][4][16] = { + { + { 1, 2, 2, 0, 0, 0, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 }, + { 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1 }, + { 1, 3, 3, 0, 0, 0, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + }, + { + { 1, -1, -1, -1, 2, -1, 2, 0, 0, 0, 1, 1, 1, 1, 1, -1 }, + { 0, -1, -1, -1, 2, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, -1 }, + { 1, -1, -1, -1, 3, -1, 3, 0, 0, 0, 1, 1, 1, 1, 1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + } +}; + +const int mpeg_audio::band_parameter_indexed_values[5][32][17] = { + { + { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, + { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, + { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + }, + { + { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, + { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, + { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + }, + { + { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + }, + { + { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + }, + { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, + } +}; + +const int mpeg_audio::band_parameter_index_bits_count[5][32] = { + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 0, 0, 0, 0, 0, }, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 0, 0, }, + { 4, 4, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, }, +}; + +const int mpeg_audio::total_band_counts[5] = { 27, 30, 8, 12, 30 }; + +const int mpeg_audio::joint_band_counts[4] = { 4, 8, 12, 16 }; + +const mpeg_audio::band_info mpeg_audio::band_infos[18] = { + { 0x0000, 0.00, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x0003, 7.00, 2, 5, 3, 9, 1-1.0/ 4, -1.0/ 4, 1/(1-1.0/ 4), 1.0/ 2 }, + { 0x0005, 11.00, 3, 7, 5, 25, 1-3.0/ 8, -3.0/ 8, 1/(1-3.0/ 8), 1.0/ 2 }, + { 0x0007, 16.00, 3, 9, 0, 0, 1-1.0/ 8, -1.0/ 8, 1/(1-1.0/ 8), 1.0/ 4 }, + { 0x0009, 20.84, 4, 10, 9, 81, 1-7.0/ 16, -7.0/ 16, 1/(1-7.0/ 16), 1.0/ 2 }, + { 0x000f, 25.28, 4, 12, 0, 0, 1-1.0/ 16, -1.0/ 16, 1/(1-1.0/ 16), 1.0/ 8 }, + { 0x001f, 31.59, 5, 15, 0, 0, 1-1.0/ 32, -1.0/ 32, 1/(1-1.0/ 32), 1.0/ 16 }, + { 0x003f, 37.75, 6, 18, 0, 0, 1-1.0/ 64, -1.0/ 64, 1/(1-1.0/ 64), 1.0/ 32 }, + { 0x007f, 43.84, 7, 21, 0, 0, 1-1.0/ 128, -1.0/ 128, 1/(1-1.0/ 128), 1.0/ 64 }, + { 0x00ff, 49.89, 8, 24, 0, 0, 1-1.0/ 256, -1.0/ 256, 1/(1-1.0/ 256), 1.0/ 128 }, + { 0x01ff, 55.93, 9, 27, 0, 0, 1-1.0/ 512, -1.0/ 512, 1/(1-1.0/ 512), 1.0/ 256 }, + { 0x03ff, 61.96, 10, 30, 0, 0, 1-1.0/ 1024, -1.0/ 1024, 1/(1-1.0/ 1024), 1.0/ 512 }, + { 0x07ff, 67.98, 11, 33, 0, 0, 1-1.0/ 2048, -1.0/ 2048, 1/(1-1.0/ 2048), 1.0/ 1024 }, + { 0x0fff, 74.01, 12, 36, 0, 0, 1-1.0/ 4096, -1.0/ 4096, 1/(1-1.0/ 4096), 1.0/ 2048 }, + { 0x1fff, 80.03, 13, 39, 0, 0, 1-1.0/ 8192, -1.0/ 8192, 1/(1-1.0/ 8192), 1.0/ 4096 }, + { 0x3fff, 86.05, 14, 42, 0, 0, 1-1.0/16384, -1.0/16384, 1/(1-1.0/16384), 1.0/ 8192 }, + { 0x7fff, 92.01, 15, 45, 0, 0, 1-1.0/32768, -1.0/32768, 1/(1-1.0/32768), 1.0/16384 }, + { 0xffff, 98.01, 16, 48, 0, 0, 1-1.0/65536, -1.0/65536, 1/(1-1.0/65536), 1.0/32768 }, +}; + +const double mpeg_audio::scalefactors[64] = { + 2.00000000000000, 1.58740105196820, 1.25992104989487, 1.00000000000000, + 0.79370052598410, 0.62996052494744, 0.50000000000000, 0.39685026299205, + 0.31498026247372, 0.25000000000000, 0.19842513149602, 0.15749013123686, + 0.12500000000000, 0.09921256574801, 0.07874506561843, 0.06250000000000, + 0.04960628287401, 0.03937253280921, 0.03125000000000, 0.02480314143700, + 0.01968626640461, 0.01562500000000, 0.01240157071850, 0.00984313320230, + 0.00781250000000, 0.00620078535925, 0.00492156660115, 0.00390625000000, + 0.00310039267963, 0.00246078330058, 0.00195312500000, 0.00155019633981, + 0.00123039165029, 0.00097656250000, 0.00077509816991, 0.00061519582514, + 0.00048828125000, 0.00038754908495, 0.00030759791257, 0.00024414062500, + 0.00019377454248, 0.00015379895629, 0.00012207031250, 0.00009688727124, + 0.00007689947814, 0.00006103515625, 0.00004844363562, 0.00003844973907, + 0.00003051757812, 0.00002422181781, 0.00001922486954, 0.00001525878906, + 0.00001211090890, 0.00000961243477, 0.00000762939453, 0.00000605545445, + 0.00000480621738, 0.00000381469727, 0.00000302772723, 0.00000240310869, + 0.00000190734863, 0.00000151386361, 0.00000120155435, 0.00000000000000 +}; + +const double mpeg_audio::synthesis_filter[512] = { + +0.000000000, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000030518, + -0.000030518, -0.000030518, -0.000030518, -0.000045776, -0.000045776, -0.000061035, -0.000061035, -0.000076294, + -0.000076294, -0.000091553, -0.000106812, -0.000106812, -0.000122070, -0.000137329, -0.000152588, -0.000167847, + -0.000198364, -0.000213623, -0.000244141, -0.000259399, -0.000289917, -0.000320435, -0.000366211, -0.000396729, + -0.000442505, -0.000473022, -0.000534058, -0.000579834, -0.000625610, -0.000686646, -0.000747681, -0.000808716, + -0.000885010, -0.000961304, -0.001037598, -0.001113892, -0.001205444, -0.001296997, -0.001388550, -0.001480103, + -0.001586914, -0.001693726, -0.001785278, -0.001907349, -0.002014160, -0.002120972, -0.002243042, -0.002349854, + -0.002456665, -0.002578735, -0.002685547, -0.002792358, -0.002899170, -0.002990723, -0.003082275, -0.003173828, + +0.003250122, +0.003326416, +0.003387451, +0.003433228, +0.003463745, +0.003479004, +0.003479004, +0.003463745, + +0.003417969, +0.003372192, +0.003280640, +0.003173828, +0.003051758, +0.002883911, +0.002700806, +0.002487183, + +0.002227783, +0.001937866, +0.001617432, +0.001266479, +0.000869751, +0.000442505, -0.000030518, -0.000549316, + -0.001098633, -0.001693726, -0.002334595, -0.003005981, -0.003723145, -0.004486084, -0.005294800, -0.006118774, + -0.007003784, -0.007919312, -0.008865356, -0.009841919, -0.010848999, -0.011886597, -0.012939453, -0.014022827, + -0.015121460, -0.016235352, -0.017349243, -0.018463135, -0.019577026, -0.020690918, -0.021789550, -0.022857666, + -0.023910522, -0.024932861, -0.025909424, -0.026840210, -0.027725220, -0.028533936, -0.029281616, -0.029937744, + -0.030532837, -0.031005860, -0.031387330, -0.031661987, -0.031814575, -0.031845093, -0.031738280, -0.031478880, + +0.031082153, +0.030517578, +0.029785156, +0.028884888, +0.027801514, +0.026535034, +0.025085450, +0.023422241, + +0.021575928, +0.019531250, +0.017257690, +0.014801025, +0.012115479, +0.009231567, +0.006134033, +0.002822876, + -0.000686646, -0.004394531, -0.008316040, -0.012420654, -0.016708374, -0.021179200, -0.025817871, -0.030609130, + -0.035552980, -0.040634155, -0.045837402, -0.051132202, -0.056533813, -0.061996460, -0.067520140, -0.073059080, + -0.078628540, -0.084182740, -0.089706420, -0.095169070, -0.100540160, -0.105819700, -0.110946655, -0.115921020, + -0.120697020, -0.125259400, -0.129562380, -0.133590700, -0.137298580, -0.140670780, -0.143676760, -0.146255500, + -0.148422240, -0.150115970, -0.151306150, -0.151962280, -0.152069090, -0.151596070, -0.150497440, -0.148773200, + -0.146362300, -0.143264770, -0.139450070, -0.134887700, -0.129577640, -0.123474120, -0.116577150, -0.108856200, + +0.100311280, +0.090927124, +0.080688480, +0.069595340, +0.057617188, +0.044784546, +0.031082153, +0.016510010, + +0.001068115, -0.015228271, -0.032379150, -0.050354004, -0.069168090, -0.088775635, -0.109161380, -0.130310060, + -0.152206420, -0.174789430, -0.198059080, -0.221984860, -0.246505740, -0.271591200, -0.297210700, -0.323318480, + -0.349868770, -0.376800540, -0.404083250, -0.431655880, -0.459472660, -0.487472530, -0.515609740, -0.543823240, + -0.572036740, -0.600219700, -0.628295900, -0.656219500, -0.683914200, -0.711318970, -0.738372800, -0.765029900, + -0.791214000, -0.816864000, -0.841949460, -0.866363500, -0.890090940, -0.913055400, -0.935195900, -0.956481930, + -0.976852400, -0.996246340, -1.014617900, -1.031936600, -1.048156700, -1.063217200, -1.077117900, -1.089782700, + -1.101211500, -1.111373900, -1.120224000, -1.127746600, -1.133926400, -1.138763400, -1.142211900, -1.144287100, + +1.144989000, +1.144287100, +1.142211900, +1.138763400, +1.133926400, +1.127746600, +1.120224000, +1.111373900, + +1.101211500, +1.089782700, +1.077117900, +1.063217200, +1.048156700, +1.031936600, +1.014617900, +0.996246340, + +0.976852400, +0.956481930, +0.935195900, +0.913055400, +0.890090940, +0.866363500, +0.841949460, +0.816864000, + +0.791214000, +0.765029900, +0.738372800, +0.711318970, +0.683914200, +0.656219500, +0.628295900, +0.600219700, + +0.572036740, +0.543823240, +0.515609740, +0.487472530, +0.459472660, +0.431655880, +0.404083250, +0.376800540, + +0.349868770, +0.323318480, +0.297210700, +0.271591200, +0.246505740, +0.221984860, +0.198059080, +0.174789430, + +0.152206420, +0.130310060, +0.109161380, +0.088775635, +0.069168090, +0.050354004, +0.032379150, +0.015228271, + -0.001068115, -0.016510010, -0.031082153, -0.044784546, -0.057617188, -0.069595340, -0.080688480, -0.090927124, + +0.100311280, +0.108856200, +0.116577150, +0.123474120, +0.129577640, +0.134887700, +0.139450070, +0.143264770, + +0.146362300, +0.148773200, +0.150497440, +0.151596070, +0.152069090, +0.151962280, +0.151306150, +0.150115970, + +0.148422240, +0.146255500, +0.143676760, +0.140670780, +0.137298580, +0.133590700, +0.129562380, +0.125259400, + +0.120697020, +0.115921020, +0.110946655, +0.105819700, +0.100540160, +0.095169070, +0.089706420, +0.084182740, + +0.078628540, +0.073059080, +0.067520140, +0.061996460, +0.056533813, +0.051132202, +0.045837402, +0.040634155, + +0.035552980, +0.030609130, +0.025817871, +0.021179200, +0.016708374, +0.012420654, +0.008316040, +0.004394531, + +0.000686646, -0.002822876, -0.006134033, -0.009231567, -0.012115479, -0.014801025, -0.017257690, -0.019531250, + -0.021575928, -0.023422241, -0.025085450, -0.026535034, -0.027801514, -0.028884888, -0.029785156, -0.030517578, + +0.031082153, +0.031478880, +0.031738280, +0.031845093, +0.031814575, +0.031661987, +0.031387330, +0.031005860, + +0.030532837, +0.029937744, +0.029281616, +0.028533936, +0.027725220, +0.026840210, +0.025909424, +0.024932861, + +0.023910522, +0.022857666, +0.021789550, +0.020690918, +0.019577026, +0.018463135, +0.017349243, +0.016235352, + +0.015121460, +0.014022827, +0.012939453, +0.011886597, +0.010848999, +0.009841919, +0.008865356, +0.007919312, + +0.007003784, +0.006118774, +0.005294800, +0.004486084, +0.003723145, +0.003005981, +0.002334595, +0.001693726, + +0.001098633, +0.000549316, +0.000030518, -0.000442505, -0.000869751, -0.001266479, -0.001617432, -0.001937866, + -0.002227783, -0.002487183, -0.002700806, -0.002883911, -0.003051758, -0.003173828, -0.003280640, -0.003372192, + -0.003417969, -0.003463745, -0.003479004, -0.003479004, -0.003463745, -0.003433228, -0.003387451, -0.003326416, + +0.003250122, +0.003173828, +0.003082275, +0.002990723, +0.002899170, +0.002792358, +0.002685547, +0.002578735, + +0.002456665, +0.002349854, +0.002243042, +0.002120972, +0.002014160, +0.001907349, +0.001785278, +0.001693726, + +0.001586914, +0.001480103, +0.001388550, +0.001296997, +0.001205444, +0.001113892, +0.001037598, +0.000961304, + +0.000885010, +0.000808716, +0.000747681, +0.000686646, +0.000625610, +0.000579834, +0.000534058, +0.000473022, + +0.000442505, +0.000396729, +0.000366211, +0.000320435, +0.000289917, +0.000259399, +0.000244141, +0.000213623, + +0.000198364, +0.000167847, +0.000152588, +0.000137329, +0.000122070, +0.000106812, +0.000106812, +0.000091553, + +0.000076294, +0.000076294, +0.000061035, +0.000061035, +0.000045776, +0.000045776, +0.000030518, +0.000030518, + +0.000030518, +0.000030518, +0.000015259, +0.000015259, +0.000015259, +0.000015259, +0.000015259, +0.000015259, +}; + +int mpeg_audio::do_gb_msb(const unsigned char *data, int &pos, int count) +{ + int v = 0; + for(int i=0; i != count; i++) { + v <<= 1; + if(data[pos >> 3] & (0x80 >> (pos & 7))) + v |= 1; + pos++; + } + return v; +} + +int mpeg_audio::do_gb_lsb(const unsigned char *data, int &pos, int count) +{ + int v = 0; + for(int i=0; i != count; i++) { + v <<= 1; + if(data[pos >> 3] & (0x01 << (pos & 7))) + v |= 1; + pos++; + } + return v; +} + +int mpeg_audio::get_band_param(int band) +{ + int bit_count = band_parameter_index_bits_count[param_index][band]; + int index = gb(bit_count); + return band_parameter_indexed_values[param_index][band][index]; +} + +void mpeg_audio::read_band_params() +{ + int band = 0; + + while(band < joint_bands) { + for(int chan=0; chan < channel_count; chan++) + band_param[chan][band] = get_band_param(band); + band++; + } + + while(band < total_bands) { + int val = get_band_param(band); + band_param[0][band] = val; + band_param[1][band] = val; + band++; + } + + while(band < 32) { + band_param[0][band] = 0; + band_param[1][band] = 0; + band++; + } +} + +void mpeg_audio::read_scfci() +{ + memset(scfsi, 0, sizeof(scfsi)); + for(int band=0; band < total_bands; band++) + for(int chan=0; chan < channel_count; chan++) + if(band_param[chan][band]) + scfsi[chan][band] = gb(2); +} + +void mpeg_audio::read_band_amplitude_params() +{ + memset(scf, 0, sizeof(scf)); + for(int band=0; band < total_bands; band++) + for(int chan=0; chan<channel_count; chan++) + if(band_param[chan][band]) { + switch(scfsi[chan][band]) { + case 0: + scf[chan][0][band] = gb(6); + scf[chan][1][band] = gb(6); + scf[chan][2][band] = gb(6); + break; + + case 1: { + int val = gb(6); + scf[chan][0][band] = val; + scf[chan][1][band] = val; + scf[chan][2][band] = gb(6); + break; + } + + case 2: { + int val = gb(6); + scf[chan][0][band] = val; + scf[chan][1][band] = val; + scf[chan][2][band] = val; + break; + } + + case 3: { + scf[chan][0][band] = gb(6); + int val = gb(6); + scf[chan][1][band] = val; + scf[chan][2][band] = val; + break; + } + } + } +} + +void mpeg_audio::build_amplitudes() +{ + memset(amp_values, 0, sizeof(amp_values)); + + for(int band=0; band < total_bands; band++) + for(int chan=0; chan<channel_count; chan++) + if(band_param[chan][band]) + for(int step=0; step<3; step++) + amp_values[chan][step][band] = scalefactors[scf[chan][step][band]]; +} + +void mpeg_audio::read_band_value_triplet(int chan, int band) +{ + double buffer[3]; + + int band_idx = band_param[chan][band]; + switch(band_idx) { + case 0: + bdata[chan][0][band] = 0; + bdata[chan][1][band] = 0; + bdata[chan][2][band] = 0; + return; + + case 1: + case 2: + case 4: { + int modulo = band_infos[band_idx].modulo; + int val = gb(band_infos[band_idx].cube_bits); + buffer[0] = val % modulo; + val = val / modulo; + buffer[1] = val % modulo; + val = val / modulo; + buffer[2] = val % modulo; + break; + } + + default: { + int bits = band_infos[band_idx].bits; + buffer[0] = gb(bits); + buffer[1] = gb(bits); + buffer[2] = gb(bits); + break; + } + } + + double scale = 1 << (band_infos[band_idx].bits - 1); + + bdata[chan][0][band] = ((buffer[0] - scale) / scale + band_infos[band_idx].offset) * band_infos[band_idx].scale; + bdata[chan][1][band] = ((buffer[1] - scale) / scale + band_infos[band_idx].offset) * band_infos[band_idx].scale; + bdata[chan][2][band] = ((buffer[2] - scale) / scale + band_infos[band_idx].offset) * band_infos[band_idx].scale; +} + +void mpeg_audio::build_next_segments(int step) +{ + int band = 0; + while(band < joint_bands) { + for(int chan=0; chan<channel_count; chan++) { + read_band_value_triplet(chan, band); + double amp = amp_values[chan][step][band]; + bdata[chan][0][band] *= amp; + bdata[chan][1][band] *= amp; + bdata[chan][2][band] *= amp; + } + band++; + } + + while(band < joint_bands) { + read_band_value_triplet(0, band); + bdata[1][0][band] = bdata[0][0][band]; + bdata[1][1][band] = bdata[0][1][band]; + bdata[1][2][band] = bdata[0][2][band]; + + for(int chan=0; chan<channel_count; chan++) { + double amp = amp_values[chan][step][band]; + bdata[chan][0][band] *= amp; + bdata[chan][1][band] *= amp; + bdata[chan][2][band] *= amp; + } + band++; + } + + while(band < 32) { + bdata[0][0][band] = 0; + bdata[0][1][band] = 0; + bdata[0][2][band] = 0; + bdata[1][0][band] = 0; + bdata[1][1][band] = 0; + bdata[1][2][band] = 0; + band++; + } +} + +void mpeg_audio::retrieve_subbuffer(int step) +{ + for(int chan=0; chan<channel_count; chan++) + memcpy(subbuffer[chan], bdata[chan][step], 32*sizeof(subbuffer[0][0])); +} + +void mpeg_audio::idct32(const double *input, double *output) +{ + // Simplest idct32 ever, non-fast at all + for(int i=0; i<32; i++) { + double s = 0; + for(int j=0; j<32; j++) + s += input[j] * cos(i*(2*j+1)*M_PI/64); + output[i] = s; + } +} + +void mpeg_audio::resynthesis(const double *input, double *output) +{ + memset(output, 0, 32*sizeof(output[0])); + for(int j=0; j<64*8; j+=64) { + for(int i=0; i<16; i++) + output[i] += input[ i+j]*synthesis_filter[i+j] - input[32-i+j]*synthesis_filter[32+i+j]; + output[16] -= input[16+j]*synthesis_filter[32+16+j]; + for(int i=17; i<32; i++) + output[i] -= input[32-i+j]*synthesis_filter[i+j] + input[ i+j]*synthesis_filter[32+i+j]; + } +} + +void mpeg_audio::scale_and_clamp(const double *input, short *output, int step) +{ + for(int i=0; i<32; i++) { + double val = input[i]*32768 + 0.5; + short cval; + if(val <= -32768) + cval = -32768; + else if(val >= 32767) + cval = 32767; + else + cval = int(val); + *output = cval; + output += step; + } +} diff --git a/src/emu/sound/mpeg_audio.h b/src/emu/sound/mpeg_audio.h new file mode 100644 index 00000000000..0ea2fb367e6 --- /dev/null +++ b/src/emu/sound/mpeg_audio.h @@ -0,0 +1,129 @@ +/*************************************************************************** + + MPEG audio support. Only layer2 and variants for now. + +***************************************************************************/ + +#ifndef __MPEG_AUDIO_H__ +#define __MPEG_AUDIO_H__ + +class mpeg_audio { +public: + // Accepted layers. Beware that AMM is incompatible with L2 (and + // not automatically recognizable) and that 2.5 implies 2. + + enum { + L1 = 1, + L2 = 2, + L2_5 = 4, + L3 = 8, + AMM = 16 + }; + + // base = Start of the mpeg data block + // accepted = Binary or of accepted layers + // lsb_first = Read bits out of bytes lsb-first rather than msb first + // position_align = Position alignment after reading a block (0 = pure bitstream, must be a power of 2 otherwise) + + mpeg_audio(const void *base, unsigned int accepted, bool lsb_first, int position_align); + + // Decode one mpeg buffer. + // pos = position in *bits* relative to base + // limit = maximum accepted position in bits + // output = output samples, interleaved + // 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) + // + // returns true if the buffer was complete and the new position in pos, false otherwise + // + // Sample rate and channels can change every buffer. That's mpeg + // for you. Channels rarely changes, sample rate sometimes do, + // especially in amm samples (drops to half at the end). + // + // One call to output buffer will generate 0 or 1 frame, which is + // 384 samples per channel in layer I and 1152 otherwise (up to + // 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); + + + // Change the base pointer + void set_base(const void *base); + +private: + struct limit_hit {}; + + struct band_info { + int modulo; + double s1; + int bits, cube_bits; + int s4, s5; + double range, s7, scale, offset; + }; + + static const double scalefactors[64]; + static const int sample_rates[8]; + static const int layer2_param_index[2][4][16]; + static const int band_parameter_indexed_values[5][32][17]; + static const int band_parameter_index_bits_count[5][32]; + static const int joint_band_counts[4], total_band_counts[5]; + static const band_info band_infos[18]; + static const double synthesis_filter[512]; + + const UINT8 *base; + int accepted, position_align; + + int sampling_rate, last_frame_number; + int param_index; + + int channel_count, total_bands, joint_bands; + + int band_param[2][32]; + int scfsi[2][32]; + int scf[2][3][32]; + double amp_values[2][3][32]; + double bdata[2][3][32]; + double subbuffer[2][32]; + double audio_buffer[2][32*32]; + int audio_buffer_pos[2]; + + int master_pos; + + int current_pos, current_limit; + + void read_header_amm(bool layer25); + void read_header_mpeg2(bool layer25); + void read_data_mpeg2(); + void decode_mpeg2(short *output, int &output_samples); + + int get_band_param(int band); + void read_band_params(); + void read_scfci(); + void read_band_amplitude_params(); + void read_band_value_triplet(int chan, int band); + void build_amplitudes(); + void build_next_segments(int step); + void retrieve_subbuffer(int step); + void handle_block(int &pos); + void idct32(const double *input, double *output); + void resynthesis(const double *input, double *output); + void scale_and_clamp(const double *input, short *output, int step); + + + static int do_gb_msb(const unsigned char *data, int &pos, int count); + static int do_gb_lsb(const unsigned char *data, int &pos, int count); + + int (*do_gb)(const unsigned char *data, int &pos, int count); + + inline int gb(int count) + { + if(current_pos + count > current_limit) + throw limit_hit(); + + return do_gb(base, current_pos, count); + } +}; + +#endif diff --git a/src/emu/sound/sound.mak b/src/emu/sound/sound.mak index bc1bf26cd8f..2bed0bf3505 100644 --- a/src/emu/sound/sound.mak +++ b/src/emu/sound/sound.mak @@ -752,7 +752,7 @@ endif #------------------------------------------------- ifneq ($(filter YMZ770,$(SOUNDS)),) -SOUNDOBJS += $(SOUNDOBJ)/ymz770.o +SOUNDOBJS += $(SOUNDOBJ)/ymz770.o $(SOUNDOBJ)/mpeg_audio.o endif #------------------------------------------------- diff --git a/src/emu/sound/ymz770.c b/src/emu/sound/ymz770.c index b6aefefb9cf..8e02497536a 100644 --- a/src/emu/sound/ymz770.c +++ b/src/emu/sound/ymz770.c @@ -9,705 +9,11 @@ #include "emu.h" #include "ymz770.h" +#include "mpeg_audio.h" // device type definition const device_type YMZ770 = &device_creator<ymz770_device>; -//************************************************************************** -// Yamaha "AMM" decoder -//************************************************************************** - -class amm { -public: - amm(); - - void init(); - bool run(); - - void set_pointers(UINT8 *ptr, UINT8 *outptr) { data = ptr; result = outptr; size = rsize = 0; } - int get_rsize() { return rsize; } - -private: - struct band_parameter_size { - int band_count; - int s1, s2, s3, s4, s5; - }; - - struct band_info { - int modulo; - double s1; - int bits, cube_bits; - int s4, s5; - double range, s7, scale, offset; - }; - - double amplitude_table[64]; - - static const int sample_rates[8]; - static const int band_parameter_indexed_values[5][32][17]; - static const int band_parameter_index_bits_count[5][32]; - static const band_parameter_size band_parameter_sizes[5]; - static const int init_band_counts[4]; - static const band_info band_infos[18]; - static const double synthesis_filter[512]; - - int sampling_rate, last_frame_number; - int param_index, forced_param_index; - - int channel_count, total_bands, init_bands; - - int band_param[2][32]; - int scfsi[2][32]; - int scalefactors[2][3][32]; - double amp_values[2][3][32]; - double bdata[2][3][32]; - double subbuffer[2][32]; - double audio_buffer[2][32*32]; - int audio_buffer_pos[2]; - - int master_pos; - - void read_header(int &pos); - int get_band_param(int &pos, int band); - void read_band_params(int &pos); - void read_scfci(int &pos); - void read_band_amplitude_params(int &pos); - void read_band_value_triplet(int &pos, int chan, int band); - void build_amplitudes(); - void build_next_segments(int &pos, int step); - void retrieve_subbuffer(int step); - void handle_block(int &pos); - void idct32(const double *input, double *output); - void resynthesis(const double *input, double *output); - void scale_and_clamp(const double *input, int offset, int step); - - UINT8 *data; - int size; - - UINT8 *result; - int rsize; - - int gb(int &pos, int count) - { - int v = 0; - for(int i=0; i != count; i++) { - v <<= 1; - if(data[pos >> 3] & (0x80 >> (pos & 7))) - v |= 1; - pos++; - } - return v; - } - - void w16(int offset, unsigned short value) - { - if (offset > (0x8fe*2)) - { - fatalerror("AMM block decoded to %x bytes, buffer overflow!\n", offset); - } - - *(unsigned short *)(result+offset) = value; - } -}; - -void amm::read_header(int &pos) -{ - int full_rate = gb(pos, 1); - gb(pos, 2); // must be 2 - gb(pos, 1); // unused - int full_packets_count = gb(pos, 4); // max 12 - int srate_index = gb(pos, 2); // max 2 - sampling_rate = srate_index + 4 * (1 - full_rate); - int last_packet_frame_id = gb(pos, 2); // max 2 - last_frame_number = 3*full_packets_count + last_packet_frame_id; - int frame_type = gb(pos, 2); - int init_band_count_index = gb(pos, 2); - int normal_param_index = gb(pos, 3); - gb(pos, 1); // must be zero - param_index = forced_param_index >= 5 ? normal_param_index : forced_param_index; // max 4 - channel_count = frame_type != 3 ? 2 : 1; - total_bands = band_parameter_sizes[param_index].band_count; - init_bands = total_bands; - if(frame_type == 1) - init_bands = init_band_counts[init_band_count_index]; - if(init_bands > total_bands ) - init_bands = total_bands; -} - -const int amm::sample_rates[8] = { 44100, 48000, 32000, 0, 22050, 24000, 16000, 0 }; - -const int amm::band_parameter_indexed_values[5][32][17] = { - { - { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, - { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, - { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - }, - { - { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, - { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, - { 0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - }, - { - { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - }, - { - { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - }, - { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, 1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, - } -}; - -const int amm::band_parameter_index_bits_count[5][32] = { - { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 0, 0, 0, 0, 0, }, - { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 0, 0, }, - { 4, 4, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - { 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, }, -}; - -const amm::band_parameter_size amm::band_parameter_sizes[5] = { - { 27, 88, 104, 120, 135, 147 }, - { 30, 94, 110, 126, 141, 153 }, - { 8, 26, 40, 52, 52, 52 }, - { 12, 38, 52, 64, 76, 76 }, - { 30, 75, 91, 103, 114, 122 }, -}; - -const int amm::init_band_counts[4] = { 4, 8, 12, 16 }; - -const amm::band_info amm::band_infos[18] = { - { 0x0000, 0.00, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0x0003, 7.00, 2, 5, 3, 9, 1-1.0/ 4, -1.0/ 4, 1/(1-1.0/ 4), 1.0/ 2 }, - { 0x0005, 11.00, 3, 7, 5, 25, 1-3.0/ 8, -3.0/ 8, 1/(1-3.0/ 8), 1.0/ 2 }, - { 0x0007, 16.00, 3, 9, 0, 0, 1-1.0/ 8, -1.0/ 8, 1/(1-1.0/ 8), 1.0/ 4 }, - { 0x0009, 20.84, 4, 10, 9, 81, 1-7.0/ 16, -7.0/ 16, 1/(1-7.0/ 16), 1.0/ 2 }, - { 0x000f, 25.28, 4, 12, 0, 0, 1-1.0/ 16, -1.0/ 16, 1/(1-1.0/ 16), 1.0/ 8 }, - { 0x001f, 31.59, 5, 15, 0, 0, 1-1.0/ 32, -1.0/ 32, 1/(1-1.0/ 32), 1.0/ 16 }, - { 0x003f, 37.75, 6, 18, 0, 0, 1-1.0/ 64, -1.0/ 64, 1/(1-1.0/ 64), 1.0/ 32 }, - { 0x007f, 43.84, 7, 21, 0, 0, 1-1.0/ 128, -1.0/ 128, 1/(1-1.0/ 128), 1.0/ 64 }, - { 0x00ff, 49.89, 8, 24, 0, 0, 1-1.0/ 256, -1.0/ 256, 1/(1-1.0/ 256), 1.0/ 128 }, - { 0x01ff, 55.93, 9, 27, 0, 0, 1-1.0/ 512, -1.0/ 512, 1/(1-1.0/ 512), 1.0/ 256 }, - { 0x03ff, 61.96, 10, 30, 0, 0, 1-1.0/ 1024, -1.0/ 1024, 1/(1-1.0/ 1024), 1.0/ 512 }, - { 0x07ff, 67.98, 11, 33, 0, 0, 1-1.0/ 2048, -1.0/ 2048, 1/(1-1.0/ 2048), 1.0/ 1024 }, - { 0x0fff, 74.01, 12, 36, 0, 0, 1-1.0/ 4096, -1.0/ 4096, 1/(1-1.0/ 4096), 1.0/ 2048 }, - { 0x1fff, 80.03, 13, 39, 0, 0, 1-1.0/ 8192, -1.0/ 8192, 1/(1-1.0/ 8192), 1.0/ 4096 }, - { 0x3fff, 86.05, 14, 42, 0, 0, 1-1.0/16384, -1.0/16384, 1/(1-1.0/16384), 1.0/ 8192 }, - { 0x7fff, 92.01, 15, 45, 0, 0, 1-1.0/32768, -1.0/32768, 1/(1-1.0/32768), 1.0/16384 }, - { 0xffff, 98.01, 16, 48, 0, 0, 1-1.0/65536, -1.0/65536, 1/(1-1.0/65536), 1.0/32768 }, -}; - -const double amm::synthesis_filter[512] = { - +0.000000000, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000030518, - -0.000030518, -0.000030518, -0.000030518, -0.000045776, -0.000045776, -0.000061035, -0.000061035, -0.000076294, - -0.000076294, -0.000091553, -0.000106812, -0.000106812, -0.000122070, -0.000137329, -0.000152588, -0.000167847, - -0.000198364, -0.000213623, -0.000244141, -0.000259399, -0.000289917, -0.000320435, -0.000366211, -0.000396729, - -0.000442505, -0.000473022, -0.000534058, -0.000579834, -0.000625610, -0.000686646, -0.000747681, -0.000808716, - -0.000885010, -0.000961304, -0.001037598, -0.001113892, -0.001205444, -0.001296997, -0.001388550, -0.001480103, - -0.001586914, -0.001693726, -0.001785278, -0.001907349, -0.002014160, -0.002120972, -0.002243042, -0.002349854, - -0.002456665, -0.002578735, -0.002685547, -0.002792358, -0.002899170, -0.002990723, -0.003082275, -0.003173828, - +0.003250122, +0.003326416, +0.003387451, +0.003433228, +0.003463745, +0.003479004, +0.003479004, +0.003463745, - +0.003417969, +0.003372192, +0.003280640, +0.003173828, +0.003051758, +0.002883911, +0.002700806, +0.002487183, - +0.002227783, +0.001937866, +0.001617432, +0.001266479, +0.000869751, +0.000442505, -0.000030518, -0.000549316, - -0.001098633, -0.001693726, -0.002334595, -0.003005981, -0.003723145, -0.004486084, -0.005294800, -0.006118774, - -0.007003784, -0.007919312, -0.008865356, -0.009841919, -0.010848999, -0.011886597, -0.012939453, -0.014022827, - -0.015121460, -0.016235352, -0.017349243, -0.018463135, -0.019577026, -0.020690918, -0.021789550, -0.022857666, - -0.023910522, -0.024932861, -0.025909424, -0.026840210, -0.027725220, -0.028533936, -0.029281616, -0.029937744, - -0.030532837, -0.031005860, -0.031387330, -0.031661987, -0.031814575, -0.031845093, -0.031738280, -0.031478880, - +0.031082153, +0.030517578, +0.029785156, +0.028884888, +0.027801514, +0.026535034, +0.025085450, +0.023422241, - +0.021575928, +0.019531250, +0.017257690, +0.014801025, +0.012115479, +0.009231567, +0.006134033, +0.002822876, - -0.000686646, -0.004394531, -0.008316040, -0.012420654, -0.016708374, -0.021179200, -0.025817871, -0.030609130, - -0.035552980, -0.040634155, -0.045837402, -0.051132202, -0.056533813, -0.061996460, -0.067520140, -0.073059080, - -0.078628540, -0.084182740, -0.089706420, -0.095169070, -0.100540160, -0.105819700, -0.110946655, -0.115921020, - -0.120697020, -0.125259400, -0.129562380, -0.133590700, -0.137298580, -0.140670780, -0.143676760, -0.146255500, - -0.148422240, -0.150115970, -0.151306150, -0.151962280, -0.152069090, -0.151596070, -0.150497440, -0.148773200, - -0.146362300, -0.143264770, -0.139450070, -0.134887700, -0.129577640, -0.123474120, -0.116577150, -0.108856200, - +0.100311280, +0.090927124, +0.080688480, +0.069595340, +0.057617188, +0.044784546, +0.031082153, +0.016510010, - +0.001068115, -0.015228271, -0.032379150, -0.050354004, -0.069168090, -0.088775635, -0.109161380, -0.130310060, - -0.152206420, -0.174789430, -0.198059080, -0.221984860, -0.246505740, -0.271591200, -0.297210700, -0.323318480, - -0.349868770, -0.376800540, -0.404083250, -0.431655880, -0.459472660, -0.487472530, -0.515609740, -0.543823240, - -0.572036740, -0.600219700, -0.628295900, -0.656219500, -0.683914200, -0.711318970, -0.738372800, -0.765029900, - -0.791214000, -0.816864000, -0.841949460, -0.866363500, -0.890090940, -0.913055400, -0.935195900, -0.956481930, - -0.976852400, -0.996246340, -1.014617900, -1.031936600, -1.048156700, -1.063217200, -1.077117900, -1.089782700, - -1.101211500, -1.111373900, -1.120224000, -1.127746600, -1.133926400, -1.138763400, -1.142211900, -1.144287100, - +1.144989000, +1.144287100, +1.142211900, +1.138763400, +1.133926400, +1.127746600, +1.120224000, +1.111373900, - +1.101211500, +1.089782700, +1.077117900, +1.063217200, +1.048156700, +1.031936600, +1.014617900, +0.996246340, - +0.976852400, +0.956481930, +0.935195900, +0.913055400, +0.890090940, +0.866363500, +0.841949460, +0.816864000, - +0.791214000, +0.765029900, +0.738372800, +0.711318970, +0.683914200, +0.656219500, +0.628295900, +0.600219700, - +0.572036740, +0.543823240, +0.515609740, +0.487472530, +0.459472660, +0.431655880, +0.404083250, +0.376800540, - +0.349868770, +0.323318480, +0.297210700, +0.271591200, +0.246505740, +0.221984860, +0.198059080, +0.174789430, - +0.152206420, +0.130310060, +0.109161380, +0.088775635, +0.069168090, +0.050354004, +0.032379150, +0.015228271, - -0.001068115, -0.016510010, -0.031082153, -0.044784546, -0.057617188, -0.069595340, -0.080688480, -0.090927124, - +0.100311280, +0.108856200, +0.116577150, +0.123474120, +0.129577640, +0.134887700, +0.139450070, +0.143264770, - +0.146362300, +0.148773200, +0.150497440, +0.151596070, +0.152069090, +0.151962280, +0.151306150, +0.150115970, - +0.148422240, +0.146255500, +0.143676760, +0.140670780, +0.137298580, +0.133590700, +0.129562380, +0.125259400, - +0.120697020, +0.115921020, +0.110946655, +0.105819700, +0.100540160, +0.095169070, +0.089706420, +0.084182740, - +0.078628540, +0.073059080, +0.067520140, +0.061996460, +0.056533813, +0.051132202, +0.045837402, +0.040634155, - +0.035552980, +0.030609130, +0.025817871, +0.021179200, +0.016708374, +0.012420654, +0.008316040, +0.004394531, - +0.000686646, -0.002822876, -0.006134033, -0.009231567, -0.012115479, -0.014801025, -0.017257690, -0.019531250, - -0.021575928, -0.023422241, -0.025085450, -0.026535034, -0.027801514, -0.028884888, -0.029785156, -0.030517578, - +0.031082153, +0.031478880, +0.031738280, +0.031845093, +0.031814575, +0.031661987, +0.031387330, +0.031005860, - +0.030532837, +0.029937744, +0.029281616, +0.028533936, +0.027725220, +0.026840210, +0.025909424, +0.024932861, - +0.023910522, +0.022857666, +0.021789550, +0.020690918, +0.019577026, +0.018463135, +0.017349243, +0.016235352, - +0.015121460, +0.014022827, +0.012939453, +0.011886597, +0.010848999, +0.009841919, +0.008865356, +0.007919312, - +0.007003784, +0.006118774, +0.005294800, +0.004486084, +0.003723145, +0.003005981, +0.002334595, +0.001693726, - +0.001098633, +0.000549316, +0.000030518, -0.000442505, -0.000869751, -0.001266479, -0.001617432, -0.001937866, - -0.002227783, -0.002487183, -0.002700806, -0.002883911, -0.003051758, -0.003173828, -0.003280640, -0.003372192, - -0.003417969, -0.003463745, -0.003479004, -0.003479004, -0.003463745, -0.003433228, -0.003387451, -0.003326416, - +0.003250122, +0.003173828, +0.003082275, +0.002990723, +0.002899170, +0.002792358, +0.002685547, +0.002578735, - +0.002456665, +0.002349854, +0.002243042, +0.002120972, +0.002014160, +0.001907349, +0.001785278, +0.001693726, - +0.001586914, +0.001480103, +0.001388550, +0.001296997, +0.001205444, +0.001113892, +0.001037598, +0.000961304, - +0.000885010, +0.000808716, +0.000747681, +0.000686646, +0.000625610, +0.000579834, +0.000534058, +0.000473022, - +0.000442505, +0.000396729, +0.000366211, +0.000320435, +0.000289917, +0.000259399, +0.000244141, +0.000213623, - +0.000198364, +0.000167847, +0.000152588, +0.000137329, +0.000122070, +0.000106812, +0.000106812, +0.000091553, - +0.000076294, +0.000076294, +0.000061035, +0.000061035, +0.000045776, +0.000045776, +0.000030518, +0.000030518, - +0.000030518, +0.000030518, +0.000015259, +0.000015259, +0.000015259, +0.000015259, +0.000015259, +0.000015259, -}; - -int amm::get_band_param(int &pos, int band) -{ - int bit_count = band_parameter_index_bits_count[param_index][band]; - int index = gb(pos, bit_count); - return band_parameter_indexed_values[param_index][band][index]; -} - -void amm::read_band_params(int &pos) -{ - int band = 0; - - while(band < init_bands) { - for(int chan=0; chan < channel_count; chan++) - band_param[chan][band] = get_band_param(pos, band); - band++; - } - - while(band < total_bands) { - int val = get_band_param(pos, band); - band_param[0][band] = val; - band_param[1][band] = val; - band++; - } - - while(band < 32) { - band_param[0][band] = 0; - band_param[1][band] = 0; - band++; - } -} - -void amm::read_scfci(int &pos) -{ - memset(scfsi, 0, sizeof(scfsi)); - for(int band=0; band < total_bands; band++) - for(int chan=0; chan < channel_count; chan++) - if(band_param[chan][band]) - scfsi[chan][band] = gb(pos, 2); -} - -void amm::read_band_amplitude_params(int &pos) -{ - memset(scalefactors, 0, sizeof(scalefactors)); - for(int band=0; band < total_bands; band++) - for(int chan=0; chan<channel_count; chan++) - if(band_param[chan][band]) { - switch(scfsi[chan][band]) { - case 0: - scalefactors[chan][0][band] = gb(pos, 6); - scalefactors[chan][1][band] = gb(pos, 6); - scalefactors[chan][2][band] = gb(pos, 6); - break; - - case 1: { - int val = gb(pos, 6); - scalefactors[chan][0][band] = val; - scalefactors[chan][1][band] = val; - scalefactors[chan][2][band] = gb(pos, 6); - break; - } - - case 2: { - int val = gb(pos, 6); - scalefactors[chan][0][band] = val; - scalefactors[chan][1][band] = val; - scalefactors[chan][2][band] = val; - break; - } - - case 3: { - scalefactors[chan][0][band] = gb(pos, 6); - int val = gb(pos, 6); - scalefactors[chan][1][band] = val; - scalefactors[chan][2][band] = val; - break; - } - } - } -} - -void amm::build_amplitudes() -{ - memset(amp_values, 0, sizeof(amp_values)); - - for(int band=0; band < total_bands; band++) - for(int chan=0; chan<channel_count; chan++) - if(band_param[chan][band]) - for(int step=0; step<3; step++) - amp_values[chan][step][band] = amplitude_table[scalefactors[chan][step][band]]; -} - -void amm::read_band_value_triplet(int &pos, int chan, int band) -{ - double buffer[3]; - - int band_idx = band_param[chan][band]; - switch(band_idx) { - case 0: - bdata[chan][0][band] = 0; - bdata[chan][1][band] = 0; - bdata[chan][2][band] = 0; - return; - - case 1: - case 2: - case 4: { - int modulo = band_infos[band_idx].modulo; - int val = gb(pos, band_infos[band_idx].cube_bits); - buffer[0] = val % modulo; - val = val / modulo; - buffer[1] = val % modulo; - val = val / modulo; - buffer[2] = val % modulo; - break; - } - - default: { - int bits = band_infos[band_idx].bits; - buffer[0] = gb(pos, bits); - buffer[1] = gb(pos, bits); - buffer[2] = gb(pos, bits); - break; - } - } - - double scale = 1 << (band_infos[band_idx].bits - 1); - - bdata[chan][0][band] = ((buffer[0] - scale) / scale + band_infos[band_idx].offset) * band_infos[band_idx].scale; - bdata[chan][1][band] = ((buffer[1] - scale) / scale + band_infos[band_idx].offset) * band_infos[band_idx].scale; - bdata[chan][2][band] = ((buffer[2] - scale) / scale + band_infos[band_idx].offset) * band_infos[band_idx].scale; -} - -void amm::build_next_segments(int &pos, int step) -{ - int band = 0; - while(band < init_bands) { - for(int chan=0; chan<channel_count; chan++) { - read_band_value_triplet(pos, chan, band); - double amp = amp_values[chan][step][band]; - bdata[chan][0][band] *= amp; - bdata[chan][1][band] *= amp; - bdata[chan][2][band] *= amp; - } - band++; - } - - while(band < init_bands) { - read_band_value_triplet(pos, 0, band); - bdata[1][0][band] = bdata[0][0][band]; - bdata[1][1][band] = bdata[0][1][band]; - bdata[1][2][band] = bdata[0][2][band]; - - for(int chan=0; chan<channel_count; chan++) { - double amp = amp_values[chan][step][band]; - bdata[chan][0][band] *= amp; - bdata[chan][1][band] *= amp; - bdata[chan][2][band] *= amp; - } - band++; - } - - while(band < 32) { - bdata[0][0][band] = 0; - bdata[0][1][band] = 0; - bdata[0][2][band] = 0; - bdata[1][0][band] = 0; - bdata[1][1][band] = 0; - bdata[1][2][band] = 0; - band++; - } -} - -void amm::retrieve_subbuffer(int step) -{ - for(int chan=0; chan<channel_count; chan++) - memcpy(subbuffer[chan], bdata[chan][step], 32*sizeof(subbuffer[0][0])); -} - -void amm::idct32(const double *input, double *output) -{ - // Simplest idct32 ever, non-fast at all - for(int i=0; i<32; i++) { - double s = 0; - for(int j=0; j<32; j++) - s += input[j] * cos(i*(2*j+1)*M_PI/64); - output[i] = s; - } -} - -void amm::resynthesis(const double *input, double *output) -{ - memset(output, 0, 32*sizeof(output[0])); - for(int j=0; j<64*8; j+=64) { - for(int i=0; i<16; i++) { - output[ i] += input[ i+j]*synthesis_filter[ i+j] - input[32-i+j]*synthesis_filter[32+i+j]; - } - output[16] -= input[16+j]*synthesis_filter[32+16+j]; - for(int i=17; i<32; i++) { - output[i] -= input[32-i+j]*synthesis_filter[i+j] + input[i+j]*synthesis_filter[32+i+j]; - } - } -} - -void amm::scale_and_clamp(const double *input, int offset, int step) -{ - for(int i=0; i<32; i++) { - double val = input[i]*32768 + 0.5; - short cval; - if(val <= -32768) - cval = -32768; - else if(val >= 32767) - cval = 32767; - else - cval = int(val); - w16(offset, cval); - offset += step; - } -} - -amm::amm() -{ - forced_param_index = 5; - - for(int i=0; i<63; i++) - amplitude_table[i] = pow(2, (3-i)/3.0); - amplitude_table[63] = 1e-20; - - memset(audio_buffer, 0, sizeof(audio_buffer)); - audio_buffer_pos[0] = 16*32; - audio_buffer_pos[1] = 16*32; -} - -void amm::handle_block(int &pos) -{ - gb(pos, 12); // Must be 0xfff -// printf("sync: %03x\n", h); - read_header(pos); -// printf("sample rate: %d\n", sample_rates[sampling_rate]); - read_band_params(pos); - read_scfci(pos); - read_band_amplitude_params(pos); - build_amplitudes(); - - // Supposed to stop at last_frame_number when it's not 12*3+2 = 38 - for(int upper_step = 0; upper_step<3; upper_step++) - for(int middle_step = 0; middle_step < 4; middle_step++) { - build_next_segments(pos, upper_step); - for(int lower_step = 0; lower_step < 3; lower_step++) { - retrieve_subbuffer(lower_step); - - int base_offset = rsize; - for(int chan=0; chan<channel_count; chan++) { - double resynthesis_buffer[32]; - idct32(subbuffer[chan], audio_buffer[chan] + audio_buffer_pos[chan]); - resynthesis(audio_buffer[chan] + audio_buffer_pos[chan] + 16, resynthesis_buffer); - scale_and_clamp(resynthesis_buffer, base_offset+2*chan, 2*channel_count); - audio_buffer_pos[chan] -= 32; - if(audio_buffer_pos[chan]<0) { - memmove(audio_buffer[chan]+17*32, audio_buffer[chan], 15*32*sizeof(audio_buffer[chan][0])); - audio_buffer_pos[chan] = 16*32; - } - } - rsize += 32*2*channel_count; - } - } - pos = (pos+7) & ~7; -} - -void amm::init() -{ - master_pos = 0; -} - -// returns true if this is the last block -bool amm::run() -{ - rsize = 0; - handle_block(master_pos); - - // "last_frame_number" for the current chunk is 36 means there are more segments, otherwise not - if (last_frame_number == 36) - { - return false; - } - - return true; -} - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - //------------------------------------------------- // ymz770_device - constructor //------------------------------------------------- @@ -725,15 +31,16 @@ void ymz770_device::device_start() { // create the stream m_stream = machine().sound().stream_alloc(*this, 0, 2, 16000, this); + rom_base = device().machine().root_device().memregion(":ymz770")->base(); + rom_size = device().machine().root_device().memregion(":ymz770")->bytes() * 8; for (int i = 0; i < 8; i++) { channels[i].is_playing = false; channels[i].is_seq_playing = false; - channels[i].decoder = new amm; + channels[i].decoder = new mpeg_audio(rom_base, mpeg_audio::AMM, false, 0); } - rom_base = device().machine().root_device().memregion(":ymz770")->base(); save_item(NAME(cur_reg)); for (int i = 0; i < 8; i++) @@ -746,6 +53,7 @@ void ymz770_device::device_start() save_item(NAME(channels[i].last_block), i); save_item(NAME(channels[i].output_remaining), i); save_item(NAME(channels[i].output_ptr), i); + save_item(NAME(channels[i].pptr), i); save_item(NAME(channels[i].sequence), i); save_item(NAME(channels[i].seqcontrol), i); save_item(NAME(channels[i].seqdelay), i); @@ -839,15 +147,13 @@ void ymz770_device::sound_stream_update(sound_stream &stream, stream_sample_t ** } else { + retry: if (channels[ch].last_block) { if (channels[ch].control & 1) { UINT8 phrase = channels[ch].phrase; - UINT32 pptr = rom_base[(4*phrase)+1]<<16 | rom_base[(4*phrase)+2]<<8 | rom_base[(4*phrase)+3]; - - channels[ch].decoder->set_pointers(&rom_base[pptr], (UINT8 *)&channels[ch].output_data[0]); - channels[ch].decoder->init(); + channels[ch].pptr = 8*(rom_base[(4*phrase)+1]<<16 | rom_base[(4*phrase)+2]<<8 | rom_base[(4*phrase)+3]); } else { @@ -857,8 +163,20 @@ void ymz770_device::sound_stream_update(sound_stream &stream, stream_sample_t ** if (channels[ch].is_playing) { - channels[ch].last_block = channels[ch].decoder->run(); - channels[ch].output_remaining = (channels[ch].decoder->get_rsize()/2)-1; + int sample_rate, channel_count; + if(!channels[ch].decoder->decode_buffer(channels[ch].pptr, + rom_size, + channels[ch].output_data, + channels[ch].output_remaining, + sample_rate, + channel_count)) + { + channels[ch].last_block = true; + goto retry; + } + + channels[ch].last_block = channels[ch].output_remaining < 1152; + channels[ch].output_remaining--; channels[ch].output_ptr = 1; mix += (channels[ch].output_data[0]*2*channels[ch].volume); @@ -913,10 +231,7 @@ void ymz770_device::internal_reg_write(int offset, UINT8 data) if (data & 6) { UINT8 phrase = channels[voice].phrase; - UINT32 pptr = rom_base[(4*phrase)+1]<<16 | rom_base[(4*phrase)+2]<<8 | rom_base[(4*phrase)+3]; - - channels[voice].decoder->set_pointers(&rom_base[pptr], (UINT8 *)&channels[voice].output_data[0]); - channels[voice].decoder->init(); + channels[voice].pptr = 8*(rom_base[(4*phrase)+1]<<16 | rom_base[(4*phrase)+2]<<8 | rom_base[(4*phrase)+3]); channels[voice].output_remaining = 0; channels[voice].output_ptr = 0; channels[voice].last_block = false; diff --git a/src/emu/sound/ymz770.h b/src/emu/sound/ymz770.h index ea0da561a9b..cfacdcea874 100644 --- a/src/emu/sound/ymz770.h +++ b/src/emu/sound/ymz770.h @@ -28,7 +28,7 @@ //************************************************************************** // forward definition -class amm; +class mpeg_audio; // ======================> ymz770_device @@ -43,11 +43,12 @@ class ymz770_device : public device_t, public device_sound_interface bool is_playing, last_block; - amm *decoder; + mpeg_audio *decoder; - INT16 output_data[0x8fe]; + INT16 output_data[1152]; int output_remaining; int output_ptr; + int pptr; UINT8 sequence; UINT8 seqcontrol; @@ -80,6 +81,7 @@ protected: // data UINT8 cur_reg; UINT8 *rom_base; + int rom_size; ymz_channel channels[8]; }; diff --git a/src/mame/audio/dsbz80.c b/src/mame/audio/dsbz80.c index 32e45d9d20d..ec0ecf72cd9 100644 --- a/src/mame/audio/dsbz80.c +++ b/src/mame/audio/dsbz80.c @@ -30,15 +30,9 @@ ADDRESS_MAP_END MACHINE_CONFIG_FRAGMENT( dsbz80 ) - MCFG_CPU_ADD(Z80_TAG, Z80, 1000000) /* unknown clock, but probably pretty slow considering the z80 does like nothing */ + MCFG_CPU_ADD(Z80_TAG, Z80, 4000000) /* unknown clock, but probably pretty slow considering the z80 does like nothing */ MCFG_CPU_PROGRAM_MAP(dsbz80_map) MCFG_CPU_IO_MAP(dsbz80io_map) -#if 0 - MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") - MCFG_YMZ770_ADD(YMZ770_TAG, 8000000) /* clock ignored for this */ - MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) - MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) -#endif MACHINE_CONFIG_END //************************************************************************** @@ -68,8 +62,8 @@ machine_config_constructor dsbz80_device::device_mconfig_additions() const dsbz80_device::dsbz80_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, DSBZ80, "Sega Z80-based Digital Sound Board", tag, owner, clock), - m_ourcpu(*this, Z80_TAG), - m_ymz770(*this, YMZ770_TAG) + device_sound_interface(mconfig, *this), + m_ourcpu(*this, Z80_TAG) { } @@ -79,6 +73,9 @@ dsbz80_device::dsbz80_device(const machine_config &mconfig, const char *tag, dev void dsbz80_device::device_start() { + UINT8 *rom_base = machine().root_device().memregion("mpeg")->base(); + decoder = new mpeg_audio(rom_base, mpeg_audio::L2, false, 0); + machine().sound().stream_alloc(*this, 0, 2, 32000, this); } //------------------------------------------------- @@ -90,6 +87,9 @@ void dsbz80_device::device_reset() m_dsb_latch = 0; status = 1; start = end = 0; + audio_pos = audio_avail = 0; + memset(audio_buf, 0, sizeof(audio_buf)); + mp_state = 0; } WRITE8_MEMBER(dsbz80_device::latch_w) @@ -97,13 +97,13 @@ WRITE8_MEMBER(dsbz80_device::latch_w) m_ourcpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); m_dsb_latch = data; status |= 2; -// printf("%02x to DSB latch\n", data); +// printf("%02x to DSB latch\n", data); } READ8_MEMBER(dsbz80_device::latch_r) { m_ourcpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); -// printf("DSB Z80 read %02x\n", m_dsb_latch); +// printf("DSB Z80 read %02x\n", m_dsb_latch); status &= ~2; return m_dsb_latch; } @@ -114,27 +114,22 @@ WRITE8_MEMBER(dsbz80_device::mpeg_trigger_w) if (data == 0) // stop { -// MPEG_Stop_Playing(); -// printf("MPEG stop\n"); + mp_state = 0; + audio_pos = audio_avail = 0; } else if (data == 1) // play without loop { -// MPEG_Set_Loop(NULL, 0); -// MPEG_Play_Memory(ROM + mp_start, mp_end-mp_start); -// printf("MPEG start, one-shot from %x\n", mp_start); + mp_pos = mp_start*8; } else if (data == 2) // play with loop { -// MPEG_Play_Memory(ROM + mp_start, mp_end-mp_start); -// printf("MPEG start, loop from %x\n", mp_start); + mp_pos = mp_start*8; } } READ8_MEMBER(dsbz80_device::mpeg_pos_r) { - int mp_prg = 0; //MPEG_Get_Progress(); // returns the byte offset currently playing - - mp_prg += mp_start; + int mp_prg = mp_pos >> 3; switch (offset) { @@ -153,7 +148,7 @@ READ8_MEMBER(dsbz80_device::mpeg_pos_r) get latched. When the current stream ends, the MPEG hardware starts playing immediately from the latched start and end position. In this way, the Z80 enforces looping where appropriate and multi-part songs in other cases - (song #16 is a good example) + (song #16 is a good example) */ WRITE8_MEMBER(dsbz80_device::mpeg_start_w) @@ -182,11 +177,11 @@ WRITE8_MEMBER(dsbz80_device::mpeg_start_w) // SWA: if loop end is zero, it means "keep previous end marker" if (lp_end == 0) { -// MPEG_Set_Loop(ROM + lp_start, mp_end-lp_start); +// MPEG_Set_Loop(ROM + lp_start, mp_end-lp_start); } else { -// MPEG_Set_Loop(ROM + lp_start, lp_end-lp_start); +// MPEG_Set_Loop(ROM + lp_start, lp_end-lp_start); } } break; @@ -216,7 +211,7 @@ WRITE8_MEMBER(dsbz80_device::mpeg_end_w) else { lp_end = end; -// MPEG_Set_Loop(ROM + lp_start, lp_end-lp_start); +// MPEG_Set_Loop(ROM + lp_start, lp_end-lp_start); } break; } @@ -229,7 +224,7 @@ WRITE8_MEMBER(dsbz80_device::mpeg_volume_w) WRITE8_MEMBER(dsbz80_device::mpeg_stereo_w) { - mp_pan = data & 3; + mp_pan = data & 3; // 0 = stereo, 1 = left on both channels, 2 = right on both channels } READ8_MEMBER(dsbz80_device::status_r) @@ -240,3 +235,83 @@ READ8_MEMBER(dsbz80_device::status_r) // SWA requires that status & 0x38 = 0 or else it loops endlessly... return status; } + +void dsbz80_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +{ + stream_sample_t *out_l = outputs[0]; + stream_sample_t *out_r = outputs[1]; + + for(;;) + { + while(samples && audio_pos < audio_avail) + { + switch (mp_pan) + { + case 0: // stereo + *out_l++ = audio_buf[audio_pos*2]; + *out_r++ = audio_buf[audio_pos*2+1]; + break; + + case 1: // left only + *out_l++ = audio_buf[audio_pos*2]; + *out_r++ = audio_buf[audio_pos*2]; + break; + + case 2: // right only + *out_l++ = audio_buf[audio_pos*2+1]; + *out_r++ = audio_buf[audio_pos*2+1]; + break; + } + audio_pos++; + samples--; + } + + if(!samples) + { + break; + } + + if(mp_state == 0) + { + for(int i=0; i != samples; i++) + { + *out_l++ = 0; + *out_r++ = 0; + } + break; + + } + else + { + int sample_rate, channel_count; + bool ok = decoder->decode_buffer(mp_pos, mp_end*8, audio_buf, audio_avail, sample_rate, channel_count); + + if (ok) + { + audio_pos = 0; + } + else + { + if(mp_state == 2) + { + if (mp_pos == lp_start*8) + { + // We're looping on un-decodable crap, abort abort abort + mp_state = 0; + } + mp_pos = lp_start*8; + + if (lp_end) + { + mp_end = lp_end; + } + } + else + { + mp_state = 0; + } + } + } + } +} + diff --git a/src/mame/audio/dsbz80.h b/src/mame/audio/dsbz80.h index bd42c721ddf..47560e63870 100644 --- a/src/mame/audio/dsbz80.h +++ b/src/mame/audio/dsbz80.h @@ -5,7 +5,7 @@ #include "emu.h" #include "cpu/z80/z80.h" -#include "sound/ymz770.h" +#include "sound/mpeg_audio.h" #define DSBZ80_TAG "dsbz80" @@ -16,7 +16,7 @@ // TYPE DEFINITIONS //************************************************************************** -class dsbz80_device : public device_t +class dsbz80_device : public device_t, public device_sound_interface { public: // construction/destruction @@ -28,7 +28,6 @@ public: DECLARE_WRITE8_MEMBER(latch_w); required_device<cpu_device> m_ourcpu; - optional_device<ymz770_device> m_ymz770; DECLARE_WRITE8_MEMBER(mpeg_trigger_w); DECLARE_WRITE8_MEMBER(mpeg_start_w); @@ -44,10 +43,16 @@ protected: virtual void device_start(); virtual void device_reset(); + virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); + private: + mpeg_audio *decoder; + INT16 audio_buf[1152*2]; UINT8 m_dsb_latch; UINT32 mp_start, mp_end, mp_vol, mp_pan, mp_state, lp_start, lp_end, start, end; + int mp_pos, audio_pos, audio_avail; int status; + int getbit(); }; diff --git a/src/mame/drivers/model1.c b/src/mame/drivers/model1.c index cf9cd42e2ee..cf1b2c8a444 100644 --- a/src/mame/drivers/model1.c +++ b/src/mame/drivers/model1.c @@ -867,11 +867,28 @@ WRITE16_MEMBER(model1_state::snd_latch_to_68k_w) m_fifo_wptr++; if (m_fifo_wptr >= ARRAY_LENGTH(m_to_68k)) m_fifo_wptr = 0; + if (data == 0xae) + { + m_snd_cmd_state = 0; + } + if (m_dsbz80 != NULL) { - m_dsbz80->latch_w(space, 0, data); +// printf("%d: %02x (last %02x)\n", m_snd_cmd_state, data, m_last_snd_cmd); + // HACK: on h/w, who filters out commands the DSB shouldn't see? Need a wiring diagram. + if ((m_snd_cmd_state == 2) && (m_last_snd_cmd == 0x50)) + { + m_dsbz80->latch_w(space, 0, data); + } + else // keep in sync but send a "don't care" + { + m_dsbz80->latch_w(space, 0, 0x70); + } } + m_last_snd_cmd = data; + m_snd_cmd_state++; + // signal the 68000 that there's data waiting machine().device("audiocpu")->execute().set_input_line(2, HOLD_LINE); // give the 68k time to reply @@ -1356,7 +1373,7 @@ ROM_START( swa ) ROM_REGION( 0x20000, "mpegcpu", 0 ) /* Z80 DSB code */ ROM_LOAD( "epr-16471.bin", 0x000000, 0x020000, CRC(f4ee84a4) SHA1(f12b214e6f195b0e5f49ba9f41d8e54bfcea9acc) ) - ROM_REGION( 0x400000, "ymz770", 0 ) /* DSB MPEG data */ + ROM_REGION( 0x400000, "mpeg", 0 ) /* DSB MPEG data */ ROM_LOAD( "mpr-16514.bin", 0x000000, 0x200000, CRC(3175b0be) SHA1(63649d053c8c17ce1746d16d0cc8202be20c302f) ) ROM_LOAD( "mpr-16515.bin", 0x200000, 0x200000, CRC(3114d748) SHA1(9ef090623cdd2a1d06b5d1bc4b9a07ab4eff5b76) ) @@ -1564,6 +1581,8 @@ MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED(swa, model1) MCFG_DSBZ80_ADD(DSBZ80_TAG) + MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) + MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) MACHINE_CONFIG_END static MACHINE_CONFIG_START( model1_vr, model1_state ) diff --git a/src/mame/includes/model1.h b/src/mame/includes/model1.h index af853e327d1..ab080b38461 100644 --- a/src/mame/includes/model1.h +++ b/src/mame/includes/model1.h @@ -37,6 +37,8 @@ public: struct quad_m1 **m_quadind; int m_sound_irq; int m_to_68k[8]; + UINT8 m_last_snd_cmd; + int m_snd_cmd_state; int m_fifo_wptr; int m_fifo_rptr; int m_last_irq; |