private FlacFrame(Stream stream, FlacMetadataStreamInfo streamInfo) { if (stream == null) throw new ArgumentNullException("stream"); if (stream.CanRead == false) throw new ArgumentException("Stream is not readable"); _stream = stream; _streamInfo = streamInfo; }
internal unsafe FlacFrameHeader(ref byte* buffer, FlacMetadataStreamInfo streamInfo, bool doCrc, bool logError) { printErrors = logError; //optimized for prescan DoCRC = doCrc; StreamPosition = -1; HasError = !ParseHeader(ref buffer, streamInfo); }
/// <param name="streamInfo">Can be null</param> public FlacFrameHeader(Stream stream, FlacMetadataStreamInfo streamInfo, bool doCrc) { if (stream == null) throw new ArgumentNullException("stream"); if (stream.CanRead == false) throw new ArgumentException("stream is not readable"); //streamInfo can be null DoCRC = doCrc; StreamPosition = stream.Position; HasError = !ParseHeader(stream, streamInfo); }
public void ScanStream(FlacMetadataStreamInfo streamInfo, FlacPreScanMode mode) { long saveOffset = _stream.Position; StartScan(streamInfo, mode); _stream.Position = saveOffset; long totalLength = 0, totalsamples = 0; foreach (var frame in Frames) { totalLength += frame.Header.BlockSize * frame.Header.BitsPerSample * frame.Header.Channels; totalsamples += frame.Header.BlockSize; } TotalLength = totalLength; TotalSamples = totalsamples; Debug.WriteLineIf(TotalSamples == streamInfo.TotalSamples, "Flac prescan successful. Calculated total_samples value matching the streaminfo-metadata."); }
public FlacFile(Stream stream, FlacPreScanMethodMode? scanFlag, Action<FlacPreScanFinishedEventArgs> onscanFinished) { if (stream == null) throw new ArgumentNullException(); if (!stream.CanRead) throw new ArgumentException("Stream is not readable.", "stream"); _stream = stream; //skip ID3v2 Tags.ID3.ID3v2.SkipTag(stream); int read = 0; //read fLaC sync byte[] beginSync = new byte[4]; read = stream.Read(beginSync, 0, beginSync.Length); if (read < beginSync.Length) throw new EndOfStreamException("Can not read \"fLaC\" sync."); if (beginSync[0] == 0x66 && beginSync[1] == 0x4C && beginSync[2] == 0x61 && beginSync[3] == 0x43) { //read metadata var metadata = FlacMetadata.AllDataFromStream(stream); Metadata = metadata; if (metadata == null || metadata.Count <= 0) { throw new FlacException("No Metadata found.", FlacLayer.Metadata); } FlacMetadataStreamInfo streamInfo = metadata.Where(x => x.MetaDataType == FlacMetaDataType.StreamInfo).First() as FlacMetadataStreamInfo; if (streamInfo == null) new FlacException("No StreamInfo-Metadata found.", FlacLayer.Metadata); _streamInfo = streamInfo; _waveFormat = new WaveFormat(streamInfo.SampleRate, (short)streamInfo.BitsPerSample, (short)streamInfo.Channels, AudioEncoding.Pcm); Debug.WriteLine("Flac StreamInfo found -> WaveFormat: " + _waveFormat.ToString()); Debug.WriteLine("Flac-File-Metadata read."); } else { throw new FlacException("Invalid Flac-File. \"fLaC\" Sync not found.", FlacLayer.Top); } //prescan stream if (scanFlag != null) { FlacPreScan scan = new FlacPreScan(stream); scan.ScanFinished += (s, e) => { if (onscanFinished != null) onscanFinished(e); }; scan.ScanStream(_streamInfo, (FlacPreScanMethodMode)scanFlag); _scan = scan; } }
/// <summary> /// Initializes a new instance of the <see cref="FlacFrameHeader"/> class. /// </summary> /// <param name="buffer">The raw byte-data which contains the <see cref="FlacFrameHeader"/>.</param> /// <param name="streamInfo">The stream-info-metadata-block of the flac stream which provides some basic information about the flac framestream. Can be set to null.</param> /// <param name="doCrc">A value which indicates whether the crc8 checksum of the <see cref="FlacFrameHeader"/> should be calculated.</param> public unsafe FlacFrameHeader(ref byte *buffer, FlacMetadataStreamInfo streamInfo, bool doCrc) : this(ref buffer, streamInfo, doCrc, true) { }
/// <summary> /// Initializes a new instance of the <see cref="FlacFile" /> class. /// </summary> /// <param name="stream">Stream which contains flac data which should be decoded.</param> /// <param name="scanFlag">Scan mode which defines how to scan the flac data for frames.</param> /// <param name="onscanFinished"> /// Callback which gets called when the pre scan processes finished. Should be used if the /// <paramref name="scanFlag" /> argument is set the <see cref="FlacPreScanMode.Async" />. /// </param> public FlacFile(Stream stream, FlacPreScanMode scanFlag, Action <FlacPreScanFinishedEventArgs> onscanFinished) { if (stream == null) { throw new ArgumentNullException(); } if (!stream.CanRead) { throw new ArgumentException("Stream is not readable.", "stream"); } _stream = stream; _closeStream = true; //skip ID3v2 while (ID3v2.SkipTag(stream)) { } //read fLaC sync var beginSync = new byte[4]; int read = stream.Read(beginSync, 0, beginSync.Length); if (read < beginSync.Length) { throw new EndOfStreamException("Can not read \"fLaC\" sync."); } if (beginSync[0] == 0x66 && beginSync[1] == 0x4C && //Check for 'fLaC' signature beginSync[2] == 0x61 && beginSync[3] == 0x43) { //read metadata List <FlacMetadata> metadata = FlacMetadata.ReadAllMetadataFromStream(stream).ToList(); Metadata = metadata.AsReadOnly(); if (metadata.Count <= 0) { throw new FlacException("No Metadata found.", FlacLayer.Metadata); } var streamInfo = metadata.First(x => x.MetaDataType == FlacMetaDataType.StreamInfo) as FlacMetadataStreamInfo; if (streamInfo == null) { throw new FlacException("No StreamInfo-Metadata found.", FlacLayer.Metadata); } _streamInfo = streamInfo; _waveFormat = CreateWaveFormat(streamInfo); Debug.WriteLine("Flac StreamInfo found -> WaveFormat: " + _waveFormat); Debug.WriteLine("Flac-File-Metadata read."); } else { throw new FlacException("Invalid Flac-File. \"fLaC\" Sync not found.", FlacLayer.OutSideOfFrame); } //prescan stream if (scanFlag != FlacPreScanMode.None) { var scan = new FlacPreScan(stream); scan.ScanFinished += (s, e) => { if (onscanFinished != null) { onscanFinished(e); } }; scan.ScanStream(_streamInfo, scanFlag); _scan = scan; } }
private WaveFormat CreateWaveFormat(FlacMetadataStreamInfo streamInfo) { if (streamInfo.Channels > 2 && streamInfo.Channels <= 8) { ChannelMask channelMask; switch (streamInfo.Channels) { case 3: //2.1 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight | ChannelMask.SpeakerFrontCenter; break; case 4: //quadraphonic channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight | ChannelMask.SpeakerBackLeft | ChannelMask.SpeakerBackRight; break; case 5: //5.0 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight | ChannelMask.SpeakerFrontCenter | ChannelMask.SpeakerSideLeft | ChannelMask.SpeakerSideRight; break; case 6: //5.1 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight | ChannelMask.SpeakerFrontCenter | ChannelMask.SpeakerLowFrequency | ChannelMask.SpeakerSideLeft | ChannelMask.SpeakerSideRight; break; case 7: //6.1 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight | ChannelMask.SpeakerFrontCenter | ChannelMask.SpeakerLowFrequency | ChannelMask.SpeakerSideLeft | ChannelMask.SpeakerSideRight | ChannelMask.SpeakerBackCenter; break; case 8: //7.1 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight | ChannelMask.SpeakerFrontCenter | ChannelMask.SpeakerLowFrequency | ChannelMask.SpeakerBackLeft | ChannelMask.SpeakerBackRight | ChannelMask.SpeakerSideLeft | ChannelMask.SpeakerSideRight; break; default: throw new Exception("Invalid number of channels. This error should not occur."); } return new WaveFormatExtensible(streamInfo.SampleRate, streamInfo.BitsPerSample, streamInfo.Channels, AudioSubTypes.Pcm, channelMask); } return new WaveFormat(streamInfo.SampleRate, streamInfo.BitsPerSample, streamInfo.Channels, AudioEncoding.Pcm); }
private unsafe bool IsFrame(ref byte* buffer, FlacMetadataStreamInfo streamInfo, FlacFrameHeader baseHeader, out FlacFrameHeader header) { header = new FlacFrameHeader(ref buffer, streamInfo, true, false); return !header.HasError; }
protected virtual List<FlacFrameInformation> RunScan(FlacMetadataStreamInfo streamInfo) { #if DEBUG Stopwatch watch = new Stopwatch(); watch.Start(); #endif var result = ScanThisShit(streamInfo); #if DEBUG watch.Stop(); Debug.WriteLine(String.Format("FlacPreScan finished: {0} Bytes processed in {1} ms.", _stream.Length.ToString(), watch.ElapsedMilliseconds.ToString())); #endif RaiseScanFinished(result); return result; }
public static unsafe FlacMetadata FromStream(Stream stream) { bool lastBlock = false; FlacMetaDataType type = FlacMetaDataType.Undef; int length = 0; byte[] b = new byte[4]; if (stream.Read(b, 0, 4) <= 0) throw new FlacException(new EndOfStreamException("Could not read metadata"), FlacLayer.Metadata); fixed (byte* headerBytes = b) { FlacBitReader bitReader = new FlacBitReader(headerBytes, 0); lastBlock = bitReader.ReadBits(1) == 1; type = (FlacMetaDataType)bitReader.ReadBits(7); length = (int)bitReader.ReadBits(24); ////1000 0000 //if (((b[0] & 0x80) >> 7) == 1) // lastBlock = true; //type = (FlacMetaDataType)(b[0] & 0x7F); //int length = (b[1] + (b[2] << 8) + (b[3] << 16)); } FlacMetadata data; long streamStartPosition = stream.Position; if ((int)type < 0 || (int)type > 6) return null; else { switch (type) { case FlacMetaDataType.StreamInfo: data = new FlacMetadataStreamInfo(stream, length, lastBlock); break; case FlacMetaDataType.Seektable: data = new FlacMetadataSeekTable(stream, length, lastBlock); break; default: data = new FlacMetadata(type, lastBlock, length); break; } } stream.Seek(length - (stream.Position - streamStartPosition), SeekOrigin.Current); return data; }
private unsafe bool ParseHeader(ref byte* headerBuffer, FlacMetadataStreamInfo streamInfo) { const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)"; int val; if (headerBuffer[0] == 0xFF && headerBuffer[1] >> 1 == 0x7C) //sync bits { if ((headerBuffer[1] & 0x02) != 0) { Error("Invalid FlacFrame. Reservedbit_0 is 1", loggerLocation); return false; } byte* __headerbufferPtr = headerBuffer; FlacBitReader reader = new FlacBitReader(__headerbufferPtr, 0); #region blocksize //blocksize val = headerBuffer[2] >> 4; int blocksize = -1; if (val == 0) { Error("Invalid Blocksize value: 0", loggerLocation); return false; } if (val == 1) blocksize = 192; else if (val >= 2 && val <= 5) blocksize = 576 << (val - 2); else if (val == 6 || val == 7) _blocksizeHint = val; else if (val >= 8 && val <= 15) blocksize = 256 << (val - 8); else { Error("Invalid Blocksize value: " + val, loggerLocation); return false; } BlockSize = blocksize; #endregion blocksize #region samplerate //samplerate val = headerBuffer[2] & 0x0F; int sampleRate = -1; if (val == 0) { if (streamInfo != null) sampleRate = streamInfo.SampleRate; else { Error("Missing Samplerate. Samplerate Index = 0 && streamInfoMetaData == null.", loggerLocation); return false; } } else if (val >= 1 && val <= 11) sampleRate = FlacConstant.SampleRateTable[val]; else if (val >= 12 && val <= 14) _sampleRateHint = val; else { Error("Invalid SampleRate value: " + val, loggerLocation); return false; } SampleRate = sampleRate; #endregion samplerate #region channels val = headerBuffer[3] >> 4; //cc: unsigned int channels; if ((val & 8) != 0) { channels = 2; if ((val & 7) > 2 || (val & 7) < 0) { Error("Invalid ChannelAssignment", loggerLocation); return false; } ChannelAssignment = (ChannelAssignment)((val & 7) + 1); } else { channels = val + 1; ChannelAssignment = ChannelAssignment.Independent; } Channels = channels; #endregion channels #region bitspersample val = (headerBuffer[3] & 0x0E) >> 1; int bitsPerSample; if (val == 0) { if (streamInfo != null) bitsPerSample = streamInfo.BitsPerSample; else { Error("Missing BitsPerSample. Index = 0 && streamInfoMetaData == null.", loggerLocation); return false; } } else if (val == 3 || val >= 7 || val < 0) { Error("Invalid BitsPerSampleIndex", loggerLocation); return false; } else bitsPerSample = FlacConstant.BitPerSampleTable[val]; BitsPerSample = bitsPerSample; #endregion bitspersample if ((headerBuffer[3] & 0x01) != 0) // reserved bit -> 0 { Error("Invalid FlacFrame. Reservedbit_1 is 1", loggerLocation); return false; } reader.ReadBits(32); //skip the first 4 bytes since they got already processed //BYTE 4 #region utf8 //variable blocksize if ((headerBuffer[1] & 0x01) != 0 || (streamInfo != null && streamInfo.MinBlockSize != streamInfo.MaxBlockSize)) { ulong samplenumber; if (reader.ReadUTF8_64(out samplenumber) && samplenumber != ulong.MaxValue) { BlockingStrategy = BlockingStrategy.VariableBlockSize; SampleNumber = (long) samplenumber; } else { Error("Invalid UTF8 Samplenumber coding.", loggerLocation); return false; } } else //fixed blocksize { uint framenumber; if (reader.ReadUTF8_32(out framenumber) && framenumber != uint.MaxValue) { BlockingStrategy = BlockingStrategy.FixedBlockSize; FrameNumber = (int) framenumber; } else { Error("Invalid UTF8 Framenumber coding.", loggerLocation); return false; } } #endregion utf8 #region read hints //blocksize am ende des frameheaders if (_blocksizeHint != 0) { val = (int)reader.ReadBits(8); if (_blocksizeHint == 7) { val = (val << 8) | (int)reader.ReadBits(8); } BlockSize = val + 1; } //samplerate if (_sampleRateHint != 0) { val = (int)reader.ReadBits(8); if (_sampleRateHint != 12) { val = (val << 8) | (int)reader.ReadBits(8); } if (_sampleRateHint == 12) SampleRate = val * 1000; else if (_sampleRateHint == 13) SampleRate = val; else SampleRate = val * 10; } #endregion read hints if (DoCrc) { var crc8 = Utils.CRC8.Instance.CalcCheckSum(reader.Buffer, 0, reader.Position); Crc8 = (byte) reader.ReadBits(8); if (Crc8 != crc8) { Error("CRC8 missmatch", loggerLocation); return false; } } else { Crc8 = (byte) reader.ReadBits(8); } headerBuffer += reader.Position; return true; } Error("Invalid Syncbits", loggerLocation); return false; }
/// <summary> /// Reads and returns a single <see cref="FlacMetadata"/> from the specified <paramref name="stream"/>. /// </summary> /// <param name="stream">The stream which contains the <see cref="FlacMetadata"/>.</param> /// <returns>Returns the read <see cref="FlacMetadata"/>.</returns> public static unsafe FlacMetadata FromStream(Stream stream) { bool lastBlock; FlacMetaDataType type; int length; byte[] b = new byte[4]; if (stream.Read(b, 0, 4) <= 0) throw new FlacException(new EndOfStreamException("Could not read metadata"), FlacLayer.Metadata); fixed (byte* headerBytes = b) { FlacBitReader bitReader = new FlacBitReader(headerBytes, 0); lastBlock = bitReader.ReadBits(1) == 1; type = (FlacMetaDataType)bitReader.ReadBits(7); length = (int)bitReader.ReadBits(24); } FlacMetadata data; long streamStartPosition = stream.Position; if ((int)type < 0 || (int)type > 6) return null; switch (type) { case FlacMetaDataType.StreamInfo: data = new FlacMetadataStreamInfo(stream, length, lastBlock); break; case FlacMetaDataType.Seektable: data = new FlacMetadataSeekTable(stream, length, lastBlock); break; default: data = new FlacMetadata(type, lastBlock, length); break; } stream.Seek(length - (stream.Position - streamStartPosition), SeekOrigin.Current); return data; }
private void StartScan(FlacMetadataStreamInfo streamInfo, FlacPreScanMode mode) { if (_isRunning) throw new Exception("Scan is already running."); _isRunning = true; if (mode == FlacPreScanMode.Async) { ThreadPool.QueueUserWorkItem(o => { Frames = RunScan(streamInfo); _isRunning = false; }); } else { Frames = RunScan(streamInfo); _isRunning = false; } }
private unsafe bool IsFrame(ref byte *buffer, FlacMetadataStreamInfo streamInfo, out FlacFrameHeader header) { header = new FlacFrameHeader(ref buffer, streamInfo, true, false); return(!header.HasError); }
private unsafe List <FlacFrameInformation> ScanThisShit(FlacMetadataStreamInfo streamInfo) { Stream stream = _stream; //if (!(stream is BufferedStream)) // stream = new BufferedStream(stream); byte[] buffer = new byte[BufferSize]; stream.Position = 4; //fLaC //skip the metadata FlacMetadata.SkipMetadata(stream); List <FlacFrameInformation> frames = new List <FlacFrameInformation>(); FlacFrameInformation frameInfo = new FlacFrameInformation(); frameInfo.IsFirstFrame = true; FlacFrameHeader baseHeader = null; while (true) { int read = stream.Read(buffer, 0, buffer.Length); if (read <= FlacConstant.FrameHeaderSize) break; fixed(byte *bufferPtr = buffer) { byte *ptr = bufferPtr; //for (int i = 0; i < read - FlacConstant.FrameHeaderSize; i++) while ((bufferPtr + read - FlacConstant.FrameHeaderSize) > ptr) { if (*ptr++ == 0xFF && (*ptr & 0xF8) == 0xF8) //check sync { byte *ptrSafe = ptr; ptr--; FlacFrameHeader tmp; if (IsFrame(ref ptr, streamInfo, out tmp)) { FlacFrameHeader header = tmp; if (frameInfo.IsFirstFrame) { baseHeader = header; frameInfo.IsFirstFrame = false; } if (baseHeader != null && baseHeader.IsFormatEqualTo(header)) { frameInfo.StreamOffset = stream.Position - read + ((ptrSafe - 1) - bufferPtr); frameInfo.Header = header; frames.Add(frameInfo); frameInfo.SampleOffset += header.BlockSize; } else { ptr = ptrSafe; } } else { ptr = ptrSafe; } } } } stream.Position -= FlacConstant.FrameHeaderSize; } return(frames); }
private void Decode(Stream stream, FlacMetadataStreamInfo streamInfo) { Header = new FlacFrameHeader(stream, streamInfo); _stream = stream; _streamInfo = streamInfo; HasError = Header.HasError; if (!HasError) { ReadSubFrames(); FreeBuffers(); } }
protected unsafe virtual bool ParseHeader(Stream stream, FlacMetadataStreamInfo streamInfo) { const string loggerLocation = "FlacFrameHeader.ParseHeader(Stream, FlacMetadataStreamInfo)"; byte[] headerBuffer = new byte[FlacConstant.FrameHeaderSize]; if (stream.Read(headerBuffer, 0, headerBuffer.Length) == headerBuffer.Length) { fixed (byte* ptrBuffer = headerBuffer) { byte* ptrSave = ptrBuffer; byte* __ptrBuffer = ptrBuffer; bool result = ParseHeader(ref __ptrBuffer, streamInfo); stream.Position -= (headerBuffer.Length - (__ptrBuffer - ptrSave)); //todo return result; } } else { Error("Not able to read Flac header - EOF?", loggerLocation); return false; } }
/// <summary> /// Creates a new instance of the <see cref="FlacFrame"/> class based on the specified <paramref name="stream"/> and some basic stream information. /// </summary> /// <param name="stream">The stream which contains the flac frame.</param> /// <param name="streamInfo">Some basic information about the flac stream.</param> /// <returns>A new instance of the <see cref="FlacFrame"/> class.</returns> public static FlacFrame FromStream(Stream stream, FlacMetadataStreamInfo streamInfo) { FlacFrame frame = new FlacFrame(stream, streamInfo); return frame; //return frame.HasError ? null : frame; }
protected unsafe virtual bool ParseHeader(ref byte* headerBuffer, FlacMetadataStreamInfo streamInfo) { const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)"; int x = -1; //tmp value to store in if (headerBuffer[0] == 0xFF && headerBuffer[1] >> 1 == 0x7C) //sync bits { if ((headerBuffer[1] & 0x02) != 0) // ...10 2. letzes bits muss 0 sein { Error("Invalid FlacFrame. Reservedbit_0 is 1", loggerLocation); return false; } byte* __headerbufferPtr = headerBuffer; FlacBitReader reader = new FlacBitReader(__headerbufferPtr, 0); #region blocksize //blocksize x = headerBuffer[2] >> 4; int blocksize = -1; if (x == 0) { Error("Invalid Blocksize value: 0", loggerLocation); return false; } else if (x == 1) blocksize = 192; else if (x >= 2 && x <= 5) blocksize = 576 << (x - 2); else if (x == 6 || x == 7) blocksize_hint = x; else if (x >= 8 && x <= 15) blocksize = 256 << (x - 8); else { Error("Invalid Blocksize value: " + x, loggerLocation); return false; } BlockSize = blocksize; #endregion blocksize #region samplerate //samplerate x = headerBuffer[2] & 0x0F; int sampleRate = -1; if (x == 0) { if (streamInfo != null) sampleRate = streamInfo.SampleRate; else { Error("Missing Samplerate. Samplerate Index = 0 && streamInfoMetaData == null.", loggerLocation); return false; } } else if (x >= 1 && x <= 11) sampleRate = FlacConstant.SampleRateTable[x]; else if (x >= 12 && x <= 14) sampleRate_hint = x; else { Error("Invalid SampleRate value: " + x, loggerLocation); return false; } SampleRate = sampleRate; #endregion samplerate #region channels x = headerBuffer[3] >> 4; //cc: unsigned int channels = -1; if ((x & 8) != 0) { channels = 2; if ((x & 7) > 2 || (x & 7) < 0) { Error("Invalid ChannelAssignment", loggerLocation); return false; } else ChannelAssignment = (ChannelAssignment)((x & 7) + 1); } else { channels = x + 1; ChannelAssignment = ChannelAssignment.Independent; } Channels = channels; #endregion channels #region bitspersample x = (headerBuffer[3] & 0x0E) >> 1; int bitsPerSample = -1; if (x == 0) { if (streamInfo != null) bitsPerSample = streamInfo.BitsPerSample; else { Error("Missing BitsPerSample. Index = 0 && streamInfoMetaData == null.", loggerLocation); return false; } } else if (x == 3 || x >= 7 || x < 0) { Error("Invalid BitsPerSampleIndex", loggerLocation); return false; } else bitsPerSample = FlacConstant.BitPerSampleTable[x]; BitsPerSample = bitsPerSample; #endregion bitspersample if ((headerBuffer[3] & 0x01) != 0) // reserved bit -> 0 { Error("Invalid FlacFrame. Reservedbit_1 is 1", loggerLocation); return false; } //reader.SkipBits(4 * 8); //erste 3 bytes headerbytes überspringen, da diese schon ohne reader verarbeitet reader.ReadBits(32); //BYTE 4 #region utf8 //variable blocksize if ((headerBuffer[1] & 0x01) != 0 || (streamInfo != null && streamInfo.MinBlockSize != streamInfo.MaxBlockSize)) { ulong samplenumber; if (reader.ReadUTF8_64(out samplenumber) && samplenumber != ulong.MaxValue) { NumberType = FlacNumberType.SampleNumber; SampleNumber = samplenumber; } else { Error("Invalid UTF8 Samplenumber coding.", loggerLocation); return false; } } else //fixed blocksize { uint framenumber;// = reader.ReadUTF8(); if (reader.ReadUTF8_32(out framenumber) && framenumber != uint.MaxValue) { NumberType = FlacNumberType.FrameNumber; FrameNumber = framenumber; } else { Error("Invalid UTF8 Framenumber coding.", loggerLocation); return false; } } #endregion utf8 #region read hints //blocksize am ende des frameheaders if (blocksize_hint != 0) { x = (int)reader.ReadBits(8); if (blocksize_hint == 7) { x = (x << 8) | (int)reader.ReadBits(8); } BlockSize = x + 1; } //samplerate am ende des frameheaders if (sampleRate_hint != 0) { x = (int)reader.ReadBits(8); if (sampleRate_hint != 12) { x = (x << 8) | (int)reader.ReadBits(8); } if (sampleRate_hint == 12) SampleRate = x * 1000; else if (sampleRate_hint == 13) SampleRate = x; else SampleRate = x * 10; } #endregion read hints //if (Channels == 1 && BitsPerSample == 24 && SampleRate == 44100) // System.Diagnostics.Debugger.Break(); if (DoCRC) { var crc8 = CSMath.CRC8.Instance.CalcCheckSum(reader.Buffer, 0, reader.Position); CRC8 = (byte)reader.ReadBits(8); if (CRC8 != crc8) { Error("CRC8 missmatch", loggerLocation); return false; } } headerBuffer += reader.Position; return true; } Error("Invalid Syncbits", loggerLocation); return false; }
public void ScanStream(FlacMetadataStreamInfo streamInfo, FlacPreScanMethodMode method) { long saveOffset = _stream.Position; StartScan(streamInfo, method); _stream.Position = saveOffset; long totalLength = 0, totalsamples = 0; foreach (var frame in Frames) { totalLength += frame.Header.BlockSize * frame.Header.BitsPerSample * frame.Header.Channels; totalsamples += frame.Header.BlockSize; } TotalLength = totalLength; TotalSamples = totalsamples; }
public FlacFrameHeader(Stream stream, FlacMetadataStreamInfo streamInfo) : this(stream, streamInfo, true) { }
protected void StartScan(FlacMetadataStreamInfo streamInfo, FlacPreScanMethodMode method) { if (_isRunning) throw new Exception("Scan is already running."); _isRunning = true; if (method == FlacPreScanMethodMode.Async) { new Thread((o) => { Frames = RunScan(streamInfo); _isRunning = false; }).Start(); } else { Frames = ScanThisShit(streamInfo); _isRunning = false; } }
/// <summary> /// Initializes a new instance of the <see cref="FlacFrameHeader"/> class. /// </summary> /// <param name="stream">The underlying stream which contains the <see cref="FlacFrameHeader"/>.</param> /// <param name="streamInfo">The stream-info-metadata-block of the flac stream which provides some basic information about the flac framestream. Can be set to null.</param> public FlacFrameHeader(Stream stream, FlacMetadataStreamInfo streamInfo) : this(stream, streamInfo, true) { }
private unsafe List<FlacFrameInformation> ScanThisShit(FlacMetadataStreamInfo streamInfo) { Stream stream = _stream; //if (!(stream is BufferedStream)) // stream = new BufferedStream(stream); byte[] buffer = new byte[bufferSize]; int read = 0; stream.Position = 4; //fLaC FlacMetadata.AllDataFromStream(stream); List<FlacFrameInformation> frames = new List<FlacFrameInformation>(); FlacFrameInformation frameInfo = new FlacFrameInformation(); frameInfo.IsFirstFrame = true; FlacFrameHeader header; FlacFrameHeader tmp = null; FlacFrameHeader baseHeader = null; while (true) { read = stream.Read(buffer, 0, buffer.Length); if (read <= FlacConstant.FrameHeaderSize) break; fixed (byte* bufferPtr = buffer) { byte* ptr = bufferPtr; byte* ptrSafe; //for (int i = 0; i < read - FlacConstant.FrameHeaderSize; i++) while ((bufferPtr + read - FlacConstant.FrameHeaderSize) > ptr) { if ((*ptr++ & 0xFF) == 0xFF && (*ptr & 0xF8) == 0xF8) //check sync { ptrSafe = ptr; ptr--; if (IsFrame(ref ptr, streamInfo, baseHeader, out tmp)) { header = tmp; if (frameInfo.IsFirstFrame) { baseHeader = header; frameInfo.IsFirstFrame = false; } if (baseHeader.CompareTo(header)) { frameInfo.StreamOffset = stream.Position - read + ((ptrSafe - 1) - bufferPtr); frameInfo.Header = header; frames.Add(frameInfo); frameInfo.SampleOffset += header.BlockSize; } else { ptr = ptrSafe; } //todo: } else { ptr = ptrSafe; } } } } stream.Position -= FlacConstant.FrameHeaderSize; } return frames; }
public unsafe FlacFrameHeader(ref byte* buffer, FlacMetadataStreamInfo streamInfo, bool doCrc) : this(ref buffer, streamInfo, doCrc, true) { }
/// <summary> /// Initializes a new instance of the <see cref="FlacFile" /> class. /// </summary> /// <param name="stream">Stream which contains flac data which should be decoded.</param> /// <param name="scanFlag">Scan mode which defines how to scan the flac data for frames.</param> /// <param name="onscanFinished"> /// Callback which gets called when the pre scan processes finished. Should be used if the /// <paramref name="scanFlag" /> argument is set the <see cref="FlacPreScanMode.Async" />. /// </param> public FlacFile(Stream stream, FlacPreScanMode scanFlag, Action<FlacPreScanFinishedEventArgs> onscanFinished) { if (stream == null) throw new ArgumentNullException(); if (!stream.CanRead) throw new ArgumentException("Stream is not readable.", "stream"); _stream = stream; //skip ID3v2 ID3v2.SkipTag(stream); //read fLaC sync var beginSync = new byte[4]; int read = stream.Read(beginSync, 0, beginSync.Length); if (read < beginSync.Length) throw new EndOfStreamException("Can not read \"fLaC\" sync."); if (beginSync[0] == 0x66 && beginSync[1] == 0x4C && //Check for 'fLaC' signature beginSync[2] == 0x61 && beginSync[3] == 0x43) { //read metadata List<FlacMetadata> metadata = FlacMetadata.ReadAllMetadataFromStream(stream).ToList(); Metadata = metadata.AsReadOnly(); if (metadata.Count <= 0) throw new FlacException("No Metadata found.", FlacLayer.Metadata); var streamInfo = metadata.First(x => x.MetaDataType == FlacMetaDataType.StreamInfo) as FlacMetadataStreamInfo; if (streamInfo == null) throw new FlacException("No StreamInfo-Metadata found.", FlacLayer.Metadata); _streamInfo = streamInfo; _waveFormat = CreateWaveFormat(streamInfo); Debug.WriteLine("Flac StreamInfo found -> WaveFormat: " + _waveFormat); Debug.WriteLine("Flac-File-Metadata read."); } else throw new FlacException("Invalid Flac-File. \"fLaC\" Sync not found.", FlacLayer.OutSideOfFrame); //prescan stream if (scanFlag != FlacPreScanMode.None) { var scan = new FlacPreScan(stream); scan.ScanFinished += (s, e) => { if (onscanFinished != null) onscanFinished(e); }; scan.ScanStream(_streamInfo, scanFlag); _scan = scan; } }
private unsafe bool ParseHeader(ref byte *headerBuffer, FlacMetadataStreamInfo streamInfo) { const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)"; int val; if (headerBuffer[0] == 0xFF && headerBuffer[1] >> 1 == 0x7C) //sync bits { if ((headerBuffer[1] & 0x02) != 0) { Error("Invalid FlacFrame. Reservedbit_0 is 1", loggerLocation); return(false); } byte * __headerbufferPtr = headerBuffer; FlacBitReader reader = new FlacBitReader(__headerbufferPtr, 0); #region blocksize //blocksize val = headerBuffer[2] >> 4; int blocksize = -1; if (val == 0) { Error("Invalid Blocksize value: 0", loggerLocation); return(false); } if (val == 1) { blocksize = 192; } else if (val >= 2 && val <= 5) { blocksize = 576 << (val - 2); } else if (val == 6 || val == 7) { _blocksizeHint = val; } else if (val >= 8 && val <= 15) { blocksize = 256 << (val - 8); } else { Error("Invalid Blocksize value: " + val, loggerLocation); return(false); } BlockSize = blocksize; #endregion blocksize #region samplerate //samplerate val = headerBuffer[2] & 0x0F; int sampleRate = -1; if (val == 0) { if (streamInfo != null) { sampleRate = streamInfo.SampleRate; } else { Error("Missing Samplerate. Samplerate Index = 0 && streamInfoMetaData == null.", loggerLocation); return(false); } } else if (val >= 1 && val <= 11) { sampleRate = FlacConstant.SampleRateTable[val]; } else if (val >= 12 && val <= 14) { _sampleRateHint = val; } else { Error("Invalid SampleRate value: " + val, loggerLocation); return(false); } SampleRate = sampleRate; #endregion samplerate #region channels val = headerBuffer[3] >> 4; //cc: unsigned int channels; if ((val & 8) != 0) { channels = 2; if ((val & 7) > 2 || (val & 7) < 0) { Error("Invalid ChannelAssignment", loggerLocation); return(false); } ChannelAssignment = (ChannelAssignment)((val & 7) + 1); } else { channels = val + 1; ChannelAssignment = ChannelAssignment.Independent; } Channels = channels; #endregion channels #region bitspersample val = (headerBuffer[3] & 0x0E) >> 1; int bitsPerSample; if (val == 0) { if (streamInfo != null) { bitsPerSample = streamInfo.BitsPerSample; } else { Error("Missing BitsPerSample. Index = 0 && streamInfoMetaData == null.", loggerLocation); return(false); } } else if (val == 3 || val >= 7 || val < 0) { Error("Invalid BitsPerSampleIndex", loggerLocation); return(false); } else { bitsPerSample = FlacConstant.BitPerSampleTable[val]; } BitsPerSample = bitsPerSample; #endregion bitspersample if ((headerBuffer[3] & 0x01) != 0) // reserved bit -> 0 { Error("Invalid FlacFrame. Reservedbit_1 is 1", loggerLocation); return(false); } reader.ReadBits(32); //skip the first 4 bytes since they got already processed //BYTE 4 #region utf8 //variable blocksize if ((headerBuffer[1] & 0x01) != 0 || (streamInfo != null && streamInfo.MinBlockSize != streamInfo.MaxBlockSize)) { ulong samplenumber; if (reader.ReadUTF8_64(out samplenumber) && samplenumber != ulong.MaxValue) { BlockingStrategy = BlockingStrategy.VariableBlockSize; SampleNumber = (long)samplenumber; } else { Error("Invalid UTF8 Samplenumber coding.", loggerLocation); return(false); } } else //fixed blocksize { uint framenumber; if (reader.ReadUTF8_32(out framenumber) && framenumber != uint.MaxValue) { BlockingStrategy = BlockingStrategy.FixedBlockSize; FrameNumber = (int)framenumber; } else { Error("Invalid UTF8 Framenumber coding.", loggerLocation); return(false); } } #endregion utf8 #region read hints //blocksize am ende des frameheaders if (_blocksizeHint != 0) { val = (int)reader.ReadBits(8); if (_blocksizeHint == 7) { val = (val << 8) | (int)reader.ReadBits(8); } BlockSize = val + 1; } //samplerate if (_sampleRateHint != 0) { val = (int)reader.ReadBits(8); if (_sampleRateHint != 12) { val = (val << 8) | (int)reader.ReadBits(8); } if (_sampleRateHint == 12) { SampleRate = val * 1000; } else if (_sampleRateHint == 13) { SampleRate = val; } else { SampleRate = val * 10; } } #endregion read hints if (DoCrc) { var crc8 = Utils.CRC8.Instance.CalcCheckSum(reader.Buffer, 0, reader.Position); Crc8 = (byte)reader.ReadBits(8); if (Crc8 != crc8) { Error("CRC8 missmatch", loggerLocation); return(false); } } else { Crc8 = (byte)reader.ReadBits(8); } headerBuffer += reader.Position; return(true); } Error("Invalid Syncbits", loggerLocation); return(false); }