public void Decode(VGM_Stream vgmStream, VGM_Channel vgmChannel, ref short[] vgmOutput, int vgmChannelSpacing, int vgmFirstSample, int vgmSamplesToDo, int vgmChannelNumber) { int vgmSampleCount, i; int framesin = vgmFirstSample / 32; int scale = vgmChannel.fReader.Read_16bitsBE(vgmChannel.currentOffset + (UInt64)((framesin * 18) ^ vgmChannel.adx_xor)) + 1; int vgmSampleHistory1 = vgmChannel.adpcm_history_32bits_1; int vgmSampleHistory2 = vgmChannel.adpcm_history_32bits_2; int coef1 = vgmChannel.adpcm_coef[0]; int coef2 = vgmChannel.adpcm_coef[1]; int vgmSample; vgmFirstSample = vgmFirstSample % 32; for (i = vgmFirstSample, vgmSampleCount = 0; i < vgmFirstSample + vgmSamplesToDo; i++, vgmSampleCount += vgmChannelSpacing) { int sample_byte = vgmChannel.fReader.Read_8Bits(vgmChannel.currentOffset + (UInt64)((framesin * 18) + 2 + i / 2)); sample_byte = (((i & 1) == 1) ? VGM_Utils.LOWNIBBLE_SIGNED(sample_byte) : VGM_Utils.HINIBBLE_SIGNED(sample_byte)); vgmSample = (sample_byte * scale); vgmSample += (((coef1 * vgmSampleHistory1) + (coef2 * vgmSampleHistory2)) >> 12); vgmOutput[vgmStream.vgmSamplesBlockOffset + vgmSampleCount + vgmChannelNumber] = VGM_Utils.clamp16(vgmSample); vgmSampleHistory2 = vgmSampleHistory1; vgmSampleHistory1 = vgmSample; } vgmChannel.adpcm_history_32bits_1 = vgmSampleHistory1; vgmChannel.adpcm_history_32bits_2 = vgmSampleHistory2; if ((i % 32) == 0) { for (i = 0; i < vgmChannel.adx_channels; i++) { VGM_Utils.adx_next_key(ref vgmChannel); } } }
public void Init(StreamReader.IReader fileReader, UInt64 offset, ref VGM_Stream vgmStream, bool InitReader, UInt64 fileLength) { bool loop_flag = false; UInt32 loop_start_sample = 0; UInt32 loop_start_offset; UInt32 loop_end_sample = 0; UInt32 loop_end_offset; Int16 coef1 = 0; Int16 coef2 = 0; UInt16 xor_start = 0; UInt16 xor_mult = 0; UInt16 xor_add = 0; int i; int channel_count = fileReader.Read_8Bits(offset + 0x07); /* check version signature, read loop info */ UInt16 version_signature = fileReader.Read_16bitsBE(offset + 0x12); UInt64 criOffset = (UInt64)(fileReader.Read_16bitsBE(offset + 2) + 4); /* encryption */ if (version_signature == 0x0408) { if (!find_key(fileReader, offset, ref xor_start, ref xor_mult, ref xor_add)) { return; } } UInt32 ainf_info_length = 0; if (fileReader.Read_32bitsBE(offset + 0x24) == 0x41494E46) /* AINF Header */ { ainf_info_length = fileReader.Read_32bitsBE(offset + 0x28); } if (criOffset - ainf_info_length - 6 >= 0x38) { /* enough space for loop info? */ loop_flag = (fileReader.Read_32bitsBE(offset + 0x24) != 0); loop_start_sample = (fileReader.Read_32bitsBE(offset + 0x28)); loop_start_offset = fileReader.Read_32bitsBE(offset + 0x2C); loop_end_sample = fileReader.Read_32bitsBE(offset + 0x30); loop_end_offset = fileReader.Read_32bitsBE(offset + 0x34); } /* build the VGMSTREAM */ VGM_Utils.allocate_vgmStream(ref vgmStream, channel_count, loop_flag); vgmStream.vgmChannelCount = channel_count; vgmStream.vgmSampleRate = (int)fileReader.Read_32bitsBE(offset + 0x08); vgmStream.vgmTotalSamples = (int)fileReader.Read_32bitsBE(offset + 0x0C); vgmStream.vgmDecoder = new ADXENC_Decoder(); if (channel_count == 1) { vgmStream.vgmLayout = new NoLayout(); } else { vgmStream.vgmLayout = new Interleave(); } vgmStream.vgmLoopFlag = loop_flag; if (loop_flag) { vgmStream.vgmLoopStartSample = (int)loop_start_sample; vgmStream.vgmLoopEndSample = (int)loop_end_sample; } /* high-pass cutoff frequency, always 500 that I've seen */ UInt16 cutoff = fileReader.Read_16bitsBE(offset + 0x10); /* calculate filter coefficients */ { double x, y, z, a, b, c; x = cutoff; y = vgmStream.vgmSampleRate; z = Math.Cos(2.0 * Math.PI * x / y); a = Math.Sqrt(2) - z; b = Math.Sqrt(2) - 1.0; c = (a - Math.Sqrt((a + b) * (a - b))) / b; coef1 = (Int16)Math.Floor(c * 8192); coef2 = (Int16)Math.Floor(c * c * -4096); } vgmStream.vgmInterleaveBlockSize = 18; if (InitReader) { for (i = 0; i < channel_count; i++) { vgmStream.vgmChannel[i].fReader = (StreamReader.IReader)Activator.CreateInstance(fileReader.GetType());; vgmStream.vgmChannel[i].fReader.Open(fileReader.GetFilename()); vgmStream.vgmChannel[i].fReader.SetSessionID(fileReader.GetSessionID()); vgmStream.vgmChannel[i].adpcm_coef[0] = coef1; vgmStream.vgmChannel[i].adpcm_coef[1] = coef2; vgmStream.vgmChannel[i].startOffset = vgmStream.vgmChannel[i].currentOffset = offset + criOffset + (UInt64)((vgmStream.vgmInterleaveBlockSize * i)); int j; vgmStream.vgmChannel[i].adx_channels = channel_count; vgmStream.vgmChannel[i].adx_xor = xor_start; vgmStream.vgmChannel[i].adx_mult = xor_mult; vgmStream.vgmChannel[i].adx_add = xor_add; for (j = 0; j < i; j++) { VGM_Utils.adx_next_key(ref vgmStream.vgmChannel[i]); } } } }