public void Scan(TSAudioStream stream, TSStreamBuffer buffer, ref string tag, long?bitrate) { if (stream.IsInitialized && (stream.StreamType == TSStreamType.DTS_HD_SECONDARY_AUDIO || stream.CoreStream != null && stream.CoreStream.IsInitialized)) { return; } var syncFound = false; uint sync = 0; for (var i = 0; i < buffer.Length; i++) { sync = (sync << 8) + buffer.ReadByte(); if (sync == 0x64582025) { syncFound = true; break; } } if (!syncFound) { tag = "CORE"; if (stream.CoreStream == null) { stream.CoreStream = new TSAudioStream { StreamType = TSStreamType.DTS_AUDIO } } ; if (!stream.CoreStream.IsInitialized) { buffer.BeginRead(); (new TSCodecDTS()).Scan(stream.CoreStream, buffer, ref tag, bitrate); } return; } tag = "HD"; buffer.BSSkipBits(8); var nuSubStreamIndex = buffer.ReadBits4(2); var bBlownUpHeader = buffer.ReadBool(); buffer.BSSkipBits(bBlownUpHeader ? 32 : 24); var nuNumAssets = 1; var bStaticFieldsPresent = buffer.ReadBool(); if (bStaticFieldsPresent) { buffer.BSSkipBits(5); if (buffer.ReadBool()) { buffer.BSSkipBits(36); } var nuNumAudioPresent = buffer.ReadBits2(3) + 1; nuNumAssets = buffer.ReadBits2(3) + 1; var nuActiveExSsMask = new uint[nuNumAudioPresent]; for (var i = 0; i < nuNumAudioPresent; i++) { nuActiveExSsMask[i] = buffer.ReadBits4((int)(nuSubStreamIndex + 1)); //? } for (var i = 0; i < nuNumAudioPresent; i++) { for (var j = 0; j < nuSubStreamIndex + 1; j++) { if ((j + 1) % 2 == 1) { buffer.BSSkipBits(8); } } } if (buffer.ReadBool()) { buffer.BSSkipBits(2); var nuBits4MixOutMask = buffer.ReadBits2(2) * 4 + 4; var nuNumMixOutConfigs = buffer.ReadBits2(2) + 1; var nuMixOutChMask = new uint[nuNumMixOutConfigs]; for (var i = 0; i < nuNumMixOutConfigs; i++) { nuMixOutChMask[i] = buffer.ReadBits4(nuBits4MixOutMask); } } } var assetSizes = new uint[nuNumAssets]; for (var i = 0; i < nuNumAssets; i++) { if (bBlownUpHeader) { assetSizes[i] = buffer.ReadBits4(20) + 1; } else { assetSizes[i] = buffer.ReadBits4(16) + 1; } } for (var i = 0; i < nuNumAssets; i++) { buffer.BSSkipBits(12); if (bStaticFieldsPresent) { if (buffer.ReadBool()) { buffer.BSSkipBits(4); } if (buffer.ReadBool()) { buffer.BSSkipBits(24); } if (buffer.ReadBool()) { var nuInfoTextByteSize = buffer.ReadBits2(10) + 1; var infoText = new ushort[nuInfoTextByteSize]; for (var j = 0; j < nuInfoTextByteSize; j++) { infoText[j] = buffer.ReadBits2(8); } } var nuBitResolution = buffer.ReadBits2(5) + 1; int nuMaxSampleRate = buffer.ReadBits2(4); var nuTotalNumChs = buffer.ReadBits2(8) + 1; uint nuSpkrActivityMask = 0; if (buffer.ReadBool()) { if (nuTotalNumChs > 2) { buffer.BSSkipBits(1); } if (nuTotalNumChs > 6) { buffer.BSSkipBits(1); } if (buffer.ReadBool()) { int nuNumBits4SAMask = buffer.ReadBits2(2); nuNumBits4SAMask = nuNumBits4SAMask * 4 + 4; nuSpkrActivityMask = buffer.ReadBits4(nuNumBits4SAMask); } // TODO... } stream.SampleRate = SampleRates[nuMaxSampleRate]; stream.BitDepth = nuBitResolution; stream.LFE = 0; if ((nuSpkrActivityMask & 0x8) == 0x8) { ++stream.LFE; } if ((nuSpkrActivityMask & 0x1000) == 0x1000) { ++stream.LFE; } stream.ChannelCount = nuTotalNumChs - stream.LFE; } if (nuNumAssets > 1) { // TODO... break; } } uint temp2 = 0; while (buffer.Position < buffer.Length) { temp2 = (temp2 << 8) + buffer.ReadByte(); switch (temp2) { case 0x41A29547: // XLL Extended data case 0x655E315E: // XBR Extended data case 0x0A801921: // XSA Extended data case 0x1D95F262: // X96k case 0x47004A03: // XXch case 0x5A5A5A5A: // Xch var temp3 = 0; for (var i = (int)buffer.Position; i < buffer.Length; i++) { temp3 = (temp3 << 8) + buffer.ReadByte(); if (temp3 == 0x02000850) //DTS:X Pattern { stream.HasExtensions = true; break; } } break; } if (stream.HasExtensions) { break; } } // TODO if (stream.CoreStream != null) { var coreStream = stream.CoreStream; if (coreStream.AudioMode == TSAudioMode.Extended && stream.ChannelCount == 5) { stream.AudioMode = TSAudioMode.Extended; } /* * if (coreStream.DialNorm != 0) * { * stream.DialNorm = coreStream.DialNorm; * } */ } if (stream.StreamType == TSStreamType.DTS_HD_MASTER_AUDIO) { stream.IsVBR = true; stream.IsInitialized = true; } else if (bitrate.HasValue && bitrate > 0) { stream.IsVBR = false; stream.BitRate = bitrate.Value; if (stream.CoreStream != null) { stream.BitRate += stream.CoreStream.BitRate; stream.IsInitialized = true; } stream.IsInitialized = stream.BitRate > 0; } } }
public void Scan(TSAudioStream stream, TSStreamBuffer buffer, ref string tag, long?bitrate) { if (stream.IsInitialized) { return; } var syncFound = false; uint sync = 0; for (var i = 0; i < buffer.Length; i++) { sync = (sync << 8) + buffer.ReadByte(); if (sync == 0x7FFE8001) { syncFound = true; break; } } if (!syncFound) { return; } buffer.BSSkipBits(6); var crcPresent = buffer.ReadBits4(1); buffer.BSSkipBits(7); var frameSize = buffer.ReadBits4(14); if (frameSize < 95) { return; } buffer.BSSkipBits(6); var sampleRate = buffer.ReadBits4(4); if (sampleRate >= DcaSampleRates.Length) { return; } var bitRate = buffer.ReadBits4(5); if (bitRate >= DcaBitRates.Length) { return; } buffer.BSSkipBits(8); var extCoding = buffer.ReadBits4(1); buffer.BSSkipBits(1); var lfe = buffer.ReadBits4(2); buffer.BSSkipBits(1); if (crcPresent == 1) { buffer.BSSkipBits(16); } buffer.BSSkipBits(7); var sourcePcmRes = buffer.ReadBits4(3); buffer.BSSkipBits(2); var dialogNorm = buffer.ReadBits4(4); if (sourcePcmRes >= DcaBitsPerSample.Length) { return; } buffer.BSSkipBits(4); var totalChannels = buffer.ReadBits4(3) + 1 + extCoding; stream.SampleRate = DcaSampleRates[sampleRate]; stream.ChannelCount = (int)totalChannels; stream.LFE = lfe > 0 ? 1 : 0; stream.BitDepth = DcaBitsPerSample[sourcePcmRes]; stream.DialNorm = (int)-dialogNorm; if ((sourcePcmRes & 0x1) == 0x1) { stream.AudioMode = TSAudioMode.Extended; } stream.BitRate = (uint)DcaBitRates[bitRate]; switch (stream.BitRate) { case 1: if (bitrate != null && bitrate > 0) { stream.BitRate = bitrate.Value; stream.IsVBR = false; stream.IsInitialized = true; } else { stream.BitRate = 0; } break; case 2: case 3: stream.IsVBR = true; stream.IsInitialized = true; break; default: stream.IsVBR = false; stream.IsInitialized = true; break; } }