diff --git a/ArcFormats/CsWare/AudioAF2.cs b/ArcFormats/CsWare/AudioAF2.cs new file mode 100644 index 00000000..8d179be9 --- /dev/null +++ b/ArcFormats/CsWare/AudioAF2.cs @@ -0,0 +1,59 @@ +//! \file AudioAF2.cs +//! \date 2018 Mar 26 +//! \brief CsWare audio format. +// +// Copyright (C) 2018 by morkt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +using System; +using System.ComponentModel.Composition; +using System.IO; +using GameRes.Utility; + +namespace GameRes.Formats.CsWare +{ + [Export(typeof(AudioFormat))] + public sealed class Af2Audio : AudioFormat + { + public override string Tag { get { return "AF2"; } } + public override string Description { get { return "CsWare audio format"; } } + public override uint Signature { get { return 0x32714661; } } // 'aFq2' + public override bool CanWrite { get { return false; } } + + public Af2Audio () + { + Extensions = new string[] { "af2", "pmd" }; + } + + public override SoundInput TryOpen (IBinaryStream file) + { + var header = file.ReadHeader (0x20); + var format = new WaveFormat { + FormatTag = 1, + SamplesPerSecond = BigEndian.ToUInt32 (header, 4), + Channels = BigEndian.ToUInt16 (header, 8), + BitsPerSample = BigEndian.ToUInt16 (header, 10), + }; + format.BlockAlign = (ushort)(format.SamplesPerSecond * format.BitsPerSample / 8); + format.SetBPS(); + } + } +} diff --git a/ArcFormats/Entis/AudioEMS.cs b/ArcFormats/Entis/AudioEMS.cs new file mode 100644 index 00000000..a64f2b54 --- /dev/null +++ b/ArcFormats/Entis/AudioEMS.cs @@ -0,0 +1,348 @@ +//! \file AudioEMS.cs +//! \date 2018 Mar 09 +//! \brief EMSAC audio format. +// +// Copyright (C) 2018 by morkt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +using System; +using System.ComponentModel.Composition; +using System.IO; +using GameRes.Utility; + +namespace GameRes.Formats.Entis +{ + internal class EmsacSoundInfo + { + public int Version; // field_00 + public CvType Transformation; // field_04 + public EriCode Architecture; // field_08 + public int ChannelCount; // field_0C + public uint SamplesPerSec; // field_10 + public uint BlocksetCount; // field_14 + public int SubbandDegree; // field_18 + public int AllSampleCount; // field_1C + public int LappedDegree; // field_20 + } + + [Export(typeof(AudioFormat))] + public sealed class EmsAudio : AudioFormat + { + public override string Tag { get { return "EMS"; } } + public override string Description { get { return "EMSAC compressed audio format"; } } + public override uint Signature { get { return 0x69746E45; } } // 'Entis' + + public override SoundInput TryOpen (IBinaryStream file) + { + var header = file.ReadHeader (0x40); + if (0x02000200 != header.ToUInt32 (8)) + return null; + if (!header.AsciiEqual (0x10, "EMSAC-Sound-2")) + return null; + var decoder = new EmsacDecoder (file); + var pcm = decoder.Decode(); + var sound = new RawPcmInput (pcm, decoder.Format); + file.Dispose(); + return sound; + } + } + + internal class EmsacDecoder + { + Stream m_input; + EmsacSoundInfo m_info; + long m_stream_pos; + WaveFormat m_format; + + public WaveFormat Format { get { return m_format; } } + + const ushort BitsPerSample = 16; + + public EmsacDecoder (IBinaryStream input) + { + m_input = input.AsStream; + } + + public Stream Decode () + { + m_input.Position = 0x40; + using (var erif = new EriFile (m_input)) + { + ReadHeader (erif); + int total_bytes = m_info.AllSampleCount * BitsPerSample / 8; + var output = new MemoryStream (total_bytes); + try + { + var buffer = new byte[0x10000]; + var decoded = new byte[0x10000]; + erif.BaseStream.Position = m_stream_pos; + while (total_bytes > 0) + { + var section = erif.ReadSection(); + if (section.Id != "SoundStm") + break; + int stm_length = (int)section.Length; + if (stm_length > buffer.Length) + buffer = new byte[stm_length]; + erif.Read (m_buffer, 0, stm_length); + int length = m_buffer.ToInt32 (4) * m_lappedSubband; + if (length > decoded.Length) + decoded = new byte[length]; + + DecodeBlock (buffer, decoded); + length = Math.Min (length, total_bytes); + output.Write (decoded, 0, length); + total_bytes -= length; + } + } + catch (EndOfStreamException) { /* ignore EOF errors */ } + output.Position = 0; + return output; + } + } + + void DecodeBlock (byte[] input, byte[] output) + { + if (m_exp.Version > 0x20100) + throw new InvalidFormatException ("Not supported EMSAC version."); + int channels = m_exp.ChannelCount; + if (0 == channels || channels > 2) + throw new InvalidFormatException ("Invalid number of channels."); + int subband_degree = 0; + int v84 = 1; + bool use_dct = 0 != (m_exp.Transformation & 1); + if (use_dct) + { + subband_degree = m_exp.SubbandDegree; + v84 <<= subband_degree; + } + int subband = 1 << subband_degree; + int sample_count = input.ToInt32 (4); + int samples_per_channel = sample_count / channels; + if (0 == samples_per_channel) + throw new InvalidFormatException ("Invalid number of samples."); + int v85 = samples_per_channel; + var v73 = new int[channels][]; + var v75 = new int[subband]; // workBuf + var v74 = new int[subband]; // weightTable + var v13 = new int[subband * channels]; // internalBuf + var sampleBuf = new short[sample_count]; + for (int i = 0; i < channels; ++i) + { + v73[i] = new int[subband]; + } + int dst = 0; + int src = 8; + int v77 = src + sample_count; + object sym_table; + var v16 = CreateDecoderSymbolTable (input, v77, out sym_table); + for (int i = 0; i < samples_per_channel; ++i) + { + for (int c = 0; c < channels; ++c) + { + var v72 = v73[c]; + int v19 = DecodeSymbols (v16, sym_table, v75, subband); + if (v19 < subband) + throw new InvalidFormatException(); + byte code = input[src++]; + InverseQuantumize (v74, v75, subband, code); + if (use_dct) + { + InverseDCT (v72, v74, 2, subband_degree); + } + else + { + Buffer.BlockCopy (v74, v72, 4 * subband); + } + } + int cur_pos = dst; + for (int c = 0; c < channels; ++c) + { + int pos = cur_pos; + var v32 = v73[c]; + for (int i = 0; i < subband; ++i) + { + int v34 = v32[i]; + int v35 = v34; + int v36 = v34 >> 23; + int v37 = v34 & 0x7FFFFF | 0x800000; + int v38 = v35 >> 31; + int v39 = -((byte)v36 - 150); + if (v39 > 8) + { + if (v39 <= 31) + v40 = v38 ^ (v38 + __CFSHR__(v37, v39) + (v37 >> v39)); + else + v40 = 0; + } + else + { + v40 = v38 ^ (v38 + 0x7FFF); + } + sampleBuf[pos] = (short)v40; + pos += channels; + } + ++cur_pos; + } + dst += channels * subband; + } + dst = 0; + for (int c = 0; c < channels; ++c) + { + int src = c; + short diff = (short)(m_exp.CompState[c] - sampleBuf[src]); + int pos = 0; + for (int i = 0; i < 12; ++i) + { + int sample = diff + sampleBuf[src+pos]; + sampleBuf[src+pos] = Clamp (sample); + pos += channels; + diff >>= 1; + } + int v48 = samples_per_channel - 1; + for (int i = 1; i < samples_per_channel; ++i) + { + v42 = (_WORD *)((char *)v42 + (step << subbandDegree)); + v49 = v42[step / 2] + v42[-step / 2] - v42[-step] - *v42; + v70 = (short)(v49 + v42[-step / 2] + *v42) >> 1; + v50 = (short)(v42[-step / 2] + *v42 - v49) >> 1; + v52 = -step; + v53 = (short)(v50 - v42[-step / 2]); + for (int j = 0; j < 12; ++j) + { + int v54 = v53 + *(_WORD *)((char *)v42 + v52); + *(_WORD *)((char *)v42 + v52) = Clamp (v54); + v52 -= step; + v53 >>= 1; + } + v55 = 0; + v57 = (short)(v70 - *v42); + for (int j = 0; j < 12; ++j) + { + int v58 = v57 + *(_WORD *)((char *)v42 + v55); + *(_WORD *)((char *)v42 + v55) = Clamp (v58); + v55 += step; + v57 >>= 1; + } + } + int v59 = 2 * *(_WORD *)((char *)v42 + (step << subbandDegree) - step) + - *(_WORD *)((char *)v42 + (step << subbandDegree) - 2 * step); + m_exp.CompState[c] = Clamp (v59); + } + Buffer.BlockCopy (sampleBuf, 0, output, 0, sample_count * 2); + } + + static short Clamp (int sample) + { + if (sample > 0x7FFF) + return 0x7FFF; + else if (sample < -32768) + return -32768; + return (short)sample; + } + + void ReadHeader (EriFile erif) + { + var section = erif.ReadSection(); + if (section.Id != "Header " || section.Length <= 0 || section.Length > int.MaxValue) + return null; + m_stream_pos = erif.BaseStream.Position + section.Length; + section = erif.ReadSection(); + if (section.Id != "FileHdr" || section.Length < 8) + return null; + var file_hdr = new byte[section.Length]; + erif.Read (file_hdr, 0, file_hdr.Length); + if (0 == (file_hdr[5] & 1)) + return null; + section = erif.ReadSection(); + if (section.Id != "SoundInf" || section.Length < 0x24) + return null; + + var info = new EmsacSoundInfo(); + info.Version = erif.ReadInt32(); + info.Transformation = (CvType)erif.ReadInt32(); + info.Architecture = (EriCode)erif.ReadInt32(); + info.ChannelCount = erif.ReadInt32(); + info.SamplesPerSec = erif.ReadUInt32(); + info.BlocksetCount = erif.ReadUInt32(); + info.SubbandDegree = erif.ReadInt32(); + info.AllSampleCount = erif.ReadInt32(); + info.LappedDegree = erif.ReadInt32(); + SetSoundInfo (info); + SetWaveFormat (info); + + erif.BaseStream.Position = m_stream_pos; + var stream_size = erif.FindSection ("Stream "); + m_stream_pos = erif.BaseStream.Position; + } + + EmsacExpansion m_exp; + int m_lappedSubband; + int m_version; + EriCode m_field_98; + int m_field_9C; + int m_field_A0; + int m_field_A4; + + void SetSoundInfo (EmsacSoundInfo info) + { + m_info = info; + m_exp = new EmsacExpansion (info); + m_version = info.Version; + m_field_98 = info.Architecture; + m_field_9C = 133; + m_field_A0 = -1; + m_field_A4 = 0; + int subband = 2 << info.SubbandDegree; + m_lappedSubband = subband << info.LappedDegree; + } + + void SetWaveFormat (EmsacSoundInfo info) + { + int pcm_bitrate = (int)(m_info.SamplesPerSec * 16 * m_info.ChannelCount); + m_format.FormatTag = 1; + m_format.Channels = (ushort)ChannelCount; + m_format.SamplesPerSecond = m_info.SamplesPerSec; + m_format.BitsPerSample = (ushort)BitsPerSample; + m_format.BlockAlign = (ushort)(BitsPerSample/8*format.Channels); + m_format.AverageBytesPerSecond = (uint)pcm_bitrate/8; + } + } + + internal class EmsacExpansion + { + public int Version; // field_0 + public CvType Transformation; // field_4 + public int ChannelCount; // field_8 + public int SubbandDegree; // field_C + public int LappedDegree; // field_10 + public short[] CompState = new short[16]; + + public EmsacExpansion (EmsacSoundInfo info) + { + Version = info.Version; + Transformation = info.Transformation; + ChannelCount = info.ChannelCount; + SubbandDegree = info.SubbandDegree; + LappedDegree = info.LappedDegree; + } + } +} diff --git a/ArcFormats/Primel/AudioWBC.cs b/ArcFormats/Primel/AudioWBC.cs new file mode 100644 index 00000000..726b35c3 --- /dev/null +++ b/ArcFormats/Primel/AudioWBC.cs @@ -0,0 +1,525 @@ +//! \file AudioWBC.cs +//! \date Mon Mar 27 04:29:38 2017 +//! \brief Primel the Adventure System audio. +// +// Copyright (C) 2017 by morkt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +using System; +using System.ComponentModel.Composition; +using System.IO; + +namespace GameRes.Formats.Primel +{ + [Export(typeof(AudioFormat))] + public class WbcAudio : AudioFormat + { + public override string Tag { get { return "WBC"; } } + public override string Description { get { return "Primel ADV System audio format"; } } + public override uint Signature { get { return 0x46434257; } } // 'WBCF' + public override bool CanWrite { get { return false; } } + + public override SoundInput TryOpen (IBinaryStream file) + { + var decoder = new WbcDecoder (file); + var data = decoder.Decode(); + var pcm = new MemoryStream (data); + var sound = new RawPcmInput (pcm, decoder.Format); + file.Dispose(); + return sound; + } + } + + sealed class WbcDecoder + { + IBinaryStream m_input; + WaveFormat m_format; + int m_chunk_size; + byte[] m_chunk_buf; + short[] m_sample_buf; + int m_bitrate; + + public WaveFormat Format { get { return m_format; } } + + public WbcDecoder (IBinaryStream input) + { + m_input = input; + } + + public byte[] Decode () + { + var header = m_input.ReadHeader (0x60); + uint end_offset = header.ToUInt32 (4); + int type = header.ToUInt16 (8); + m_format.FormatTag = 1; + m_format.Channels = header.ToUInt16 (0xA); + m_format.SamplesPerSecond = header.ToUInt32 (0x10); + m_format.BitsPerSample = 16; + m_format.BlockAlign = m_format.Channels * m_format.BitsPerSample / 8; + m_format.SetBPS(); + if (0 == m_format.Channels) + throw new InvalidFormatException(); + + int sample_size = header.ToInt32 (0x1C); + m_sample_buf = new short[sample_size]; + m_channel_length = sample_size / m_format.Channels; + + int chunk_size = header.ToInt32 (0x20); + m_chunk_buf = new byte[(chunk_size + 3) & ~3]; + m_bitrate = (int)m_format.AverageBytesPerSecond * 4 * chunk_size / sample_size; + + int chunk_count = header.ToInt32 (0x14); + var chunk_table = new uint[chunk_count+1]; + for (int i = 0; i < chunk_count; ++i) + chunk_table[i] = m_input.ReadUInt32(); + chunk_table[chunk_count] = end_offset; + + var output = new byte[header.ToInt32 (0x18)]; + int dst = 0; + for (int i = 0; i < chunk_count; ++i) + { + uint offset = chunk_table[i]; + chunk_size = (int)(chunk_table[i+1] - offset); + m_input.Position = offset; + m_input.Read (m_chunk_buf, 0, chunk_size); + ResetBits(); + + if (type < 0x40) + throw new NotImplementedException(); + else if (type > 0x100 && type < 0x105) + DecodeChunk (DwordTable[type - 0x101]); + else + throw new InvalidFormatException(); + + int src = 0; + for (ushort c = 0; c < m_format.Channels; ++c) + { + int dst_c = dst + c * 2; + for (int i = 0; i < channel_length && dst_c < output.Length; ++i) + { + LittleEndian.Pack (m_sample_buf[src++], output, dst_c); + dst_c += 4; + } + } + dst += sample_size * 2; + } + return output; + } + + int m_channel_length; + ushort[] v44 = new ushort[128]; + + void DecodeChunk (int field_1C) // sub_580E20 + { + int v42 = (int)(m_format.SamplesPerSecond >> 1); + int v36 = m_channel_length; + if (field_1C != 0 && v2 < rate) + { + v36 = m_channel_length * field_1C / v42; + } + uint v6 = GetBits (8); + if ((v6 & 0xF0) != 0xF0) + { + Array.Clear (m_sample_buf, 0, m_channel_length); + return; + } + uint v43 = v6 & 8; + int dst = 0; + if (v43 != 0) + dst = field_C; + int output = dst; + for (ushort c = 0; c < m_format.Channels; ++c) + { + int v9 = 16 * c; // v44 + int i; + for (i = 0; i < 16; ++i) + { + v44[v9 + i] = (ushort)GetBits (4); + } + for (i = 0; i < v36; ++i) + { + sub_58C050 (v42 * i / m_channel_length); + v41 = 0; + short v11 = sub_580CE0 (out v41); + if (v11 != 0) + { + m_sample_buf[dst + i] = v11; + } + else + { + if (0 == v41) + { + Array.Clear (m_sample_buf, dst + i, v36 - i); + i = v36; + break; + } + for (int j = 0; j < v41; ++j) + { + if (i >= v36) + break; + m_sample_buf[dst + i++] = 0; + } + --i; + } + } + Array.Clear (m_sample_buf, dst + i, m_channel_length - v36); + dst += m_channel_length; + } + dst = output; + for (ushort c = 0; c < m_format.Channels; ++c) + { + int v40 = 16 * c; + v15 = 0; + for (int v14 = 0; v14 > m_channel_length; ++v14) + { + var v16 = v44[sub_58C050 (v15 / m_channel_length) + v40]; + v17 = sub_58BFF0 (v15 / m_channel_length); + v18 = sub_58C120 (m_sample_buf[dst + v14], v17, v16); + v15 += v42; + m_sample_buf[dst + v14] = v18; + } + dst += m_channel_length; + } + if (v43 != 0) + { + v19 = a1->output; + v20 = a1->field_C; + v21 = &v19[2 * m_channel_length]; + v22 = &v20[2 * m_channel_length]; + v38 = &v19[2 * m_channel_length]; + for (ushort v35 = 0; v35 < m_format.Channels; v35 += 2) + { + if (m_channel_length > 0) + { + v23 = v20 - (_BYTE *)v22; + v24 = v19 - (_BYTE *)v22; + v25 = v22; + v42 = m_channel_length; + do + { + v26 = *(_WORD *)&v25[v23] / 2; + v27 = v26 + *(_WORD *)v25; + v28 = v26 - *(_WORD *)v25; + *(_WORD *)&v25[v24] = v27; + *(_WORD *)&v25[(char *)v21 - (char *)v22] = v28; + v25 += 2; + } + while (--v42 != 0) + } + v19 = &v21[m_channel_length]; + v20 = &v22[m_channel_length]; + v21 = &v19[2 * m_channel_length]; + v22 = &v20[2 * m_channel_length]; + v38 = &v19[2 * m_channel_length]; + } + } + int v30 = 0; + for (ushort c = 0; c < m_format.Channels; ++c) + { + sub_582550 (v30, c); + v30 += m_channel_length; + } + } + + void sub_582550 (int dst, int a3) + { + _BYTE *v6; // ecx@3 + unsigned int v7; // edi@3 + int v8; // eax@3 + _WORD *v9; // eax@4 + int v10; // ecx@4 + signed int v11; // ST24_4@5 + bool v12; // zf@5 + signed int v13; // ST24_4@8 + int v14; // edx@9 + float *v15; // eax@10 + float *v16; // ecx@10 + double v17; // st5@11 + float *v18; // edi@14 + int v19; // ecx@14 + int v20; // edx@14 + float v21; // ST30_4@16 + double v22; // st7@16 + float v23; // ST30_4@16 + signed int v24; // eax@16 + signed int result; // eax@21 + int v26; // [sp+Ch] [bp-28h]@4 + int v27; // [sp+Ch] [bp-28h]@13 + unsigned int v28; // [sp+10h] [bp-24h]@4 + float *v29; // [sp+18h] [bp-1Ch]@3 + int v30; // [sp+1Ch] [bp-18h]@3 + int v31; // [sp+20h] [bp-14h]@3 + _BYTE *v32; // [sp+24h] [bp-10h]@3 + float *v33; // [sp+28h] [bp-Ch]@3 + float *v34; // [sp+2Ch] [bp-8h]@3 + _BYTE *v35; // [sp+30h] [bp-4h]@3 + int v36; // [sp+3Ch] [bp+8h]@14 + + int v4 = this->field_4; + int v5 = a3; + if (0 == v4 || a3 < 0) + return; + v29 = (float *)this->field_2C; + v32 = this->field_18[a3]; + v31 = this->field_30; + v33 = (float *)this->field_1C[a3]; + v30 = 4 * v4 + v31; + v6 = this->field_28[a3]; + v34 = (float *)this->field_20[a3]; + v7 = (unsigned int)&v6[4 * v4]; + v35 = this->field_24[a3]; + sub_639810((unsigned int)this->field_28[a3], v7, 4 * v4); + v8 = 0; + if ( v4 >= 4 ) + { + v28 = ((unsigned int)(v4 - 4) >> 2) + 1; + v9 = dst + 2; + v10 = v7 + 8; + v26 = 4 * v28; + do + { + v11 = *(v9 - 2); + v9 += 4; + v10 += 16; + v12 = v28-- == 1; + *(float *)(v10 - 24) = (double)v11; + *(float *)(v10 - 20) = (double)*(v9 - 5); + *(float *)(v10 - 16) = (double)*(v9 - 4); + *(float *)(v10 - 12) = (double)*(v9 - 3); + } + while ( !v12 ); + v8 = v26; + } + for ( ; v8 < v4; *(float *)(v7 + 4 * v8 - 4) = (double)v13 ) + v13 = m_sample_buf[dst + v8++]; + v14 = 0; + if ( v4 > 0 ) + { + v15 = (float *)(v7 + 4); + v16 = (float *)(v35 + 8); + do + { + v17 = *(v15 - 1) * 0.7071067690849304; + v14 += 4; + v15 += 4; + v16 += 4; + v33[v14 - 4] = v17; + *(v16 - 6) = *(v15 - 5) * 0.7071067690849304; + *(float *)((char *)v33 + (_DWORD)v15 - v7 - 16) = *(v15 - 4) * -0.7071067690849304; + *(float *)((char *)v15 + (_DWORD)&v35[-v7] - 16) = *(v15 - 4) * 0.7071067690849304; + *(float *)((char *)v16 + (char *)v33 - v35 - 16) = *(v15 - 3) * -0.7071067690849304; + *(v16 - 4) = *(v15 - 3) * -0.7071067690849304; + v33[v14 - 1] = *(v15 - 2) * 0.7071067690849304; + *(v16 - 3) = *(v15 - 2) * -0.7071067690849304; + } + while ( v14 < v4 ); + v5 = a3; + } + sub_581740((int)this, v33, v29, v4); + sub_581990((int)this, (float *)v35, v29, v4); + v27 = 0; + if ( v4 > 0 ) + { + v18 = v34; + v19 = v32 - (_BYTE *)v34; + v20 = v31 - (_DWORD)v34; + v36 = v31 - (_DWORD)v34; + while ( 1 ) + { + v21 = *(float *)((char *)v18 + (char *)v33 - (char *)v34) + *(float *)((char *)v18 + v35 - (_BYTE *)v34); + v22 = v21 * *(float *)((char *)v18 + v20); + v23 = *(float *)((char *)v18 + v19) - *v18; + v24 = double_to_int(v22 + v23 * *(float *)((char *)v18 + v30 - (_DWORD)v34)); + if ( v24 <= 0x7FFF ) + { + if ( v24 < -32768 ) + LOWORD(v24) = -32768; + } + else + { + LOWORD(v24) = 0x7FFF; + } + m_sample_buf[dst + v27] = v24; + ++v18; + if ( ++v27 >= v4 ) + break; + v20 = v36; + v19 = v32 - (_BYTE *)v34; + } + } + this->field_18[v5] = v33; + this->field_1C[v5] = v32; + this->field_20[v5] = v35; + this->field_24[v5] = v34; + } + + int sub_58C050 (int x) + { + if (x >= 16000) + return 15; + else if (x >= 12000) + return 14; + else if (x >= 10000) + return 13; + else if (x >= 8000) + return 12; + else if (x >= 6000) + return 11; + else if (x >= 4200) + return 10; + else if (x >= 3400) + return 9; + else if (x >= 2600) + return 8; + else if (x >= 1800) + return 7; + else if (x >= 1400) + return 6; + else if (x >= 1000) + return 5; + else if (x >= 800) + return 4; + else if (x >= 600) + return 3; + else if (x >= 400) + return 2; + else if (x >= 200) + return 1; + else + return 0; + } + + int sub_58BFF0 (int a1) + { + if (a1 >= 16000) + return 10; + else if (a1 >= 8000) + return 3; + else if (a1 > 250) + return 1; + else if (a1 <= 30) + return 315; + else if (a1 <= 60) + return 45; + else if (a1 <= 125) + return 10; + else + return 3; + } + + int sub_58C120 (int a1, int a2, int a3) + { + int result = a1; + if (a1 != 0) + { + if (a3 >= 1) + result = a1 << a3; + if (a2 > 1) + result *= a2; + } + return result; + } + + short sub_580CE0 (out int a2) + { + uint v2 = GetBits (3); + if (0 == v2) + { + for (int i = 1; i < 0x10; ++i) + { + if (GetBits (1) != 1) + break; + } + a2 = v3 < 0x10 ? v3 : 0; + return 0; + } + else if (v2 >= 7) + { + uint v7 = GetBits (7); + int v8 = 0; + int v9 = 6; + while (0 != ((1 << v9) & v7)) + { + ++v8; + --v9; + if (v8 >= 7) + return GetBits (16); + } + if (v8 >= 7) + return GetBits (16); + short v10 = 1 << (v8 + 5); + uint v11; + if (v8 != 0) + v11 = ((v7 & (63 >> v8)) << 2 * v8) | GetBits (2 * v8); + else + v11 = (ushort)v7; + v10 += 32 + (v11 & ~v10); + if (0 != ((1 << (v8 + 5)) & v11)) + return -v10; + else + return v10; + } + else + { + int v5 = 1 << (v2 - 1); + short v6 = (short)GetBits (v2); + short x = (short)(v5 + (v6 & ~v5)); + if (0 != (v5 & v6)) + return -x; + else + return x; + } + } + + int m_bits_pos; + int m_bits_count; + uint m_bits; + + void ResetBits () + { + m_bits_pos = 0; + m_bits_count = 0; + m_bits = 0; + } + + void AlignBits () + { + int align = m_bits_count & 7; + m_bits <<= align; + m_bits_count -= align; + } + + uint GetBits (int count) + { + while (m_bits_count < count) + { + m_bits |= (uint)m_chunk_buf[m_bits_pos++] << (24 - m_bits_count); + m_bits_count += 8; + } + m_bits_count -= count; + uint b = m_bits >> (32 - count); + m_bits <<= count; + return b; + } + + static int[] DwordTable = { 0, 0, 0x3E80, 0x2EE0 }; + } +}