public void Init(StreamReader.IReader fileReader, UInt64 offset, ref VGM_Stream vgmStream, bool InitReader, UInt64 fileLength) { byte[] mibBuffer = new byte[0x10]; byte[] testBuffer = new byte[0x10]; byte[] testBuffer2 = new byte[0x10]; byte[] testBuffer3 = new byte[0x10]; //bool doChannelUpdate=true; //bool bDoUpdateInterleave=true; UInt64 loopStart = 0; UInt64 loopEnd = 0; UInt64 interleave = 0; UInt64 readOffset = offset; UInt64[] loopStartPoints = new UInt64[0x10]; int loopStartPointsCount = 0; UInt64[] loopEndPoints = new UInt64[0x10]; int loopEndPointsCount = 0; byte[] emptyLine = new byte[0x10]; bool loopToEnd = false; bool forceNoLoop = false; bool bolSaveEmptyLine = true; int i, channel_count = 0; bool interleave_found = false; UInt64 tstCount = 0; UInt64[] emptyLineOffset = new UInt64[100]; uint emptyLineCount = 0; uint max_interleave = 0; uint max_interleave_index = 0; // Initialize loop point to 0 for (i = 0; i < 0x10; i++) { loopStartPoints[i] = 0; loopEndPoints[i] = 0; testBuffer[i] = 0; emptyLine[i] = 0; } //if (this.Filename.ToUpper().Contains(".MIB")) /* Search for interleave value & loop points */ /* Get the first 16 values */ mibBuffer = fileReader.Read(offset, 0x10); if (MemoryReader.memcmp(mibBuffer, emptyLine, 0x10, 0)) { tstCount = 0x10; //readOffset += 0x10; } else { tstCount = 0x0e; } do { testBuffer = fileReader.Read(readOffset, 0x10); // be sure to point to an interleave value if (!interleave_found) { if (MemoryReader.memcmp(testBuffer, emptyLine, tstCount, 0x10 - tstCount)) { // don't need to stock all empty lines :P if (emptyLineCount >= 100) { emptyLineCount = 0; } if (emptyLineCount >= 1) { if ((readOffset - offset) > 0x60000) { bolSaveEmptyLine = false; } } if (bolSaveEmptyLine) { emptyLineOffset[emptyLineCount] = readOffset; emptyLineCount++; } } } // Loop Start ... if (testBuffer[0x01] == 0x06) { if (loopStartPointsCount < 0x10) { loopStartPoints[loopStartPointsCount] = readOffset - offset - 0x10; loopStartPointsCount++; } } // Loop End ... if (((testBuffer[0x01] == 0x03) && (testBuffer[0x03] != 0x77)) || (testBuffer[0x01] == 0x01)) { if (loopEndPointsCount < 0x10) { loopEndPoints[loopEndPointsCount] = readOffset - offset; //-0x10; loopEndPointsCount++; } if (testBuffer[0x01] == 0x01) { forceNoLoop = true; } } if (testBuffer[0x01] == 0x04) { // 0x04 loop points flag can't be with a 0x03 loop points flag if (loopStartPointsCount < 0x10) { if ((readOffset - offset) == 0) { loopStartPoints[loopStartPointsCount] = 0; } else { loopStartPoints[loopStartPointsCount] = readOffset - offset; } loopStartPointsCount++; // Loop end value is not set by flags ... // go until end of file loopToEnd = true; } } readOffset += 0x10; } while (readOffset < (offset + fileLength)); // Try to find biggest interleave value if (emptyLineCount > 1) { for (uint count = 1; count < emptyLineCount; count++) { if (((uint)(emptyLineOffset[count] - emptyLineOffset[count - 1])) > max_interleave) { max_interleave = (uint)(emptyLineOffset[count] - emptyLineOffset[count - 1]); max_interleave_index = count; } } if (max_interleave_index != 0) { interleave = (uint)(emptyLineOffset[max_interleave_index] - emptyLineOffset[0]); } } if ((testBuffer[0] == 0x0c) && (testBuffer[1] == 0)) { forceNoLoop = true; } if (channel_count == 0) { channel_count = 1; } // Calc Loop Points & Interleave ... if (loopStartPointsCount >= channel_count) { // can't get more then 0x10 loop point ! // and need at least 2 loop points if ((loopStartPointsCount <= 0x0F) && (loopStartPointsCount >= 2)) { // Always took the first 2 loop points interleave = loopStartPoints[loopStartPointsCount - 1] - loopStartPoints[loopStartPointsCount - 2]; loopStart = loopStartPoints[1]; // Can't be one channel .mib with interleave values if ((interleave > 0) && (channel_count == 1)) { channel_count = 2; } } else { loopStart = 0; } } if (loopEndPointsCount >= channel_count) { // can't get more then 0x10 loop point ! // and need at least 2 loop points if ((loopEndPointsCount <= 0x0F) && (loopEndPointsCount >= 2)) { if (loopEndPointsCount == 4) { if (interleave == 0) { interleave = loopEndPoints[3] - loopEndPoints[1]; } else { interleave = loopEndPoints[loopEndPointsCount - 1] - loopEndPoints[loopEndPointsCount - 2]; } } loopEnd = loopEndPoints[loopEndPointsCount - 1]; if (interleave >= 0x10) { if (channel_count == 1) { channel_count = 2; } } } else { loopToEnd = false; loopEnd = 0; } } if (loopToEnd) { loopEnd = fileLength; } // force no loop if (forceNoLoop) { loopEnd = 0; } if ((interleave > 0x10) && (channel_count == 1)) { channel_count = 2; } if (interleave <= 0) { interleave = 0x10; } /* build the VGMSTREAM */ VGM_Utils.allocate_vgmStream(ref vgmStream, channel_count, (loopEnd != 0)); /* fill in the vital statistics */ vgmStream.vgmDecoder = new PSX_Decoder(); if (channel_count == 1) { vgmStream.vgmLayout = new NoLayout(); } else { vgmStream.vgmLayout = new Interleave(); } vgmStream.vgmChannelCount = channel_count; vgmStream.vgmInterleaveBlockSize = (int)interleave; vgmStream.vgmLoopFlag = (loopEnd != 0); if (m_Description == null) { vgmStream.vgmSampleRate = 44100; } else { if (System.IO.Path.GetExtension(m_Description).ToUpper() == ".MIB") { vgmStream.vgmSampleRate = 44100; } } vgmStream.vgmTotalSamples = (int)(fileLength / (UInt64)16 / (UInt64)(channel_count * 28)); if (loopEnd != 0) { if (vgmStream.vgmChannelCount == 1) { vgmStream.vgmLoopStartSample = (int)loopStart / 16 * 18; vgmStream.vgmLoopEndSample = (int)loopEnd / 16 * 28; } else { if (loopStart == 0) { vgmStream.vgmLoopStartSample = 0; } else { vgmStream.vgmLoopStartSample = (int)(((UInt64)(((loopStart / interleave) - 1) * interleave)) / (UInt64)((16 * 14 * channel_count) / channel_count)); if (loopStart % interleave != 0) { vgmStream.vgmLoopStartSample += (int)(((UInt64)((loopStart % interleave) - 1) / (UInt64)(16 * 14 * channel_count))); } } if (loopEnd == fileLength) { vgmStream.vgmLoopEndSample = (int)((UInt64)loopEnd / (UInt64)((16 * 28) / channel_count)); } else { vgmStream.vgmLoopEndSample = (int)((UInt64)(((loopEnd / interleave) - 1) * interleave) / (UInt64)((16 * 14 * channel_count) / channel_count)); if (loopEnd % interleave != 0) { vgmStream.vgmLoopEndSample += (int)((UInt64)((loopEnd % interleave) - 1) / (UInt64)(16 * 14 * channel_count)); } } } } if (InitReader) { for (i = 0; i < channel_count; i++) { vgmStream.vgmChannel[i].currentOffset = offset + (interleave * (UInt64)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()); } } }
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]); } } } }