예제 #1
0
        private static void FixHeaderAndCloseWriter(FileStream pFs, ExtractXaStruct pExtractXaStruct,
                                                    bool nonSilentBlockFound)
        {
            string filename = pFs.Name;

            if (pExtractXaStruct.AddRiffHeader)
            {
                UInt32 xaFileSize = (UInt32)pFs.Length;

                // add file size
                pFs.Position = Cdxa.FILESIZE_OFFSET;
                pFs.Write(BitConverter.GetBytes(xaFileSize - 8), 0, 4);

                // add data size
                pFs.Position = Cdxa.DATA_LENGTH_OFFSET;
                pFs.Write(BitConverter.GetBytes((uint)(xaFileSize - Cdxa.XA_RIFF_HEADER.Length)), 0, 4);
            }

            pFs.Close();
            pFs.Dispose();

            if (!nonSilentBlockFound)
            {
                File.Delete(filename);
            }
        }
예제 #2
0
        private static string GetOutputFileName(ExtractXaStruct pExtractXaStruct, byte[] pTrackId)
        {
            string outputDirectory = Path.Combine(Path.GetDirectoryName(pExtractXaStruct.Path),
                                                  Path.GetFileNameWithoutExtension(pExtractXaStruct.Path));
            string outputFileName = Path.GetFileNameWithoutExtension(pExtractXaStruct.Path) + "_" + ParseFile.ByteArrayToString(pTrackId) + Cdxa.XA_FILE_EXTENSION;

            int fileCount = Directory.GetFiles(outputDirectory, String.Format("{0}*", Path.GetFileNameWithoutExtension(outputFileName)), SearchOption.TopDirectoryOnly).Length;

            outputFileName = String.Format("{0}_{1}{2}", Path.GetFileNameWithoutExtension(outputFileName), fileCount.ToString("X4"), Cdxa.XA_FILE_EXTENSION);

            //if (outputFileName.Equals("BGM2_01016401_0005.xa"))
            //{
            //    int x = 1;
            //}

            string ret = Path.Combine(outputDirectory, outputFileName);

            return(ret);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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;
                    }
                }
            }
        }