public static double MIN_SAMPLE_MATCH_PERCENTAGE = 0.05f; // 5% public static ArrayList GetSeqFileList(Stream fs, bool UseSeqMinimumSize, int MinimumSeqSize) { ArrayList ret = new ArrayList(); ProbableItemStruct seqEntry = new ProbableItemStruct(); long offset = 0; long seqEof = 0; uint seqLength; // build file list while ((offset = ParseFile.GetNextOffset(fs, offset, PsxSequence.ASCII_SIGNATURE_SEQ)) > -1) { seqEof = ParseFile.GetNextOffset(fs, offset, PsxSequence.END_SEQUENCE); if (seqEof > 0) { seqLength = (uint)(seqEof - offset + PsxSequence.END_SEQUENCE.Length); if ((!UseSeqMinimumSize) || ((UseSeqMinimumSize) && (seqLength >= MinimumSeqSize))) { seqEntry.offset = offset; seqEntry.length = (uint)(seqEof - offset + PsxSequence.END_SEQUENCE.Length); ret.Add(seqEntry); } } offset += 1; } return(ret); }
public static int GetMpegStreamType(string path) { int mpegType = -1; using (FileStream fs = File.OpenRead(path)) { // look for first packet long currentOffset = ParseFile.GetNextOffset(fs, 0, MpegStream.PacketStartBytes); if (currentOffset != -1) { currentOffset += 4; fs.Position = currentOffset; byte idByte = (byte)fs.ReadByte(); if ((int)ByteConversion.GetHighNibble(idByte) == 2) { mpegType = 1; } else if ((int)ByteConversion.GetHighNibble(idByte) == 4) { mpegType = 2; } } else { throw new FormatException(String.Format("Cannot find Pack Header for file: {0}{1}", Path.GetFileName(path), Environment.NewLine)); } } return(mpegType); }
public static string[] ExtractSdatsFromFile(string pPath, string pDirectorySuffix) { ArrayList extractedSdatPaths = new ArrayList(); string fullPath = Path.GetFullPath(pPath); string outputPath; string filePrefix = Path.GetFileNameWithoutExtension(fullPath); if (!String.IsNullOrEmpty(pDirectorySuffix)) { filePrefix += pDirectorySuffix; } int sdatIndex = 0; long sdatOffset; long previousOffset; byte[] sdatSizeBytes; int sdatSize; if (!File.Exists(fullPath)) { throw new FileNotFoundException(String.Format("Cannot find file <{0}>", fullPath)); } else { using (FileStream fs = File.Open(fullPath, FileMode.Open, FileAccess.Read)) { previousOffset = 0; while ((sdatOffset = ParseFile.GetNextOffset(fs, previousOffset, Sdat.ASCII_SIGNATURE)) != -1) { sdatSizeBytes = ParseFile.ParseSimpleOffset(fs, sdatOffset + 8, 4); sdatSize = BitConverter.ToInt32(sdatSizeBytes, 0); outputPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(pPath), Path.Combine(filePrefix, String.Format("sound_data_{0}.sdat", sdatIndex++.ToString("X2"))))); ParseFile.ExtractChunkToFile(fs, sdatOffset, sdatSize, outputPath); extractedSdatPaths.Add(outputPath); // only increment by one since there can be fake or bad SDATs which will move us past proper ones. previousOffset = sdatOffset + 1; } } } // return paths of extracted SDATs if (extractedSdatPaths.Count > 0) { return((string[])extractedSdatPaths.ToArray(typeof(string))); } else { return(null); } }
public static ArrayList GetSepFileList(Stream fs) { ArrayList ret = new ArrayList(); ProbableItemStruct sepEntry = new ProbableItemStruct(); long offset = 0; long sepStartingOffset = 0; int sepSeqCount; long seqEof = 0; // build file list while ((offset = ParseFile.GetNextOffset(fs, offset, PsxSequence.ASCII_SIGNATURE_SEP)) > -1) { sepStartingOffset = offset; sepSeqCount = 1; byte[] nextSepCheckBytes; seqEof = offset; while ((seqEof = ParseFile.GetNextOffset(fs, seqEof, PsxSequence.END_SEQUENCE)) > -1) { nextSepCheckBytes = ParseFile.ParseSimpleOffset(fs, (long)(seqEof + PsxSequence.END_SEQUENCE.Length), 2); Array.Reverse(nextSepCheckBytes); if (nextSepCheckBytes.Length > 0) { if (BitConverter.ToUInt16(nextSepCheckBytes, 0) == (UInt16)sepSeqCount) { sepSeqCount++; } else { sepEntry.offset = sepStartingOffset; sepEntry.length = (uint)(seqEof - sepStartingOffset + PsxSequence.END_SEQUENCE.Length); ret.Add(sepEntry); break; } } else { sepEntry.offset = sepStartingOffset; sepEntry.length = (uint)(seqEof - sepStartingOffset + PsxSequence.END_SEQUENCE.Length); ret.Add(sepEntry); break; } seqEof += 1; } offset += 1; } return(ret); }
protected void ConvertSubtitles(uint streamId, FileStream subtitleStream) { long subsLength = subtitleStream.Length; long currentOffset = 0; byte[] encodedPresentationTimeStamp; ulong decodedTimeStamp; ushort subtitlePacketSize; byte[] PNG_HEADER = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; byte[] PNG_END = new byte[] { 0x49, 0x45, 0x4E, 0x44 }; long pngStartOffset; long pngEndOffset; long pngSize; uint pngCount = 0; string baseDirectory = Path.GetDirectoryName(subtitleStream.Name); baseDirectory = Path.Combine(baseDirectory, String.Format("{0}_PNGs", Path.GetFileNameWithoutExtension(subtitleStream.Name))); string destinationFile; while (currentOffset < subsLength) { // decode time stamp encodedPresentationTimeStamp = ParseFile.ParseSimpleOffset(subtitleStream, currentOffset, 5); decodedTimeStamp = this.DecodePresentationTimeStamp(encodedPresentationTimeStamp); // get subtitle packet size subtitlePacketSize = ParseFile.ReadUshortBE(subtitleStream, currentOffset + 0xC); // extract PNG pngStartOffset = ParseFile.GetNextOffset(subtitleStream, currentOffset + 0x1E, PNG_HEADER); pngEndOffset = ParseFile.GetNextOffset(subtitleStream, pngStartOffset, PNG_END) + 4; pngSize = pngEndOffset - pngStartOffset; if (pngSize > (subtitlePacketSize - 0x14)) { throw new Exception("Warning, PNG size exceeds packet size."); } destinationFile = Path.Combine(baseDirectory, String.Format("{0}.png", pngCount.ToString("D8"))); ParseFile.ExtractChunkToFile(subtitleStream, pngStartOffset, pngSize, destinationFile); pngCount++; // write timestamp and PNG to file // move to next block currentOffset += 0xE + subtitlePacketSize; } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractStruct, DoWorkEventArgs e) { ExtractCriAcbAwbStruct extractStruct = (ExtractCriAcbAwbStruct)pExtractStruct; byte[] magicBytes; long awbOffset = 0; using (FileStream fs = File.Open(pPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { magicBytes = ParseFile.ParseSimpleOffset(fs, 0, 4); this.progressStruct.Clear(); // ACB if (ParseFile.CompareSegment(magicBytes, 0, CriAcbFile.SIGNATURE_BYTES)) { this.progressStruct.GenericMessage = String.Format("Processing ACB file: '{0}'.{1}", Path.GetFileName(pPath), Environment.NewLine); ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); CriAcbFile acb = new CriAcbFile(fs, 0, extractStruct.IncludeCueIdInFileName); acb.ExtractAll(); } else if (ParseFile.CompareSegment(magicBytes, 0, CriAfs2Archive.SIGNATURE)) { this.progressStruct.GenericMessage = String.Format("Processing AWB file: '{0}'.{1}", Path.GetFileName(pPath), Environment.NewLine); ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); CriAfs2Archive afs2 = new CriAfs2Archive(fs, 0); afs2.ExtractAll(); } else { this.progressStruct.GenericMessage = String.Format("ACB/AWB signature not found at offset 0...scanning for AWB signature: '{0}'.{1}", Path.GetFileName(pPath), Environment.NewLine); ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); awbOffset = ParseFile.GetNextOffset(fs, 0, CriAfs2Archive.SIGNATURE); if (awbOffset > 0) { CriAfs2Archive afs2 = new CriAfs2Archive(fs, awbOffset); afs2.ExtractAll(); } else { this.progressStruct.GenericMessage = String.Format("File is not an ACB or AWB...skipping: '{0}'.{1}", Path.GetFileName(pPath), Environment.NewLine); ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); } } } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractMidiStruct, DoWorkEventArgs e) { long headerOffset = 0; using (FileStream fs = File.OpenRead(pPath)) { while ((headerOffset = ParseFile.GetNextOffset(fs, headerOffset, Midi.ASCII_SIGNATURE_MTHD)) > -1) { Midi midiFile = new Midi(); midiFile.Initialize(fs, pPath, headerOffset); midiFile.ExtractToFile(fs, Path.Combine(Path.GetDirectoryName(pPath), Path.GetFileNameWithoutExtension(pPath))); headerOffset += 1; } } }
public UInt32 getEndOfTrackForSequenceNumber(Stream pStream, int pSequenceNumber) { UInt32 ret = 0; if (pSequenceNumber <= this.midiChunk.maxSeqCount && this.midiChunk.subSeqOffsetAddr[pSequenceNumber] != EMPTY_MIDI_OFFSET) { Int32 midiBlockOffset = MIDI_CHUNK_OFFSET + this.midiChunk.subSeqOffsetAddr[pSequenceNumber]; long endOfTrackOffset = ParseFile.GetNextOffset(pStream, (long)midiBlockOffset, END_OF_TRACK_BYTES); ret = (UInt32)endOfTrackOffset; } return(ret); }
public static IVolume[] GetVolumes(string isoPath, bool isRawDump) { ArrayList volumeList = new ArrayList(); XDvdFsVolume volume; long volumeOffset; using (FileStream fs = File.OpenRead(isoPath)) { volumeOffset = ParseFile.GetNextOffset(fs, 0, XDvdFs.STANDARD_IDENTIFIER, true, 0x800, 0); volume = new XDvdFsVolume(); volume.Initialize(fs, volumeOffset, isRawDump); volumeList.Add(volume); } return((IVolume[])volumeList.ToArray(typeof(XDvdFsVolume))); }
public UInt32 getTempoForSequenceNumber(Stream pStream, int pSequenceNumber) { UInt32 ret = 0; if (pSequenceNumber <= this.midiChunk.maxSeqCount && this.midiChunk.subSeqOffsetAddr[pSequenceNumber] != EMPTY_MIDI_OFFSET) { Int32 midiBlockOffset = MIDI_CHUNK_OFFSET + this.midiChunk.subSeqOffsetAddr[pSequenceNumber]; long setTempoOffset = ParseFile.GetNextOffset(pStream, (long)midiBlockOffset, SET_TEMPO_BYTES); byte[] tempoValBytes = new byte[4]; Array.Copy(ParseFile.ParseSimpleOffset(pStream, setTempoOffset + 3, 3), 0, tempoValBytes, 1, 3); Array.Reverse(tempoValBytes); // flip order to LE for use with BitConverter ret = BitConverter.ToUInt32(tempoValBytes, 0); } return(ret); }
private static bool IsSilentBlock(byte[] pCdxaBlock, ExtractXaStruct pExtractXaStruct) { bool ret = false; int silentFrameCount = 0; long bufferOffset = 0; while ((bufferOffset = ParseFile.GetNextOffset(pCdxaBlock, bufferOffset, Cdxa.XA_SILENT_FRAME)) > -1) { silentFrameCount++; bufferOffset += 1; } // did we find enough silent frames? if (silentFrameCount >= pExtractXaStruct.SilentFramesCount) { ret = true; } return(ret); }
public static uint GetRiffHeaderSize(string riffHeaderedFile) { uint headerSize = 0; using (FileStream fs = File.OpenRead(riffHeaderedFile)) { long riffHeaderLocation = ParseFile.GetNextOffset(fs, 0, Constants.RiffHeaderBytes); if (riffHeaderLocation > -1) { long waveChunkLocation = ParseFile.GetNextOffset(fs, riffHeaderLocation + Constants.RiffHeaderBytes.Length, Constants.RiffWaveBytes); if (waveChunkLocation > -1) { long dataChunkLocation = ParseFile.GetNextOffset(fs, waveChunkLocation + Constants.RiffWaveBytes.Length, Constants.RiffDataBytes); if (dataChunkLocation > -1) { headerSize = (uint)(dataChunkLocation + Constants.RiffDataBytes.Length + 4); } else { throw new FormatException("RIFF header data chunk not found."); } } else { throw new FormatException("RIFF header WAVE chunk not found."); } } else { throw new FormatException("RIFF header not found."); } } return(headerSize); }
public static uint GetDataSizeFromRiffHeader(string riffHeaderedFile) { uint dataSize = 0; using (FileStream fs = File.OpenRead(riffHeaderedFile)) { long riffHeaderLocation = ParseFile.GetNextOffset(fs, 0, Constants.RiffHeaderBytes); if (riffHeaderLocation > -1) { long waveChunkLocation = ParseFile.GetNextOffset(fs, riffHeaderLocation + Constants.RiffHeaderBytes.Length, Constants.RiffWaveBytes); if (waveChunkLocation > -1) { long dataChunkLocation = ParseFile.GetNextOffset(fs, waveChunkLocation + Constants.RiffWaveBytes.Length, Constants.RiffDataBytes); if (dataChunkLocation > -1) { dataSize = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, dataChunkLocation + 4, 4), 0); } else { throw new FormatException("RIFF header data chunk not found."); } } else { throw new FormatException("RIFF header WAVE chunk not found."); } } else { throw new FormatException("RIFF header not found."); } } return(dataSize); }
public static ushort GetChannelsFromRiffHeader(string riffHeaderedFile) { ushort channels = 0; using (FileStream fs = File.OpenRead(riffHeaderedFile)) { long riffHeaderLocation = ParseFile.GetNextOffset(fs, 0, Constants.RiffHeaderBytes); if (riffHeaderLocation > -1) { long waveChunkLocation = ParseFile.GetNextOffset(fs, riffHeaderLocation + Constants.RiffHeaderBytes.Length, Constants.RiffWaveBytes); if (waveChunkLocation > -1) { long fmtChunkLocation = ParseFile.GetNextOffset(fs, waveChunkLocation + Constants.RiffWaveBytes.Length, Constants.RiffFmtBytes); if (fmtChunkLocation > -1) { channels = BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, fmtChunkLocation + 0xA, 2), 0); } else { throw new FormatException("RIFF header data chunk not found."); } } else { throw new FormatException("RIFF header WAVE chunk not found."); } } else { throw new FormatException("RIFF header not found."); } } return(channels); }
public static IVolume[] GetVolumes(string isoPath, bool isRawDump) { ArrayList volumeList = new ArrayList(); Iso9660Volume volume; long volumeOffset; using (FileStream fs = File.OpenRead(isoPath)) { volumeOffset = ParseFile.GetNextOffset(fs, 0, Iso9660.VOLUME_DESCRIPTOR_IDENTIFIER); while (volumeOffset > -1) { volume = new Iso9660Volume(); volume.Initialize(fs, volumeOffset, isRawDump); volumeList.Add(volume); volumeOffset = ParseFile.GetNextOffset(fs, volume.VolumeBaseOffset + ((long)volume.VolumeSpaceSize * (long)volume.LogicalBlockSize), Iso9660.VOLUME_DESCRIPTOR_IDENTIFIER); } } return((IVolume[])volumeList.ToArray(typeof(Iso9660Volume))); }
public static uint GetSeqCount(string fileName) { uint seqCount = 0; long offset = 0; if (PsxSequence.IsSepTypeSequence(fileName)) { using (FileStream fs = File.OpenRead(fileName)) { while ((offset = ParseFile.GetNextOffset(fs, offset, PsxSequence.END_SEQUENCE)) > -1) { seqCount++; offset++; } } } else if (PsxSequence.IsSeqTypeSequence(fileName)) { seqCount = 1; } return(seqCount); }
public static uint GetFrequencyFromRiffHeader(Stream inputStream) { uint frequency = 0; long riffHeaderLocation = ParseFile.GetNextOffset(inputStream, 0, Constants.RiffHeaderBytes); if (riffHeaderLocation > -1) { long waveChunkLocation = ParseFile.GetNextOffset(inputStream, riffHeaderLocation + Constants.RiffHeaderBytes.Length, Constants.RiffWaveBytes); if (waveChunkLocation > -1) { long fmtChunkLocation = ParseFile.GetNextOffset(inputStream, waveChunkLocation + Constants.RiffWaveBytes.Length, Constants.RiffFmtBytes); if (fmtChunkLocation > -1) { frequency = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(inputStream, fmtChunkLocation + 0xC, 4), 0); } else { throw new FormatException("RIFF header data chunk not found."); } } else { throw new FormatException("RIFF header WAVE chunk not found."); } } else { throw new FormatException("RIFF header not found."); } return(frequency); }
public static uint GetRiffHeaderSize(Stream inputStream) { uint headerSize = 0; long riffHeaderLocation = ParseFile.GetNextOffset(inputStream, 0, Constants.RiffHeaderBytes); if (riffHeaderLocation > -1) { long waveChunkLocation = ParseFile.GetNextOffset(inputStream, riffHeaderLocation + Constants.RiffHeaderBytes.Length, Constants.RiffWaveBytes); if (waveChunkLocation > -1) { long dataChunkLocation = ParseFile.GetNextOffset(inputStream, waveChunkLocation + Constants.RiffWaveBytes.Length, Constants.RiffDataBytes); if (dataChunkLocation > -1) { headerSize = (uint)(dataChunkLocation + Constants.RiffDataBytes.Length + 4); } else { throw new FormatException("RIFF header data chunk not found."); } } else { throw new FormatException("RIFF header WAVE chunk not found."); } } else { throw new FormatException("RIFF header not found."); } return(headerSize); }
public static long GetDataStartOffsetFromRiffHeader(Stream inputStream) { long dataOffset = 0; long riffHeaderLocation = ParseFile.GetNextOffset(inputStream, 0, Constants.RiffHeaderBytes); if (riffHeaderLocation > -1) { long waveChunkLocation = ParseFile.GetNextOffset(inputStream, riffHeaderLocation + Constants.RiffHeaderBytes.Length, Constants.RiffWaveBytes); if (waveChunkLocation > -1) { long dataChunkLocation = ParseFile.GetNextOffset(inputStream, waveChunkLocation + Constants.RiffWaveBytes.Length, Constants.RiffDataBytes); if (dataChunkLocation > -1) { dataOffset = dataChunkLocation + 8; } else { throw new FormatException("RIFF header data chunk not found."); } } else { throw new FormatException("RIFF header WAVE chunk not found."); } } else { throw new FormatException("RIFF header not found."); } return(dataOffset); }
public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions) { long currentOffset = 0; long fileSize; long blockSize; long videoChunkSize; Dictionary <uint, FileStream> streamOutputWriters = new Dictionary <uint, FileStream>(); ChunkStruct currentChunk = new ChunkStruct(); ChunkStruct[] audioChunks; try { using (FileStream fs = File.OpenRead(this.FilePath)) { this.ReadHeader(fs, currentOffset); fileSize = fs.Length; currentOffset = ParseFile.GetNextOffset(fs, currentOffset, DataStartBytes) + 4; while (currentOffset < fileSize) { if (currentOffset == 0x4C7DC) { } blockSize = this.GetBlockSize(fs, currentOffset); if (blockSize > 0) { // write video block to stream currentChunk = this.GetVideoChunk(fs, currentOffset); if (demuxOptions.ExtractVideo && (currentChunk.Chunk != null)) { this.writeChunkToStream(currentChunk.Chunk, currentChunk.ChunkId, streamOutputWriters, this.FileExtensionVideo); } // NDS -- currentBlockId = (uint)(BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, currentOffset, 2), 0) & 0x00FF); // write audio block to stream if (demuxOptions.ExtractAudio && (this.AudioStreamCount > 0)) { videoChunkSize = currentChunk.Chunk == null ? 0 : currentChunk.Chunk.Length; audioChunks = this.GetAudioChunk(fs, currentOffset, blockSize, videoChunkSize); for (uint i = 0; i < this.AudioStreamCount; i++) { if (audioChunks[i].Chunk != null) { this.writeChunkToStream(audioChunks[i].Chunk, audioChunks[i].ChunkId, streamOutputWriters, this.FileExtensionAudio); } } } // move offset currentOffset += blockSize; } else { break; } } } // using (FileStream fs = File.OpenRead(this.FilePath)) } catch (Exception ex) { throw new Exception(String.Format("Exception processing block at offset 0x{0}: {1}{2}", currentOffset.ToString("X"), ex.Message, Environment.NewLine)); } finally { // clean up this.DoFinalTasks(streamOutputWriters, demuxOptions); } }
public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions) { long currentOffset = -1; long fileSize; byte[] chunkId; byte[] fullChunk; uint chunkSize = 0; long mvhdOffset = -1; long schlOffset = -1; long shenOffset = -1; Dictionary <string, FileStream> streamWriters = new Dictionary <string, FileStream>(); try { using (FileStream fs = File.OpenRead(this.FilePath)) { fileSize = fs.Length; // find header first header (audio or video) mvhdOffset = ParseFile.GetNextOffset(fs, 0, ElectronicArtsVp6Stream.MVHD_BYTES); if (mvhdOffset == 0) // video header comes first { currentOffset = mvhdOffset; } else // audio header comes first { schlOffset = ParseFile.GetNextOffset(fs, 0, ElectronicArtsVp6Stream.SCHl_BYTES); if ((schlOffset > -1) && (schlOffset < mvhdOffset)) { currentOffset = schlOffset; } else { shenOffset = ParseFile.GetNextOffset(fs, 0, ElectronicArtsVp6Stream.SHEN_BYTES); if ((shenOffset > -1) && (shenOffset < mvhdOffset)) { currentOffset = shenOffset; } } } // verify headers found if (mvhdOffset >= 0) { if (currentOffset >= 0) { // process file while (currentOffset < fileSize) { // get chunk chunkId = ParseFile.ParseSimpleOffset(fs, currentOffset, 4); // get chunk size chunkSize = (uint)BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, currentOffset + 4, 4), 0); // audio chunk if (demuxOptions.ExtractAudio && this.IsThisAnAudioBlock(chunkId)) { fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)chunkSize); this.writeChunkToStream(fullChunk, "audio", streamWriters, this.FileExtensionAudio); } // video chunk if (demuxOptions.ExtractVideo && this.IsThisAVideoBlock(chunkId)) { fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)chunkSize); this.writeChunkToStream(fullChunk, "video", streamWriters, this.FileExtensionVideo); } // unknown chunk if (!this.IsThisAnAudioBlock(chunkId) && !this.IsThisAVideoBlock(chunkId)) { fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)chunkSize); this.writeChunkToStream(fullChunk, "unknown", streamWriters, ".bin"); } // move to next chunk currentOffset += (long)chunkSize; } } else { throw new Exception(String.Format("Cannot find MVHD, SCHl, or SHEN headers.{0}", Environment.NewLine)); } } else { throw new Exception(String.Format("Cannot find MVHD header.{0}", Environment.NewLine)); } // if (mvhdOffset >= 0) } } catch (Exception ex) { throw new Exception(ex.Message); } finally { this.DoFinalTasks(streamWriters); } }
public virtual Dictionary <string, byte[]> DemultiplexStreams(DemuxOptionsStruct demuxOptions) { using (FileStream fs = File.OpenRead(this.FilePath)) { long fileSize = fs.Length; long currentOffset = 0; byte[] currentBlockId; uint currentBlockIdVal; byte[] currentBlockIdNaming; BlockSizeStruct blockStruct = new BlockSizeStruct(); byte[] blockSizeArray; uint blockSize; int audioBlockSkipSize; int videoBlockSkipSize; int audioBlockFooterSize; int videoBlockFooterSize; int cutSize; bool eofFlagFound = false; Dictionary <uint, MemoryStream> streamOutputWriters = new Dictionary <uint, MemoryStream>(); Dictionary <uint, string> FilenameTable = new Dictionary <uint, string>(); string outputFileName; byte streamId = 0; // for types that have multiple streams in the same block ID uint currentStreamKey; // hash key for each file bool isAudioBlock; string audioFileExtension; // look for first packet currentOffset = this.GetStartOffset(fs, currentOffset); currentOffset = ParseFile.GetNextOffset(fs, currentOffset, this.GetPacketStartBytes()); if (currentOffset != -1) { while (currentOffset < fileSize) { try { // get the current block currentBlockId = ParseFile.ParseSimpleOffset(fs, currentOffset, 4); // get value to use as key to hash table currentBlockIdVal = BitConverter.ToUInt32(currentBlockId, 0); if (BlockIdDictionary.ContainsKey(currentBlockIdVal)) { // get info about this block type blockStruct = BlockIdDictionary[currentBlockIdVal]; switch (blockStruct.SizeType) { ///////////////////// // Static Block Size ///////////////////// case PacketSizeType.Static: currentOffset += blockStruct.Size; // skip this block break; ////////////////// // End of Stream ////////////////// case PacketSizeType.Eof: eofFlagFound = true; // set EOF block found so we can exit the loop break; ////////////////////// // Varying Block Size ////////////////////// case PacketSizeType.SizeBytes: // Get the block size blockSizeArray = ParseFile.ParseSimpleOffset(fs, currentOffset + currentBlockId.Length, blockStruct.Size); if (!this.BlockSizeIsLittleEndian) { Array.Reverse(blockSizeArray); } switch (blockStruct.Size) { case 4: blockSize = (uint)BitConverter.ToUInt32(blockSizeArray, 0); break; case 2: blockSize = (uint)BitConverter.ToUInt16(blockSizeArray, 0); break; case 1: blockSize = (uint)blockSizeArray[0]; break; default: throw new ArgumentOutOfRangeException(String.Format("Unhandled size block size.{0}", Environment.NewLine)); } // if block type is audio or video, extract it isAudioBlock = this.IsThisAnAudioBlock(currentBlockId); if ((demuxOptions.ExtractAudio && isAudioBlock) || (demuxOptions.ExtractVideo && this.IsThisAVideoBlock(currentBlockId))) { // reset stream id streamId = 0; // if audio block, get the stream number from the queue if (isAudioBlock && this.UsesSameIdForMultipleAudioTracks) { streamId = this.GetStreamId(fs, currentOffset); currentStreamKey = (streamId | currentBlockIdVal); } else { currentStreamKey = currentBlockIdVal; } // check if we've already started parsing this stream if (!streamOutputWriters.ContainsKey(currentStreamKey)) { // convert block id to little endian for naming currentBlockIdNaming = BitConverter.GetBytes(currentStreamKey); Array.Reverse(currentBlockIdNaming); // build output file name outputFileName = Path.GetFileNameWithoutExtension(this.FilePath); outputFileName = outputFileName + "_" + BitConverter.ToUInt32(currentBlockIdNaming, 0).ToString("X8"); // add proper extension if (this.IsThisAnAudioBlock(currentBlockId)) { audioFileExtension = this.GetAudioFileExtension(fs, currentOffset); outputFileName += audioFileExtension; if (!this.StreamIdFileType.ContainsKey(streamId)) { this.StreamIdFileType.Add(streamId, audioFileExtension); } } else { this.FileExtensionVideo = this.GetVideoFileExtension(fs, currentOffset); outputFileName += this.FileExtensionVideo; } // add output directory FilenameTable[currentStreamKey] = outputFileName; // add an output stream for writing streamOutputWriters[currentStreamKey] = new MemoryStream(); } // write the block if (this.IsThisAnAudioBlock(currentBlockId)) { // write audio audioBlockSkipSize = this.GetAudioPacketHeaderSize(fs, currentOffset) + GetAudioPacketSubHeaderSize(fs, currentOffset, streamId); audioBlockFooterSize = this.GetAudioPacketFooterSize(fs, currentOffset); cutSize = (int)(blockSize - audioBlockSkipSize - audioBlockFooterSize); if (cutSize > 0) { streamOutputWriters[currentStreamKey].Write(ParseFile.ParseSimpleOffset(fs, currentOffset + currentBlockId.Length + blockSizeArray.Length + audioBlockSkipSize, (int)(blockSize - audioBlockSkipSize)), 0, cutSize); } } else { // write video videoBlockSkipSize = this.GetVideoPacketHeaderSize(fs, currentOffset); videoBlockFooterSize = this.GetVideoPacketFooterSize(fs, currentOffset); cutSize = (int)(blockSize - videoBlockSkipSize - videoBlockFooterSize); if (cutSize > 0) { streamOutputWriters[currentStreamKey].Write(ParseFile.ParseSimpleOffset(fs, currentOffset + currentBlockId.Length + blockSizeArray.Length + videoBlockSkipSize, (int)(blockSize - videoBlockSkipSize)), 0, cutSize); } } } // move to next block currentOffset += currentBlockId.Length + blockSizeArray.Length + blockSize; blockSizeArray = new byte[] { }; break; default: break; } } else // this is an undexpected block type { this.CloseAllWriters(streamOutputWriters); Array.Reverse(currentBlockId); throw new FormatException(String.Format("Block ID at 0x{0} not found in table: 0x{1}", currentOffset.ToString("X8"), BitConverter.ToUInt32(currentBlockId, 0).ToString("X8"))); } // exit loop if EOF block found if (eofFlagFound) { break; } } catch (Exception _ex) { this.CloseAllWriters(streamOutputWriters); throw new Exception(String.Format("Error parsing file at offset {0), '{1}'", currentOffset.ToString("X8"), _ex.Message), _ex); } } // while (currentOffset < fileSize) } else { this.CloseAllWriters(streamOutputWriters); throw new FormatException(String.Format("Cannot find Pack Header for file: {0}{1}", Path.GetFileName(this.FilePath), Environment.NewLine)); } return(this.DoFinalTasks(fs, FilenameTable, streamOutputWriters, demuxOptions.AddHeader)); } }
public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions) { long currentOffset = 0; long packetOffset = 0; long packetSize; long fileSize; Dictionary <uint, FileStream> streamOutputWriters = new Dictionary <uint, FileStream>(); Guid checkGuid; ulong blockSize; try { using (FileStream fs = File.OpenRead(this.FilePath)) { fileSize = fs.Length; currentOffset = 0; currentOffset = ParseFile.GetNextOffset(fs, 0, MicrosoftAsfContainer.ASF_HEADER_BYTES); if (currentOffset > -1) { while (currentOffset < fileSize) { // get guid checkGuid = new Guid(ParseFile.ParseSimpleOffset(fs, currentOffset, 0x10)); blockSize = BitConverter.ToUInt64(ParseFile.ParseSimpleOffset(fs, (currentOffset + 0x10), 8), 0); // process block if (checkGuid.Equals(MicrosoftAsfContainer.ASF_Header_Object)) { // parse header this.parseHeader(fs, currentOffset); } else if (checkGuid.Equals(MicrosoftAsfContainer.ASF_Data_Object)) { // parse data object this.DataObject = this.parseDataObject(fs, currentOffset); // process data packets packetOffset = currentOffset + 0x32; // header has been parsed for (ulong i = 0; i < this.DataObject.TotalDataPackets; i++) { // parse packet try { packetSize = this.parseDataPacket(fs, packetOffset, demuxOptions); // move to next packet if (packetSize < 0) { throw new Exception(String.Format("Error parsing data packet at offset 0x{0}.", packetOffset.ToString("X8"))); } else { packetOffset += packetSize; } } catch (Exception ex) { throw new Exception(String.Format("Error parsing data packet at offset 0x{0}: {1}.{2}", packetOffset.ToString("X8"), ex.Message, Environment.NewLine)); } } } // increment counter currentOffset += (long)blockSize; } // while } else { throw new Exception(String.Format("ASF/WMV Header not found.{0}", Environment.NewLine)); } } // using (FileStream fs = File.OpenRead(this.FilePath)) } catch (Exception ex) { throw new Exception(String.Format("Exception processing block at offset 0x{0}: {1}{2}", currentOffset.ToString("X"), ex.Message, Environment.NewLine)); } finally { // clean up this.DoFinalTasks(demuxOptions); } }
public static void ExtractXaFiles(ExtractXaStruct pExtractXaStruct) { Dictionary <UInt32, CdxaWriterStruct> bwDictionary = new Dictionary <UInt32, CdxaWriterStruct>(); List <UInt32> bwKeys; long offset; byte[] trackId; byte[] buffer = new byte[Cdxa.XA_BLOCK_SIZE]; UInt32 trackKey; byte[] tempTrackId; UInt32 tempTrackKey; long previousOffset; long distanceBetweenBlocks; long distanceCeiling = EMPTY_BLOCK_OFFSET_FLAG; Dictionary <long, int> distanceFrequency = new Dictionary <long, int>(); CdxaWriterStruct workingStruct = new CdxaWriterStruct(); string outputFileName; string outputDirectory = Path.Combine(Path.GetDirectoryName(pExtractXaStruct.Path), Path.GetFileNameWithoutExtension(pExtractXaStruct.Path)); int totalPasses = 1; bool doFileWrite = false; if (pExtractXaStruct.DoTwoPass) { totalPasses = 2; } using (FileStream fs = File.OpenRead(pExtractXaStruct.Path)) { for (int currentPass = 1; currentPass <= totalPasses; currentPass++) { // turn on write flag if (currentPass == totalPasses) { doFileWrite = true; } // get first offset to start the party offset = ParseFile.GetNextOffset(fs, 0, Cdxa.XA_SIG); if (offset != -1) // we have found an XA sig { if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } while ((offset != -1) && ((offset + Cdxa.XA_BLOCK_SIZE) <= fs.Length)) { trackId = ParseFile.ParseSimpleOffset(fs, offset + Cdxa.XA_TRACK_OFFSET, Cdxa.XA_TRACK_SIZE); trackKey = GetTrackKey(trackId); //trackKey = ParseFile.ReadUintBE(fs, offset + Cdxa.XA_TRACK_OFFSET) & 0xFFFF0000; if (pExtractXaStruct.UseEndOfTrackMarkerForEof && ( ((trackId[2] & Cdxa.XA_END_OF_TRACK_MARKER) == Cdxa.XA_END_OF_TRACK_MARKER) || ((trackId[2] & Cdxa.XA_END_OF_AUDIO_MARKER) == Cdxa.XA_END_OF_AUDIO_MARKER) )) { // close the track tempTrackId = trackId; tempTrackId[2] = Cdxa.XA_CHUNK_ID_DIGITS; tempTrackKey = GetTrackKey(tempTrackId); if (bwDictionary.ContainsKey(tempTrackKey)) { // close up this file, we're done. if (doFileWrite) { // write the block // set offset, doing this way because of boxing issues workingStruct = bwDictionary[tempTrackKey]; workingStruct.CurrentChunkOffset = offset; bwDictionary[tempTrackKey] = workingStruct; // get the next block buffer = ParseFile.ParseSimpleOffset(fs, offset, Cdxa.XA_BLOCK_SIZE); // patch if needed if (pExtractXaStruct.PatchByte0x11) { buffer[0x11] = 0x00; } // write the block bwDictionary[tempTrackKey].FileWriter.Write(buffer, 0, buffer.Length); // set flag that a non-silent block was found if (!bwDictionary[tempTrackKey].NonSilentBlockDetected) { // doing this way because of boxing issues workingStruct = bwDictionary[tempTrackKey]; workingStruct.NonSilentBlockDetected = true; bwDictionary[tempTrackKey] = workingStruct; } FixHeaderAndCloseWriter(bwDictionary[tempTrackKey].FileWriter, pExtractXaStruct, bwDictionary[tempTrackKey].NonSilentBlockDetected); } bwDictionary.Remove(tempTrackKey); } offset += Cdxa.XA_BLOCK_SIZE; } else if ((pExtractXaStruct.FilterAgainstBlockId) && ((trackId[2] & 0x0F) != Cdxa.XA_AUDIO_MASK)) { offset = ParseFile.GetNextOffset(fs, offset + 1, Cdxa.XA_SIG); } else { // check distance between blocks for possible split if ((doFileWrite) && (bwDictionary.ContainsKey(trackKey)) && (distanceCeiling != EMPTY_BLOCK_OFFSET_FLAG) && (bwDictionary[trackKey].CurrentChunkOffset != EMPTY_BLOCK_OFFSET_FLAG)) { previousOffset = bwDictionary[trackKey].CurrentChunkOffset; distanceBetweenBlocks = offset - previousOffset; if (distanceBetweenBlocks > distanceCeiling) { // close up this file, we're done. FixHeaderAndCloseWriter(bwDictionary[trackKey].FileWriter, pExtractXaStruct, bwDictionary[trackKey].NonSilentBlockDetected); bwDictionary.Remove(trackKey); } } // First Block only if (!bwDictionary.ContainsKey(trackKey)) { outputFileName = GetOutputFileName(pExtractXaStruct, trackId); workingStruct = new CdxaWriterStruct(); workingStruct.CurrentChunkOffset = EMPTY_BLOCK_OFFSET_FLAG; workingStruct.NonSilentBlockDetected = false; if (doFileWrite) { workingStruct.FileWriter = File.Open(outputFileName, FileMode.Create, FileAccess.ReadWrite); } bwDictionary.Add(trackKey, workingStruct); if (doFileWrite && pExtractXaStruct.AddRiffHeader) { bwDictionary[trackKey].FileWriter.Write(Cdxa.XA_RIFF_HEADER, 0, Cdxa.XA_RIFF_HEADER.Length); } } // calculate distance between blocks for possible split if ((!doFileWrite) && (bwDictionary[trackKey].CurrentChunkOffset != EMPTY_BLOCK_OFFSET_FLAG)) { previousOffset = bwDictionary[trackKey].CurrentChunkOffset; distanceBetweenBlocks = offset - previousOffset; if (!distanceFrequency.ContainsKey(distanceBetweenBlocks)) { distanceFrequency.Add(distanceBetweenBlocks, 1); } else { distanceFrequency[distanceBetweenBlocks]++; } } // set offset, doing this way because of boxing issues workingStruct = bwDictionary[trackKey]; workingStruct.CurrentChunkOffset = offset; bwDictionary[trackKey] = workingStruct; // get the next block buffer = ParseFile.ParseSimpleOffset(fs, offset, Cdxa.XA_BLOCK_SIZE); // check if this is a "silent" block if ((pExtractXaStruct.UseSilentBlocksForEof) && IsSilentBlock(buffer, pExtractXaStruct)) { if (doFileWrite) { // close up this file, we're done. FixHeaderAndCloseWriter(bwDictionary[trackKey].FileWriter, pExtractXaStruct, bwDictionary[trackKey].NonSilentBlockDetected); } bwDictionary.Remove(trackKey); } else if (doFileWrite) { // patch if needed if (pExtractXaStruct.PatchByte0x11) { buffer[0x11] = 0x00; } // write the block bwDictionary[trackKey].FileWriter.Write(buffer, 0, buffer.Length); // set flag that a non-silent block was found if (!bwDictionary[trackKey].NonSilentBlockDetected) { // doing this way because of boxing issues workingStruct = bwDictionary[trackKey]; workingStruct.NonSilentBlockDetected = true; bwDictionary[trackKey] = workingStruct; } } offset += Cdxa.XA_BLOCK_SIZE; } } // fix header and close writers bwKeys = new List <UInt32>(bwDictionary.Keys); foreach (UInt32 keyname in bwKeys) { if (doFileWrite) { FixHeaderAndCloseWriter(bwDictionary[keyname].FileWriter, pExtractXaStruct, bwDictionary[keyname].NonSilentBlockDetected); } bwDictionary.Remove(keyname); } // get statistical mode of distance between blocks if (!doFileWrite) { distanceCeiling = GetDistanceCeiling(distanceFrequency); } } else { // no CD-XA found break; } } } }
public void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions) { long currentOffset = 0; uint frameCount = 1; uint nextFrameSize; byte[] currentFrame; byte[] videoChunkSizeBytes = null; uint videoChunkSize; byte[] audioChunkSizeBytes = null; uint audioChunkSize; long dataStart; byte[] videoChunk; byte[] audioChunk; // bool isAudioHeaderWritten = false; Dictionary <string, bool> isAudioHeaderWritten = new Dictionary <string, bool>(); bool isVideoHeaderWritten = false; byte[] thpHeader; byte[] firstFrameSize; long headerLocation; uint previousFrameSizeVideo = 0; uint previousFrameSizeAudio = 0; uint nextFrameSizeVideo; uint nextFrameSizeAudio; byte[] previousFrameSizeBytes; byte[] nextFrameSizeBytes; uint totalDataSize = 0; byte[] totalDataSizeBytes; byte[] fourEmptyBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; long videoFrameOffset = 0; long audioFrameOffset = 0; byte[] lastOffsetBytes; string audioStreamHashKey; byte[] bigEndianOne = new byte[] { 0x00, 0x00, 0x00, 0x01 }; Dictionary <string, FileStream> streamWriters = new Dictionary <string, FileStream>(); try { using (FileStream fs = File.OpenRead(this.FilePath)) { headerLocation = ParseFile.GetNextOffset(fs, currentOffset, MAGIC_BYTES); currentOffset = headerLocation; if (currentOffset > -1) { // read header this.ReadHeader(fs, currentOffset); nextFrameSize = this.FirstFrameSize; // get component info this.ParseComponents(fs); // process frames currentOffset = this.FirstFrameOffset; while (currentOffset <= this.LastFrameOffset) { // read frame currentFrame = ParseFile.ParseSimpleOffset(fs, (long)currentOffset, (int)nextFrameSize); // get size of next frame nextFrameSize = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(currentFrame, 0, 4)); // get size of next audio/video frame (for writing output frame headers) if (frameCount < this.NumberOfFrames) { nextFrameSizeVideo = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, currentOffset + currentFrame.Length + 8, 4)); nextFrameSizeAudio = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, currentOffset + currentFrame.Length + 0xC, 4)); } else { nextFrameSizeVideo = 0; nextFrameSizeAudio = 0; } videoChunkSizeBytes = ParseFile.ParseSimpleOffset(currentFrame, 8, 4); videoChunkSize = ByteConversion.GetUInt32BigEndian(videoChunkSizeBytes); if (this.ContainsAudio) { audioChunkSizeBytes = ParseFile.ParseSimpleOffset(currentFrame, 0xC, 4); audioChunkSize = ByteConversion.GetUInt32BigEndian(audioChunkSizeBytes); dataStart = 0x10; } else { audioChunkSize = 0; dataStart = 0xC; } #region WRITE VIDEO /////////////// // write video /////////////// if (demuxOptions.ExtractVideo) { if (streamWriters.ContainsKey("video")) { videoFrameOffset = streamWriters["video"].Length; } // attach THP header if (!isVideoHeaderWritten) { // get original header thpHeader = ParseFile.ParseSimpleOffset(fs, headerLocation, (int)(fs.Length - this.DataSize)); // clean out audio info thpHeader = this.RemoveAudioInfoFromThpHeader(thpHeader); // update first frame size in header firstFrameSize = ByteConversion.GetBytesBigEndian((uint)(videoChunkSize + 0xC)); Array.Copy(firstFrameSize, 0, thpHeader, 0x18, 4); // write updated header this.writeChunkToStream(thpHeader, "video", streamWriters, this.FileExtensionVideo); isVideoHeaderWritten = true; } // add frame header // write next frame size nextFrameSizeBytes = ByteConversion.GetBytesBigEndian((uint)(nextFrameSizeVideo + 0xC)); this.writeChunkToStream(nextFrameSizeBytes, "video", streamWriters, this.FileExtensionVideo); // write previous frame size previousFrameSizeBytes = ByteConversion.GetBytesBigEndian((uint)(previousFrameSizeVideo + 0xC)); this.writeChunkToStream(nextFrameSizeBytes, "video", streamWriters, this.FileExtensionVideo); // write video size this.writeChunkToStream(videoChunkSizeBytes, "video", streamWriters, this.FileExtensionVideo); // write data videoChunk = ParseFile.ParseSimpleOffset(currentFrame, (int)dataStart, (int)videoChunkSize); this.writeChunkToStream(videoChunk, "video", streamWriters, this.FileExtensionVideo); // save previous bytes for next frame previousFrameSizeVideo = videoChunkSize; } #endregion #region WRITE AUDIO /////////////// // write audio /////////////// if (demuxOptions.ExtractAudio && this.ContainsAudio) { //if (this.NumberOfAudioBlocksPerFrame > 1) //{ // int x = 1; //} // add blocks for (int i = 0; i < this.NumberOfAudioBlocksPerFrame; i++) { audioStreamHashKey = String.Format("track_{0}", i.ToString("D2")); // write file header if (streamWriters.ContainsKey(audioStreamHashKey)) { audioFrameOffset = streamWriters[audioStreamHashKey].Position; } // attach THP header if (!isAudioHeaderWritten.ContainsKey(audioStreamHashKey) || isAudioHeaderWritten[audioStreamHashKey] == false) { // get original header thpHeader = ParseFile.ParseSimpleOffset(fs, headerLocation, (int)(fs.Length - this.DataSize)); // clean out video info thpHeader = this.RemoveVideoInfoFromThpHeader(thpHeader); // update first frame size in header firstFrameSize = ByteConversion.GetBytesBigEndian((uint)(audioChunkSize + 0x10)); Array.Copy(firstFrameSize, 0, thpHeader, 0x18, 4); // set NumberOfAudioBlocksPerFrame to 1 Array.Copy(bigEndianOne, 0, thpHeader, 0x50, 4); // write updated header this.writeChunkToStream(thpHeader, audioStreamHashKey, streamWriters, this.FileExtensionAudio); isAudioHeaderWritten.Add(audioStreamHashKey, true); } ////////////////////// // write frame header ////////////////////// // write next frame size nextFrameSizeBytes = ByteConversion.GetBytesBigEndian((uint)(nextFrameSizeAudio + 0x10)); this.writeChunkToStream(nextFrameSizeBytes, audioStreamHashKey, streamWriters, this.FileExtensionAudio); // write previous frame size previousFrameSizeBytes = ByteConversion.GetBytesBigEndian((uint)(previousFrameSizeAudio + 0x10)); this.writeChunkToStream(nextFrameSizeBytes, audioStreamHashKey, streamWriters, this.FileExtensionAudio); // write video size (zero) this.writeChunkToStream(fourEmptyBytes, audioStreamHashKey, streamWriters, this.FileExtensionAudio); // write audio size for this frame this.writeChunkToStream(audioChunkSizeBytes, audioStreamHashKey, streamWriters, this.FileExtensionAudio); // write chunk audioChunk = ParseFile.ParseSimpleOffset(currentFrame, (int)(dataStart + videoChunkSize + (i * audioChunkSize)), (int)audioChunkSize); this.writeChunkToStream(audioChunk, audioStreamHashKey, streamWriters, this.FileExtensionAudio); // set previous frame size for next frame previousFrameSizeAudio = audioChunkSize; } } #endregion // increment offset and frame counter currentOffset += currentFrame.Length; frameCount++; } // fix headers as needed // data size foreach (string key in streamWriters.Keys) { totalDataSize = (uint)(streamWriters[key].Length - this.FirstFrameOffset); totalDataSizeBytes = ByteConversion.GetBytesBigEndian(totalDataSize); streamWriters[key].Position = 0x1C; streamWriters[key].Write(totalDataSizeBytes, 0, 4); } // frame offsets for (int i = 0; i < this.NumberOfAudioBlocksPerFrame; i++) { audioStreamHashKey = String.Format("audio_{0}", i.ToString("DD")); if (streamWriters.ContainsKey(audioStreamHashKey)) { lastOffsetBytes = ByteConversion.GetBytesBigEndian((uint)audioFrameOffset); streamWriters[audioStreamHashKey].Position = 0x2C; streamWriters[audioStreamHashKey].Write(lastOffsetBytes, 0, 4); } } if (streamWriters.ContainsKey("video")) { lastOffsetBytes = ByteConversion.GetBytesBigEndian((uint)videoFrameOffset); streamWriters["video"].Position = 0x2C; streamWriters["video"].Write(lastOffsetBytes, 0, 4); } } else { throw new FormatException("Cannot find THP header."); } } // using (FileStream fs = File.OpenRead(this.FilePath)) } catch (Exception ex) { throw new Exception(ex.Message, ex); } finally { foreach (string key in streamWriters.Keys) { // close writers if (streamWriters[key] != null && streamWriters[key].CanWrite) { streamWriters[key].Close(); streamWriters[key].Dispose(); } } } }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pPsfDataFinderStruct, DoWorkEventArgs e) { PsfDataFinderStruct psfStruct = (PsfDataFinderStruct)pPsfDataFinderStruct; this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("[{0}]{1}", pPath, Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); long offset; string seqName; int seqNumber = 0; ArrayList seqFiles = new ArrayList(); bool seqNamingMessageDisplayed = false; string sepName; int sepNumber = 0; ArrayList sepFiles = new ArrayList(); bool sepNamingMessageDisplayed = false; int vhNumber = 0; int minSampleSize = -1; int maxSampleSize = -1; int minRowLength; VhStruct vhObject; long sampleOffset; ArrayList vhArrayList = new ArrayList(); ArrayList emptyRowList = new ArrayList(); ProbableVbStruct potentialVb; ProbableVbStruct[] potentialVbList; byte[] vbRow = new byte[0x10]; long previousVbOffset = -1; // improve algorithm later using (FileStream fs = File.OpenRead(pPath)) { string destinationFolder = Path.Combine(Path.GetDirectoryName(pPath), Path.GetFileNameWithoutExtension(pPath)); // get VH files #region VH EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting VH{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; while ((offset = ParseFile.GetNextOffset(fs, offset, XsfUtil.VAB_SIGNATURE)) > -1) { vhObject = new VhStruct(); vhObject.FileName = String.Format("{0}_{1}.VH", Path.GetFileNameWithoutExtension(pPath), vhNumber++.ToString("X4")); vhObject.startingOffset = offset; vhObject.vhProgramCount = BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, (offset + 0x12), 2), 0); vhObject.vbSampleCount = BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, (offset + 0x16), 2), 0); vhObject.vbSampleSizes = new uint[vhObject.vbSampleCount]; vhObject.length = 2592 + (512 * vhObject.vhProgramCount); vhObject.vabSize = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0xC, 4), 0); vhObject.expectedVbLength = vhObject.vabSize - vhObject.length; vhObject.offsetTableOffset = offset + (512 * vhObject.vhProgramCount) + 2080; vhObject.offsetTableOffset += 2; // not sure but seems to be needed vhObject.IsSmallSamplePresent = false; vhObject.HasHeaderMismatch = false; for (int i = 0; i < vhObject.vbSampleCount; i++) { sampleOffset = vhObject.offsetTableOffset + (i * 2); vhObject.vbSampleSizes[i] = (uint)BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, sampleOffset, 2), 0); vhObject.vbSampleSizes[i] <<= 3; vhObject.expectedVbLengthBySample += vhObject.vbSampleSizes[i]; if ((minSampleSize < 0) || (vhObject.vbSampleSizes[i] < minSampleSize)) { minSampleSize = (int)vhObject.vbSampleSizes[i]; if (minSampleSize < Psf.MIN_ADPCM_ROW_SIZE) { vhObject.IsSmallSamplePresent = true; } } // update max sample size if ((maxSampleSize < 0) || (vhObject.vbSampleSizes[i] > maxSampleSize)) { maxSampleSize = (int)vhObject.vbSampleSizes[i]; } } if (vhObject.expectedVbLength != vhObject.expectedVbLengthBySample) { vhObject.HasHeaderMismatch = true; //vhObject.expectedVbLength = vhObject.expectedVbLengthBySample; //this.progressStruct.Clear(); //this.progressStruct.GenericMessage = String.Format(" Warning, for VH <{0}>, header does not match samples' lengths. Ignoring header value.{1}", vhObject.FileName, Environment.NewLine); //this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); } vhArrayList.Add(vhObject); // extract file ParseFile.ExtractChunkToFile(fs, vhObject.startingOffset, (int)vhObject.length, Path.Combine(destinationFolder, vhObject.FileName), true, true); offset += 1; } #endregion // get SEQ Files #region SEQ EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting SEQ{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); // get SEQ file list seqFiles = Psf.GetSeqFileList(fs, psfStruct.UseSeqMinimumSize, psfStruct.MinimumSize); foreach (Psf.ProbableItemStruct seq in seqFiles) { if (seq.length > 0) { if (psfStruct.ReorderSeqFiles) { if ((vhArrayList.Count < seqFiles.Count)) { if (!seqNamingMessageDisplayed) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format( "Warning, cannot reorder SEQ files, there are less VH files than SEQ files.{0}", Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); seqNamingMessageDisplayed = true; } seqName = String.Format("{0}_{1}.SEQ", Path.GetFileNameWithoutExtension(pPath), seqNumber++.ToString("X4")); } else { vhObject = (VhStruct)vhArrayList[vhArrayList.Count - seqFiles.Count + seqNumber++]; seqName = Path.ChangeExtension(vhObject.FileName, ".SEQ"); } } else { seqName = String.Format("{0}_{1}.SEQ", Path.GetFileNameWithoutExtension(pPath), seqNumber++.ToString("X4")); } ParseFile.ExtractChunkToFile(fs, seq.offset, (int)seq.length, Path.Combine(destinationFolder, seqName), true, true); } else { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" Warning SEQ found with length less than 0, at Offset 0x{1}: {2}{3}", seq.offset.ToString("X8"), seq.length.ToString("X8"), Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } #endregion // get SEP Files #region SEP EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting SEP{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); // get SEP file list sepFiles = Psf.GetSepFileList(fs); foreach (Psf.ProbableItemStruct sep in sepFiles) { if (sep.length > 0) { if (psfStruct.ReorderSeqFiles) { if ((vhArrayList.Count < sepFiles.Count)) { if (!sepNamingMessageDisplayed) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format( "Warning, cannot reorder SEP files, there are less VH files than SEP files.{0}", Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); sepNamingMessageDisplayed = true; } sepName = String.Format("{0}_{1}.SEP", Path.GetFileNameWithoutExtension(pPath), sepNumber++.ToString("X4")); } else { vhObject = (VhStruct)vhArrayList[vhArrayList.Count - sepFiles.Count + sepNumber++]; sepName = Path.ChangeExtension(vhObject.FileName, ".SEP"); } } else { sepName = String.Format("{0}_{1}.SEP", Path.GetFileNameWithoutExtension(pPath), sepNumber++.ToString("X4")); } ParseFile.ExtractChunkToFile(fs, sep.offset, (int)sep.length, Path.Combine(destinationFolder, sepName), true, true); } else { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" Warning SEP found with length less than 0, at Offset 0x{1}: {2}{3}", sep.offset.ToString("X8"), sep.length.ToString("X8"), Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } #endregion // get VB files #region VB EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting VB...WARNING, THIS WILL TAKE A LONG TIME...{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; // setup arrays for checking skips VhStruct[] vhList = (VhStruct[])vhArrayList.ToArray(typeof(VhStruct)); Psf.ProbableItemStruct[] seqList = (Psf.ProbableItemStruct[])seqFiles.ToArray(typeof(Psf.ProbableItemStruct)); Psf.ProbableItemStruct[] sepList = (Psf.ProbableItemStruct[])sepFiles.ToArray(typeof(Psf.ProbableItemStruct)); // build list of potential adpcm start indexes (VB_START_BYTES) potentialVb = new ProbableVbStruct(); // check for the smallest found size or use default //minRowLength = (minSampleSize / 0x10) - 1; // divide into rows //if ((minRowLength > 0) && (minRowLength > MIN_ADPCM_ROW_COUNT)) //{ minRowLength = Psf.MIN_ADPCM_ROW_COUNT; //} while ((offset = ParseFile.GetNextOffset(fs, offset, Psf.VB_START_BYTES, psfStruct.UseZeroOffsetForVb, 0x10, 0)) > -1) { //if (offset >= 0x42E83) //{ // int r = 1; //} if (!CancellationPending) { try { vbRow = ParseFile.ParseSimpleOffset(fs, offset, vbRow.Length); // check for potential sony adpcm signature, and also make sure this offset is not inside another // more easily parsed file since those formats are solid //if ((!InsideAnotherFile(offset, vhList, seqList, sepList)) && // (IsPotentialAdpcm(fs, offset + 0x10, minRowLength))) if (Psf.IsPotentialAdpcm(fs, offset + 0x10, minRowLength, false)) { // check if we have passed a different file type and reset previousVbOffset if we did if (SteppedOverAnotherFile(previousVbOffset, offset, vhList, seqList, sepList)) { // need to add flag here so length calculation doesn't screw up? previousVbOffset = -1; } // check if we have exceeded the max sample size and reset previous offset // so the chunk size check doesn't apply if ((offset - previousVbOffset) > maxSampleSize) { previousVbOffset = -1; } // try to preserve proper VB chunk size if ((previousVbOffset == -1) || ((offset - previousVbOffset) % 0x10 == 0)) { previousVbOffset = offset; potentialVb.offset = offset; emptyRowList.Add(potentialVb); } } } catch (Exception vbEx) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR finding VB for <{0}> at Offset 0x{1}: {2}{3}", pPath, offset.ToString("X8"), vbEx.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } offset += 1; } else { e.Cancel = true; return; } } potentialVbList = (ProbableVbStruct[])emptyRowList.ToArray(typeof(ProbableVbStruct)); // set probable lengths for (int i = 0; i < potentialVbList.Length; i++) { if (i > 0) { potentialVbList[i - 1].length = (uint)(potentialVbList[i].offset - potentialVbList[i - 1].offset); } } // compare VH sample sizes to potential adpcm sizes/indexes vhObject.startingOffset = 0; vhObject.length = 0; vhObject.vbStartingOffset = 0; vhObject.vbLength = 0; string vbName; string newFileName; string[] dupeFileNames; for (int i = 0; i < vhArrayList.Count; i++) { vhObject = (VhStruct)vhArrayList[i]; if (vhObject.vbSampleSizes.Length < 1) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building VB for <{0}>: {1} refers to a single VAG, cannot determine proper VB. Skipping...{2}", pPath, vhObject.FileName, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } else { for (int j = 0; j < potentialVbList.Length; j++) { // we have a potential match or are at the last item. skip rows that are too small if ((vhObject.vbSampleSizes[0] < Psf.MIN_ADPCM_ROW_SIZE) || (vhObject.vbSampleSizes[0] <= potentialVbList[j].length) || (potentialVbList[j].length == 0)) { try { vhObject = PopulateVbOffsetLength(fs, potentialVbList, j, vhObject, psfStruct.RelaxVbEofRestrictions); if (vhObject.vbLength > 0) { // check for other BD files that matched and rename accordingly dupeFileNames = Directory.GetFiles(destinationFolder, Path.GetFileNameWithoutExtension(vhObject.FileName) + "*.VB"); if (dupeFileNames.Length >= 1) { vbName = String.Format("{0}_{1}.VB", Path.GetFileNameWithoutExtension(vhObject.FileName), (dupeFileNames.Length).ToString("X4")); if (dupeFileNames.Length == 1) { // rename existing newFileName = String.Format("{0}_{1}.VB", Path.GetFileNameWithoutExtension(vhObject.FileName), (dupeFileNames.Length - 1).ToString("X4")); File.Move(dupeFileNames[0], Path.Combine(Path.GetDirectoryName(dupeFileNames[0]), newFileName)); } } else { vbName = Path.ChangeExtension(vhObject.FileName, ".VB"); } ParseFile.ExtractChunkToFile(fs, vhObject.vbStartingOffset, (int)vhObject.vbLength, Path.Combine(destinationFolder, vbName), true, true); } } catch (Exception ex) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building VB for <{0}>: {1}{2}", pPath, ex.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } // if (vhObject.vbSampleSizes[0] == potentialVbList[j].length) } // for (int j = 0; j < potentialVbList.Length; j++) } } #endregion } }
public static bool GetPsAdpcmLoop(string pSourcePath, GenhCreationStruct pGenhCreationStruct, out string pLoopStart, out string pLoopEnd) { bool ret = false; pLoopStart = Genh.EMPTY_SAMPLE_COUNT; pLoopEnd = Genh.EMPTY_SAMPLE_COUNT; long loopStart = -1; long loopEnd = -1; long loopCheckBytesOffset; byte[] possibleLoopBytes; long headerSkip = VGMToolbox.util.ByteConversion.GetLongValueFromString(pGenhCreationStruct.HeaderSkip); int channels = (int)VGMToolbox.util.ByteConversion.GetLongValueFromString(pGenhCreationStruct.Channels); int interleave = (int)VGMToolbox.util.ByteConversion.GetLongValueFromString(pGenhCreationStruct.Interleave); string fullIncomingPath = Path.GetFullPath(pSourcePath); byte[] checkByte = new byte[1]; FileInfo fi = new FileInfo(Path.GetFullPath(fullIncomingPath)); if ((fi.Length - headerSkip) % 0x10 != 0) { throw new Exception(String.Format("Error processing <{0}> Length of file minus the header skip value is not divisible by 0x10. This is not a proper PS ADPCM rip.", fullIncomingPath)); } using (BinaryReader br = new BinaryReader(File.OpenRead(fullIncomingPath))) { // Loop Start br.BaseStream.Position = headerSkip + 0x01; while (br.BaseStream.Position < fi.Length) { br.Read(checkByte, 0, checkByte.Length); if (checkByte[0] == 0x06) { loopStart = br.BaseStream.Position - 2 - headerSkip; break; } else { br.BaseStream.Position += 0x10 - 0x01; } } // Loop End br.BaseStream.Position = fi.Length - 0x0F; while (br.BaseStream.Position > headerSkip) { br.Read(checkByte, 0, checkByte.Length); if (checkByte[0] == 0x03) { loopEnd = br.BaseStream.Position + 0x0E - headerSkip; //if (channels > 1) //{ // loopEnd -= interleave; //} break; } else if (br.BaseStream.Position >= 0x11) { br.BaseStream.Position -= 0x11; } else { br.BaseStream.Position = headerSkip; } } // if loop end found but start not found, try alternate method if ((loopEnd >= 0) && (loopStart < 0)) { loopCheckBytesOffset = loopEnd + headerSkip - SONY_ADPCM_LOOP_HACK_BYTE_COUNT; possibleLoopBytes = ParseFile.ParseSimpleOffset( br.BaseStream, loopCheckBytesOffset, SONY_ADPCM_LOOP_HACK_BYTE_COUNT - 0x10); loopStart = ParseFile.GetNextOffset(br.BaseStream, 0, possibleLoopBytes, true); if ((loopStart > 0) && (loopStart < loopCheckBytesOffset)) { loopStart += SONY_ADPCM_LOOP_HACK_BYTE_COUNT - headerSkip; } } } if (loopStart >= 0) { pLoopStart = (loopStart / 16 / channels * 28).ToString(); ret = true; } if (loopEnd >= 0) { pLoopEnd = (loopEnd / 16 / channels * 28).ToString(); ret = true; } return(ret); }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractAdxStruct, DoWorkEventArgs e) { ExtractAdxStruct extractAdxStruct = (ExtractAdxStruct)pExtractAdxStruct; long offset = 0; uint copyrightOffset; byte[] copyrightBytes; uint totalHeaderSize; int encodingType; uint blockSize; uint bitDepth; uint channelCount; uint sampleRate; uint totalSamples; uint fileSize; int fileCount = 0; string outputPath = Path.Combine(Path.GetDirectoryName(pPath), "_cri_adx_ext"); string outputFileName; string outputFilePath; FileInfo fi = new FileInfo(pPath); using (FileStream fs = File.Open(pPath, FileMode.Open, FileAccess.Read)) { outputPath = Path.Combine(Path.GetDirectoryName(pPath), String.Format("{0}_ADXs", Path.GetFileNameWithoutExtension(pPath))); while ((offset = ParseFile.GetNextOffset(fs, offset, ADX_SIG_BYTES)) > -1) { if (!this.CancellationPending) { // get offset to copyright string copyrightOffset = (uint)ByteConversion.GetUInt16BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 2, 2)); copyrightBytes = ParseFile.ParseSimpleOffset(fs, offset + copyrightOffset - 2, CRI_COPYRIGHT_BYTES.Length); // check that copyright bytes are present if (ParseFile.CompareSegment(copyrightBytes, 0, CRI_COPYRIGHT_BYTES)) { // verify this is standard ADX encodingType = ParseFile.ParseSimpleOffset(fs, offset + 4, 1)[0]; if (encodingType != 3) { fileSize = 1; } else { // get other info blockSize = (uint)ParseFile.ParseSimpleOffset(fs, offset + 5, 1)[0]; bitDepth = (uint)ParseFile.ParseSimpleOffset(fs, offset + 6, 1)[0]; channelCount = (uint)ParseFile.ParseSimpleOffset(fs, offset + 7, 1)[0]; sampleRate = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 8, 4)); totalSamples = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, offset + 0xC, 4)); totalHeaderSize = copyrightOffset + 4; // calculate file size fileSize = (((totalSamples + 0x1F) / (bitDepth * 8)) * channelCount * blockSize) + totalHeaderSize + blockSize; // extract file outputFileName = String.Format("{0}_{1}.adx", Path.GetFileNameWithoutExtension(pPath), fileCount.ToString("X8")); outputFilePath = Path.Combine(outputPath, outputFileName); this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("{0} - offset: 0x{1} size: 0x{2}{3}", outputFileName, offset.ToString("X8"), fileSize.ToString("X8"), Environment.NewLine); ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); ParseFile.ExtractChunkToFile(fs, offset, (int)fileSize, outputFilePath, true, true); fileCount++; } offset += fileSize; } else { offset += 1; } } else { e.Cancel = true; return; } } } }
private void RenameFilesFromExternalList(ExternalListFileRenamerStruct inputValues) { string fileMask = null; string[] sourceFiles; int sourceFileCount; long listFileLength; long fileNameOffset; StringBuilder renameScript; StringBuilder undoScript; string sourceFile; byte[] destinationFileTerminator = new byte[0]; long destinationFileBytesSize = -1; byte[] destinationFileBytes; string destinationFile; string destinationFolder; long currentOffset; // verify directory exists and list file exists if (Directory.Exists(inputValues.SourceFolder) && File.Exists(inputValues.ListFileLocation)) { // set file mask fileMask = inputValues.SourceFileMask.Trim(); fileMask = String.IsNullOrEmpty(fileMask) ? "*.*" : fileMask; // get source file count sourceFiles = Directory.GetFiles(inputValues.SourceFolder, fileMask, SearchOption.TopDirectoryOnly); sourceFileCount = sourceFiles.GetLength(0); // verify some source files exist if (sourceFileCount == 0) { throw new Exception(String.Format("Source directory is empty.")); } else { // convert file name offset to long fileNameOffset = ByteConversion.GetLongValueFromString(inputValues.OffsetToFileNames); // open List File using (FileStream listFs = File.Open(inputValues.ListFileLocation, FileMode.Open, FileAccess.Read, FileShare.Read)) { listFileLength = listFs.Length; // verify offset exists within list file if (listFileLength < fileNameOffset) { throw new IOException(String.Format("File name offset is greater than the size of the list file.")); } else { renameScript = new StringBuilder(); undoScript = new StringBuilder(); // parse file name terminator, if included if (inputValues.FileNameHasTerminator) { try { destinationFileTerminator = ByteConversion.GetBytesFromHexString(inputValues.FileNameTerminator); } catch (Exception ex1) { throw new FormatException(String.Format("Unable to convert File Name Terminator Bytes to hex: '{0}'", ex1.Message), ex1); } } else // convert static filename size { try { destinationFileBytesSize = ByteConversion.GetLongValueFromString(inputValues.FileNameStaticSize); } catch (Exception ex2) { throw new FormatException(String.Format("Unable to convert File Name static size fo a number: '{0}'", ex2.Message), ex2); } } try { // rename files currentOffset = fileNameOffset; for (int i = 0; i < sourceFileCount; i++) { sourceFile = sourceFiles[i]; // get name for files with a terminator if (inputValues.FileNameHasTerminator) { destinationFileBytesSize = ParseFile.GetNextOffset(listFs, currentOffset, destinationFileTerminator) - currentOffset; } // read destination file name if (destinationFileBytesSize > 0) { destinationFileBytes = ParseFile.ParseSimpleOffset(listFs, currentOffset, (int)destinationFileBytesSize); destinationFile = this.getFileNameFromEncodedBytes(inputValues.FileNameEncoding, inputValues.FileNameCodePage, destinationFileBytes); currentOffset += destinationFileBytesSize + destinationFileTerminator.Length; } else { this.progressStruct.Clear(); this.progressStruct.FileName = sourceFile; this.progressStruct.GenericMessage = String.Format("Warning: End of List File reached when renaming <{0}>{1}", sourceFile, Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, progressStruct); break; } // rename file and build scripts destinationFile = Path.Combine(inputValues.SourceFolder, destinationFile).Trim(); if (inputValues.KeepOriginalFileExtension) { if (String.IsNullOrEmpty(Path.GetExtension(destinationFile))) { destinationFile += Path.GetExtension(sourceFile); } else { Path.ChangeExtension(destinationFile, Path.GetExtension(sourceFile)); } } if (sourceFile != destinationFile) { renameScript.AppendFormat("rename \"{0}\" \"{1}\" {2}", Path.GetFileName(sourceFile), Path.GetFileName(destinationFile), Environment.NewLine); undoScript.AppendFormat("rename \"{0}\" \"{1}\" {2}", Path.GetFileName(destinationFile), Path.GetFileName(sourceFile), Environment.NewLine); destinationFolder = Path.GetDirectoryName(destinationFile); if (!Directory.Exists(destinationFolder)) { Directory.CreateDirectory(destinationFolder); } File.Move(sourceFile, destinationFile); } // report progress this.progressStruct.Clear(); this.progressStruct.FileName = sourceFile; this.ReportProgress(((i + 1) * 100) / sourceFileCount, progressStruct); } } finally { if (renameScript.Length > 0) { // write to file. FileUtil.CreateFileFromString(Path.Combine(inputValues.SourceFolder, RENAME_SCRIPT_NAME), renameScript.ToString()); } if (undoScript.Length > 0) { // write to file. FileUtil.CreateFileFromString(Path.Combine(inputValues.SourceFolder, UNDO_RENAME_SCRIPT_NAME), undoScript.ToString()); } } } // if (listFileLength < fileNameOffset) } // using (FileStream listFs = File.Open(inputValues.ListFileLocation, FileMode.Open, FileAccess.Read, FileShare.Read)) } // if (sourceFileCount == 0) } else { throw new IOException(String.Format("Directory not found: <{0}>", inputValues.SourceFolder)); } // if (Directory.Exists(inputValues.SourceFolder)) }
protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pPspSeqDataFinderStruct, DoWorkEventArgs e) { PspSeqDataFinderStruct pspStruct = (PspSeqDataFinderStruct)pPspSeqDataFinderStruct; long offset; int phdNumber = 0; PphdStruct phdObject; ArrayList phdArrayList = new ArrayList(); string midName; int midNumber = 0; Psf.ProbableItemStruct midEntry; ArrayList midFiles = new ArrayList(); bool midNamingMessageDisplayed = false; Midi midiFile = new Midi(); Psf.ProbableItemStruct potentialPbd; Psf.ProbableItemStruct[] potentialPbdList; byte[] pbdRow = new byte[Psf.SONY_ADPCM_ROW_SIZE]; ArrayList emptyRowList = new ArrayList(); // display file name this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format("[{0}]{1}", pPath, Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); // open file using (FileStream fs = File.OpenRead(pPath)) { string destinationFolder = Path.Combine(Path.GetDirectoryName(pPath), Path.GetFileNameWithoutExtension(pPath)); // get PHD files #region PHD EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting PHD{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; while ((offset = ParseFile.GetNextOffset(fs, offset, PPHD_SIGNATURE)) > -1) { try { // get PPHD data phdObject = GetPphdData(fs, offset); phdObject.FileName = String.Format("{0}_{1}.PHD", Path.GetFileNameWithoutExtension(pPath), phdNumber++.ToString("X4")); // extract the file ParseFile.ExtractChunkToFile(fs, offset, (int)phdObject.length, Path.Combine(destinationFolder, phdObject.FileName), true, true); // add to array phdArrayList.Add(phdObject); } catch (Exception pphdEx) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" Error extracting PPHD at offset 0x{0}: {1}{2}", offset.ToString("X8"), pphdEx.Message, Environment.NewLine); ReportProgress(progress, this.progressStruct); } // increment offset offset += 1; } #endregion // get MID Files #region MID EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting MID{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); midEntry = new Psf.ProbableItemStruct(); offset = 0; // build file list while ((offset = ParseFile.GetNextOffset(fs, offset, Midi.ASCII_SIGNATURE_MTHD)) > -1) { midiFile.Initialize(fs, pPath, offset); midEntry.offset = midiFile.FileStartOffset; midEntry.length = (uint)midiFile.TotalFileLength; midFiles.Add(midEntry); offset += 1; } foreach (Psf.ProbableItemStruct mid in midFiles) { if (pspStruct.ReorderMidFiles) { if (phdArrayList.Count < midFiles.Count) { if (!midNamingMessageDisplayed) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format( "Warning, cannot reorder MID files, there are less PHD files than MID files.{0}", Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); midNamingMessageDisplayed = true; } midName = String.Format("{0}_{1}.MID", Path.GetFileNameWithoutExtension(pPath), midNumber++.ToString("X4")); } else { phdObject = (PphdStruct)phdArrayList[phdArrayList.Count - midFiles.Count + midNumber++]; midName = Path.ChangeExtension(phdObject.FileName, ".MID"); } } else { midName = String.Format("{0}_{1}.MID", Path.GetFileNameWithoutExtension(pPath), midNumber++.ToString("X4")); } ParseFile.ExtractChunkToFile(fs, mid.offset, (int)mid.length, Path.Combine(destinationFolder, midName), true, true); } #endregion // get PBD files #region PBD EXTRACT this.progressStruct.Clear(); this.progressStruct.GenericMessage = String.Format(" Extracting PBD...WARNING, THIS CAN TAKE A LONG TIME...{0}", Environment.NewLine); this.ReportProgress(Constants.ProgressMessageOnly, this.progressStruct); offset = 0; // build list of potential adpcm start indexes potentialPbd = new Psf.ProbableItemStruct(); // build list of potential adpcm start indexes while ((offset = ParseFile.GetNextOffset(fs, offset, Psf.VB_START_BYTES, pspStruct.UseZeroOffsetForPbd, 0x10L, 0x00L, true)) > -1) { try { pbdRow = ParseFile.ParseSimpleOffset(fs, offset, pbdRow.Length); if (Psf.IsPotentialAdpcm(fs, offset + 0x10, Psf.MIN_ADPCM_ROW_COUNT, false)) { potentialPbd.offset = offset; emptyRowList.Add(potentialPbd); } } catch (Exception pbdEx) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR finding BD for <{0}> at Offset 0x{1}: {2}{3}", pPath, offset.ToString("X8"), pbdEx.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } offset += 1; } potentialPbdList = (Psf.ProbableItemStruct[])emptyRowList.ToArray(typeof(Psf.ProbableItemStruct)); // set probable lengths for (int i = 0; i < potentialPbdList.Length; i++) { if (i > 0) { potentialPbdList[i - 1].length = (uint)(potentialPbdList[i].offset - potentialPbdList[i - 1].offset); } } // compare PHD sample sizes to potential adpcm sizes/indexes phdObject.startingOffset = 0; phdObject.length = 0; phdObject.pbdStartingOffset = 0; phdObject.pbdLength = 0; string pbdName; string newFileName; string[] dupeFileNames; for (int i = 0; i < phdArrayList.Count; i++) { phdObject = (PphdStruct)phdArrayList[i]; if (phdObject.vagLengths.Length < 1) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building PBD for <{0}>: {1} refers to a single VAG, cannot determine proper PBD. Skipping...{2}", pPath, phdObject.FileName, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } else { for (int j = 0; j < potentialPbdList.Length; j++) { // we have a potential match or are at the last item. if ((phdObject.vagLengths[0] <= potentialPbdList[j].length) || (potentialPbdList[j].length == 0)) { try { phdObject = PopulatePbdOffsetLength(fs, potentialPbdList, j, phdObject); if (phdObject.pbdLength > 0) { // check for other BD files that matched and rename accordingly dupeFileNames = Directory.GetFiles(destinationFolder, Path.GetFileNameWithoutExtension(phdObject.FileName) + "*.PBD"); if (dupeFileNames.Length >= 1) { pbdName = String.Format("{0}_{1}.PBD", Path.GetFileNameWithoutExtension(phdObject.FileName), (dupeFileNames.Length).ToString("X4")); if (dupeFileNames.Length == 1) { // rename existing newFileName = String.Format("{0}_{1}.PBD", Path.GetFileNameWithoutExtension(phdObject.FileName), (dupeFileNames.Length - 1).ToString("X4")); File.Move(dupeFileNames[0], Path.Combine(Path.GetDirectoryName(dupeFileNames[0]), newFileName)); } } else { pbdName = Path.ChangeExtension(phdObject.FileName, ".PBD"); } ParseFile.ExtractChunkToFile(fs, phdObject.pbdStartingOffset, phdObject.pbdLength, Path.Combine(destinationFolder, pbdName), true, true); } } catch (Exception ex) { this.progressStruct.Clear(); this.progressStruct.ErrorMessage = String.Format(" ERROR building BD for <{0}>: {1}{2}", pPath, ex.Message, Environment.NewLine); this.ReportProgress(this.progress, this.progressStruct); } } } } } #endregion } }