예제 #1
0
        protected override void DoFinalTasks(FileStream sourceFileStream, Dictionary <uint, FileStream> outputFiles, bool addHeader)
        {
            byte[] headerBytes;
            byte[] aa3HeaderBytes;
            uint   headerBlock;
            string sourceFile;

            foreach (uint streamId in outputFiles.Keys)
            {
                if (this.IsThisAnAudioBlock(BitConverter.GetBytes(streamId)) &&
                    outputFiles[streamId].Name.EndsWith(Atrac3AudioExtension))
                {
                    headerBytes = ParseFile.ParseSimpleOffset(outputFiles[streamId], 0, 0x8);

                    // remove all header chunks
                    string cleanedFile = FileUtil.RemoveAllChunksFromFile(outputFiles[streamId], headerBytes);

                    // close stream and rename file
                    sourceFile = outputFiles[streamId].Name;

                    outputFiles[streamId].Close();
                    outputFiles[streamId].Dispose();

                    File.Delete(sourceFile);
                    File.Move(cleanedFile, sourceFile);

                    // add header
                    if (addHeader)
                    {
                        Array.Reverse(headerBytes);
                        headerBlock = BitConverter.ToUInt32(headerBytes, 4);

                        string headeredFile = Path.ChangeExtension(sourceFile, Atrac3Plus.FileExtensionPsp);
                        aa3HeaderBytes = Atrac3Plus.GetAa3Header(headerBlock);
                        FileUtil.AddHeaderToFile(aa3HeaderBytes, sourceFile, headeredFile);

                        File.Delete(sourceFile);
                    }
                }
                //else if (this.IsThisAnAudioBlock(BitConverter.GetBytes(streamId)) &&
                //    outputFiles[streamId].Name.EndsWith(SubTitleExtension))
                //{
                //    this.ConvertSubtitles(streamId, outputFiles[streamId]);

                //}
            }
        }
예제 #2
0
        protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pXmaConverterStruct,
                                              DoWorkEventArgs e)
        {
            XmaConverterStruct taskStruct = (XmaConverterStruct)pXmaConverterStruct;
            string             workingFolder;
            string             workingFile;
            string             workingSourceFile;

            string consoleOutput = String.Empty;
            string consoleError  = String.Empty;

            uint riffFrequency;
            uint riffChannelCount;
            uint riffFileSize;

            string riffHeaderedFile;

            byte[] riffHeaderBytes;

            uint loopStart;
            uint loopLength;
            uint loopEnd;

            byte[] posBytes;

            //------------------
            // output file name
            //------------------
            this.ShowOutput(pPath, String.Format("[{0}]", Path.GetFileName(pPath)), false);

            //----------------------
            // build working folder
            //----------------------
            workingFolder = this.createWorkingFolder(pPath, taskStruct);

            //------------------------------------
            // copy source file to working folder
            //------------------------------------
            workingSourceFile = Path.Combine(workingFolder, Path.GetFileName(pPath));
            File.Copy(pPath, workingSourceFile, true);

            taskStruct.NumberOfStreams = 1;

            for (int i = 0; i < taskStruct.NumberOfStreams; i++)
            {
                // set working file
                workingFile = workingSourceFile;

                #region XMAPARSE
                //---------------------------
                // xma_parse.exe
                //---------------------------
                if (taskStruct.DoXmaParse)
                {
                    this.ShowOutput(pPath, "---- calling xma_parse.exe", false);

                    // call xma_parse and set output as working_file for next step
                    workingFile = this.callXmaParse(workingFolder, workingFile, taskStruct, out consoleOutput, out consoleError);

                    // show output
                    if (taskStruct.ShowExeOutput && !String.IsNullOrEmpty(consoleOutput))
                    {
                        this.ShowOutput(pPath, consoleOutput, false);
                    }

                    // clear errors if ignore is selected, but only if a file was created
                    if (taskStruct.XmaParseIgnoreErrors && (File.Exists(workingFile)))
                    {
                        consoleError = String.Empty;
                    }
                } //
                #endregion

                #region RIFF HEADER
                if ((taskStruct.DoRiffHeader) && (String.IsNullOrEmpty(consoleError)))
                {
                    //-----------------
                    // get RIFF header
                    //-----------------
                    this.ShowOutput(pPath, "---- adding RIFF header.", false);

                    // frequency
                    if (taskStruct.GetFrequencyFromRiffHeader)
                    {
                        riffFrequency = (uint)RiffUtil.GetFrequencyFromRiffHeader(workingSourceFile);
                    }
                    else if (taskStruct.GetFrequencyFromOffset)
                    {
                        using (FileStream fs = File.OpenRead(workingSourceFile))
                        {
                            riffFrequency = (uint)ParseFile.GetVaryingByteValueAtAbsoluteOffset(fs, taskStruct.RiffHeaderFrequencyOffsetInfo, true);
                        }
                    }
                    else
                    {
                        riffFrequency = (uint)ByteConversion.GetLongValueFromString(taskStruct.RiffFrequency);
                    }

                    // channels
                    if (taskStruct.GetChannelsFromRiffHeader)
                    {
                        riffChannelCount = RiffUtil.GetChannelsFromRiffHeader(workingSourceFile);
                    }
                    else if (taskStruct.GetChannelsFromOffset)
                    {
                        using (FileStream fs = File.OpenRead(workingSourceFile))
                        {
                            riffChannelCount = (uint)ParseFile.GetVaryingByteValueAtAbsoluteOffset(fs, taskStruct.RiffHeaderChannelOffsetInfo, true);

                            if (riffChannelCount > 2)
                            {
                                riffChannelCount = 2;
                            }
                        }
                    }
                    else
                    {
                        riffChannelCount = (uint)ByteConversion.GetLongValueFromString(taskStruct.RiffChannelCount);
                    }

                    riffFileSize = (uint)new FileInfo(workingFile).Length;

                    riffHeaderBytes = this.getRiffHeader(riffFrequency, riffChannelCount, riffFileSize);

                    //-------------------------
                    // add RIFF header to file
                    //-------------------------
                    riffHeaderedFile = Path.ChangeExtension(workingFile, RIFF_COPY_OUTPUT_EXTENSION);
                    FileUtil.AddHeaderToFile(riffHeaderBytes, workingFile, riffHeaderedFile);

                    // set working file for next
                    workingFile = riffHeaderedFile;
                }
                else if (!String.IsNullOrEmpty(consoleError))
                {
                    // dispay xma_parse.exe error
                    this.ShowOutput(pPath, consoleError, true);
                }
                #endregion

                #region POS CREATOR
                //-----------
                // POS Maker
                //-----------
                if ((taskStruct.DoPosMaker) && (String.IsNullOrEmpty(consoleError)))
                {
                    this.ShowOutput(pPath, "---- creating POS file", false);

                    // loop start
                    if (taskStruct.PosLoopStartIsStatic)
                    {
                        loopStart = (uint)ByteConversion.GetLongValueFromString(taskStruct.PosLoopStartStaticValue);
                    }
                    else
                    {
                        using (FileStream fs = File.OpenRead(workingSourceFile))
                        {
                            loopStart = (uint)ParseFile.GetVaryingByteValueAtAbsoluteOffset(fs, taskStruct.PosLoopStartOffsetInfo, true);

                            if (!String.IsNullOrEmpty(taskStruct.PosLoopStartOffsetInfo.CalculationString))
                            {
                                string calculationString =
                                    taskStruct.PosLoopStartOffsetInfo.CalculationString.Replace(CalculatingOffsetDescription.OFFSET_VARIABLE_STRING, loopStart.ToString());

                                loopStart = (uint)ByteConversion.GetLongValueFromString(MathUtil.Evaluate(calculationString));
                            }
                        }
                    }

                    // loop length
                    if (taskStruct.PosLoopEndIsStatic)
                    {
                        loopLength = (uint)ByteConversion.GetLongValueFromString(taskStruct.PosLoopEndStaticValue);
                    }
                    else
                    {
                        using (FileStream fs = File.OpenRead(workingSourceFile))
                        {
                            loopLength = (uint)ParseFile.GetVaryingByteValueAtAbsoluteOffset(fs, taskStruct.PosLoopEndOffsetInfo, true);

                            if (!String.IsNullOrEmpty(taskStruct.PosLoopEndOffsetInfo.CalculationString))
                            {
                                string calculationString =
                                    taskStruct.PosLoopEndOffsetInfo.CalculationString.Replace(CalculatingOffsetDescription.OFFSET_VARIABLE_STRING, loopLength.ToString());

                                loopLength = (uint)ByteConversion.GetLongValueFromString(MathUtil.Evaluate(calculationString));
                            }
                        }
                    }

                    if (loopLength > 0)
                    {
                        loopEnd = loopStart + loopLength;

                        // build .pos array and write to file
                        posBytes = new byte[8];
                        Array.Copy(BitConverter.GetBytes(loopStart), 0, posBytes, 0, 4);
                        Array.Copy(BitConverter.GetBytes(loopEnd), 0, posBytes, 4, 4);

                        using (FileStream fs = File.Open(Path.ChangeExtension(workingSourceFile, ".pos"), FileMode.Create, FileAccess.Write))
                        {
                            fs.Write(posBytes, 0, posBytes.Length);
                        }
                    }
                }
                #endregion

                #region TOWAV
                //-----------
                // ToWav.exe
                //-----------
                if ((taskStruct.DoToWav) && (String.IsNullOrEmpty(consoleError)))
                {
                    this.ShowOutput(pPath, "---- calling ToWav.exe", false);

                    // call ToWav.exe and set working file for next step (if ever needed)
                    workingFile = this.callToWav(workingFolder, workingFile, taskStruct, out consoleOutput, out consoleError);

                    // show output
                    if (taskStruct.ShowExeOutput && !String.IsNullOrEmpty(consoleOutput))
                    {
                        this.ShowOutput(pPath, consoleOutput, false);
                    }

                    // dispay ToWav.exe error
                    if (!String.IsNullOrEmpty(consoleError))
                    {
                        this.ShowOutput(pPath, consoleError, true);
                    }
                }
                #endregion

                #region XMAENCODE
                //---------------
                // XmaEncode.exe
                //---------------
                else if ((taskStruct.DoXmaEncode) && (String.IsNullOrEmpty(consoleError)))
                {
                    this.ShowOutput(pPath, "---- calling xmaencode.exe", false);

                    // call xmaencode.exe and set working file for next step (if ever needed)
                    workingFile = this.callXmaEncode(workingFolder, workingFile, taskStruct, out consoleOutput, out consoleError);

                    // show output
                    if (taskStruct.ShowExeOutput && !String.IsNullOrEmpty(consoleOutput))
                    {
                        this.ShowOutput(pPath, consoleOutput, false);
                    }

                    // dispay xmaencode.exe error
                    if (!String.IsNullOrEmpty(consoleError))
                    {
                        this.ShowOutput(pPath, consoleError, true);
                    }
                }
                #endregion
            } // for (int i = 0; i < taskStruct.NumberOfStreams; i++)


            //----------------------
            // clean working folder
            //----------------------
            this.cleanWorkingFolder(pPath, workingSourceFile, taskStruct);
        }
예제 #3
0
        protected virtual void DoFinalTasks(Dictionary <uint, FileStream> streamWriters,
                                            MpegStream.DemuxOptionsStruct demuxOptions)
        {
            string sourceFile;
            string headeredFile;

            int headerSize;

            byte[] headerBytes;
            byte[] frameOffsetBytes;

            uint previousFrameOffset;
            uint frameOffset;

            uint maxFrameSize;
            uint fileLength;

            int audioTrackIndex;

            uint frameStartLocation;

            byte[] dummyValues = new byte[4];

            foreach (uint key in streamWriters.Keys)
            {
                try
                {
                    if (demuxOptions.AddHeader)
                    {
                        //////////////////////
                        // Multi-Track Audio
                        //////////////////////
                        if (streamWriters[key].Name.EndsWith(BinkStream.DefaultFileExtensionAudioMulti))
                        {
                            //////////////////////////
                            // update original header
                            //////////////////////////
                            headerBytes = new byte[this.FullHeader.Length];
                            Array.Copy(this.FullHeader, headerBytes, this.FullHeader.Length);

                            // set frame start location
                            frameStartLocation = 0x2C + (this.AudioTrackCount * 0xC);

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                frameStartLocation += 4;
                            }

                            // set file size
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length - 8);

                            // set video size to minimum
                            Array.Copy(BitConverter.GetBytes((uint)1), 0, headerBytes, 0x14, 4);
                            Array.Copy(BitConverter.GetBytes((uint)1), 0, headerBytes, 0x18, 4);

                            // insert file length
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, 4, 4);

                            // insert frame offsets
                            previousFrameOffset = 0;
                            frameOffset         = 0;
                            maxFrameSize        = 0;

                            for (uint i = 0; i < this.FrameCount; i++)
                            {
                                // set previous offset
                                previousFrameOffset = frameOffset;
                                frameOffset         = this.NewFrameOffsetsAudio[0][i];

                                if (this.FrameOffsetList[i].IsKeyFrame)
                                {
                                    // add key frame bit
                                    frameOffsetBytes = BitConverter.GetBytes(frameOffset | 1);
                                }
                                else
                                {
                                    frameOffsetBytes = BitConverter.GetBytes(frameOffset);
                                }

                                // insert offset
                                Array.Copy(frameOffsetBytes, 0, headerBytes, (frameStartLocation + (i * 4)), 4);

                                // calculate max frame size
                                if ((frameOffset - previousFrameOffset) > maxFrameSize)
                                {
                                    maxFrameSize = frameOffset - previousFrameOffset;
                                }
                            }

                            // Add last frame offset (EOF)
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, (frameStartLocation + (this.FrameCount * 4)), 4);

                            // insert max frame size
                            if ((fileLength - frameOffset) > maxFrameSize)
                            {
                                maxFrameSize = fileLength - frameOffset;
                            }

                            Array.Copy(BitConverter.GetBytes(maxFrameSize), 0, headerBytes, 0xC, 4);

                            // append to file
                            sourceFile   = streamWriters[key].Name;
                            headeredFile = sourceFile + ".headered";

                            streamWriters[key].Close();
                            streamWriters[key].Dispose();

                            FileUtil.AddHeaderToFile(headerBytes, streamWriters[key].Name, headeredFile);
                            File.Delete(streamWriters[key].Name);
                            File.Move(headeredFile, streamWriters[key].Name);
                        }

                        //////////////////////
                        // Split Track Audio
                        //////////////////////
                        else if (streamWriters[key].Name.EndsWith(BinkStream.DefaultFileExtensionAudioSplit))
                        {
                            //////////////////////////
                            // update original header
                            //////////////////////////
                            headerBytes = new byte[this.FullHeader.Length];
                            Array.Copy(this.FullHeader, headerBytes, this.FullHeader.Length);

                            // set video size to minimum
                            Array.Copy(BitConverter.GetBytes((uint)1), 0, headerBytes, 0x14, 4);
                            Array.Copy(BitConverter.GetBytes((uint)1), 0, headerBytes, 0x18, 4);

                            // get track info
                            audioTrackIndex = this.getIndexForSplitAudioTrackFileName(streamWriters[key].Name);

                            // resize header since all audio info except this track will be removied
                            headerSize = (int)(0x2C + 0xC + ((this.FrameCount + 1) * 4));

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                headerSize += 4;
                            }

                            Array.Resize(ref headerBytes, headerSize);

                            // insert audio info for this track
                            headerBytes[0x28] = 1;
                            Array.Copy(this.FullHeader, 0x2C + (audioTrackIndex * 4), headerBytes, 0x2C, 4);

                            // only one audio track, audio track id must equal zero
                            if (this.BinkVersion == BinkType.Version01)
                            {
                                Array.Copy(this.FullHeader, 0x2C + (this.AudioTrackCount * 4) + (audioTrackIndex * 4), headerBytes, 0x30, 4);
                                Array.Copy(BitConverter.GetBytes((uint)0), 0, headerBytes, 0x34, 4);
                            }
                            else if (this.BinkVersion == BinkType.Version02)
                            {
                                Array.Copy(this.FullHeader, 0x30 + (audioTrackIndex * 4), headerBytes, 0x30, 4);
                                Array.Copy(this.FullHeader, 0x30 + (this.AudioTrackCount * 4) + (audioTrackIndex * 4), headerBytes, 0x34, 4);
                                Array.Copy(BitConverter.GetBytes((uint)0), 0, headerBytes, 0x38, 4);
                            }
                            else
                            {
                                throw new FormatException("Unsupported Bink type for split audio streams.");
                            }

                            // set file size
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length - 8);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, 4, 4);

                            // insert frame offsets
                            previousFrameOffset = 0;
                            frameOffset         = 0;
                            maxFrameSize        = 0;

                            frameStartLocation = 0x2C + 0xC;

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                frameStartLocation += 4;
                            }

                            for (uint i = 0; i < this.FrameCount; i++)
                            {
                                // set previous offset
                                previousFrameOffset = frameOffset;
                                frameOffset         = this.NewFrameOffsetsAudio[audioTrackIndex][i];

                                if (this.FrameOffsetList[i].IsKeyFrame)
                                {
                                    // add key frame bit
                                    frameOffsetBytes = BitConverter.GetBytes(this.NewFrameOffsetsAudio[audioTrackIndex][i] | 1);
                                }
                                else
                                {
                                    frameOffsetBytes = BitConverter.GetBytes(this.NewFrameOffsetsAudio[audioTrackIndex][i]);
                                }

                                // insert offset
                                Array.Copy(frameOffsetBytes, 0, headerBytes, (frameStartLocation + (i * 4)), 4);

                                // calculate max frame size
                                if ((frameOffset - previousFrameOffset) > maxFrameSize)
                                {
                                    maxFrameSize = frameOffset - previousFrameOffset;
                                }
                            }

                            // Add last frame offset (EOF)
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, (frameStartLocation + (this.FrameCount * 4)), 4);

                            // insert max frame size
                            if ((fileLength - frameOffset) > maxFrameSize)
                            {
                                maxFrameSize = fileLength - frameOffset;
                            }

                            Array.Copy(BitConverter.GetBytes(maxFrameSize), 0, headerBytes, 0xC, 4);

                            // append to file
                            sourceFile   = streamWriters[key].Name;
                            headeredFile = sourceFile + ".headered";

                            streamWriters[key].Close();
                            streamWriters[key].Dispose();

                            FileUtil.AddHeaderToFile(headerBytes, streamWriters[key].Name, headeredFile);
                            File.Delete(streamWriters[key].Name);
                            File.Move(headeredFile, streamWriters[key].Name);
                        }

                        //////////////////////
                        // Video
                        //////////////////////
                        else if (streamWriters[key].Name.EndsWith(BinkStream.DefaultFileExtensionVideo))
                        {
                            //////////////////////////
                            // update original header
                            //////////////////////////
                            headerBytes = new byte[this.FullHeader.Length];
                            Array.Copy(this.FullHeader, headerBytes, this.FullHeader.Length);

                            // resize header since audio info will be removied
                            headerSize = (int)(0x2C + ((this.FrameCount + 1) * 4));

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                headerSize += 4;
                            }

                            Array.Resize(ref headerBytes, headerSize);

                            // set file size
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length - 8);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, 4, 4);

                            // set audio track count to zero
                            headerBytes[0x28] = 0;

                            // insert frame offsets
                            previousFrameOffset = 0;
                            frameOffset         = 0;
                            maxFrameSize        = 0;

                            frameStartLocation = 0x2C;

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                frameStartLocation += 4;
                            }

                            for (uint i = 0; i < this.FrameCount; i++)
                            {
                                // set previous offset
                                previousFrameOffset = frameOffset;
                                frameOffset         = this.NewFrameOffsetsVideo[i];

                                if (this.FrameOffsetList[i].IsKeyFrame)
                                {
                                    // add key frame bit
                                    frameOffsetBytes = BitConverter.GetBytes(this.NewFrameOffsetsVideo[i] | 1);
                                }
                                else
                                {
                                    frameOffsetBytes = BitConverter.GetBytes(this.NewFrameOffsetsVideo[i]);
                                }

                                // insert frame offset
                                Array.Copy(frameOffsetBytes, 0, headerBytes, (frameStartLocation + (i * 4)), 4);

                                // calculate max frame size
                                if ((frameOffset - previousFrameOffset) > maxFrameSize)
                                {
                                    maxFrameSize = frameOffset - previousFrameOffset;
                                }
                            }

                            // Add last frame offset (EOF)
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, (frameStartLocation + (this.FrameCount * 4)), 4);

                            // insert max frame size
                            if ((fileLength - frameOffset) > maxFrameSize)
                            {
                                maxFrameSize = fileLength - frameOffset;
                            }

                            Array.Copy(BitConverter.GetBytes(maxFrameSize), 0, headerBytes, 0xC, 4);

                            // append to file
                            sourceFile   = streamWriters[key].Name;
                            headeredFile = sourceFile + ".headered";

                            streamWriters[key].Close();
                            streamWriters[key].Dispose();

                            FileUtil.AddHeaderToFile(headerBytes, streamWriters[key].Name, headeredFile);
                            File.Delete(streamWriters[key].Name);
                            File.Move(headeredFile, streamWriters[key].Name);
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (streamWriters[key] != null)
                    {
                        throw new Exception(String.Format("Exception building header for file: {0}{1}{2}", streamWriters[key].Name, ex.Message, Environment.NewLine));
                    }
                    else
                    {
                        throw new Exception(String.Format("Exception building header for file: {0}{1}{2}", "UNKNOWN", ex.Message, Environment.NewLine));
                    }
                }
                finally
                {
                    // close streams if open
                    if (streamWriters[key] != null &&
                        streamWriters[key].CanRead)
                    {
                        streamWriters[key].Close();
                        streamWriters[key].Dispose();
                    }
                }
            }
        }
예제 #4
0
        protected override void DoFinalTasks(FileStream sourceFileStream, Dictionary <uint, FileStream> outputFiles, bool addHeader)
        {
            byte[] headerBytes;
            byte[] aa3HeaderBytes;
            uint   headerBlock;
            string sourceFile;

            long streamInfoOffset;
            byte streamIdByte;
            byte streamIdCheckByte;
            byte channelCount;
            GenhCreationStruct gcStruct;
            string             genhFile;

            foreach (uint streamId in outputFiles.Keys)
            {
                if (this.IsThisAnAudioBlock(BitConverter.GetBytes(streamId)))
                {
                    if (outputFiles[streamId].Name.EndsWith(Atrac3AudioExtension))
                    {
                        headerBytes = ParseFile.ParseSimpleOffset(outputFiles[streamId], 0, 0x8);

                        // remove all header chunks
                        string cleanedFile = FileUtil.RemoveAllChunksFromFile(outputFiles[streamId], headerBytes);

                        // close stream and rename file
                        sourceFile = outputFiles[streamId].Name;

                        outputFiles[streamId].Close();
                        outputFiles[streamId].Dispose();

                        File.Delete(sourceFile);
                        File.Move(cleanedFile, sourceFile);

                        // add header
                        if (addHeader)
                        {
                            Array.Reverse(headerBytes);
                            headerBlock = BitConverter.ToUInt32(headerBytes, 4);

                            string headeredFile = Path.ChangeExtension(sourceFile, Atrac3Plus.FileExtension);
                            aa3HeaderBytes = Atrac3Plus.GetAa3Header(headerBlock);
                            FileUtil.AddHeaderToFile(aa3HeaderBytes, sourceFile, headeredFile);

                            File.Delete(sourceFile);
                        }
                    }
                    else if (addHeader &&
                             outputFiles[streamId].Name.EndsWith(LpcmAudioExtension))
                    {
                        // get this block's stream id
                        streamIdByte = BitConverter.GetBytes(streamId)[0];

                        // get location of first audio stream info block
                        streamInfoOffset = ParseFile.GetNextOffset(sourceFileStream, 0, PamAudioStreamInfoStartBytes);

                        // find matching info block
                        while ((streamInfoOffset > -1))
                        {
                            streamIdCheckByte = ParseFile.ParseSimpleOffset(sourceFileStream, streamInfoOffset + 0x4, 1)[0];

                            if (streamIdCheckByte == streamIdByte)
                            {
                                // get channel count
                                channelCount = ParseFile.ParseSimpleOffset(sourceFileStream, streamInfoOffset + 0x11, 1)[0];

                                // close stream and build GENH file
                                sourceFile = outputFiles[streamId].Name;

                                outputFiles[streamId].Close();
                                outputFiles[streamId].Dispose();

                                gcStruct            = new GenhCreationStruct();
                                gcStruct.Format     = "0x03";
                                gcStruct.HeaderSkip = "0";
                                gcStruct.Interleave = "0x2";
                                gcStruct.Channels   = channelCount.ToString();
                                gcStruct.Frequency  = "48000";
                                gcStruct.NoLoops    = true;

                                genhFile = GenhUtil.CreateGenhFile(sourceFile, gcStruct);

                                // delete original file
                                if (!String.IsNullOrEmpty(genhFile))
                                {
                                    File.Delete(sourceFile);
                                }

                                break;
                            }

                            streamInfoOffset = ParseFile.GetNextOffset(sourceFileStream, streamInfoOffset + 1, PamAudioStreamInfoStartBytes);
                        }
                    }
                }
            }
        }