/// <summary> /// Quickly checks an array of bytes to see if it represents a valid AAC frame header. /// </summary> /// <param name="frameHeader">Bytes representing an AAC frame header.</param> /// <returns>true if the supplied bytes are a valid frame header, otherwise, false.</returns> public static bool IsValidFrame(byte[] frameHeader) { if (frameHeader == null) { throw new ArgumentNullException("frameHeader"); } int value = BitTools.MaskBits(frameHeader, 0, 12); if (value != AacpFrame.syncValue) { return(false); } int sampleRate = AacpFrame.ParseSampleRate(frameHeader); if (sampleRate == -1) { return(false); } int numberOfChannels = AacpFrame.ParseChannel(frameHeader); if (numberOfChannels == -1) { return(false); } return(true); }
/// <summary> /// Parses the audio output mode of this frame's audio data. /// </summary> /// <param name="frameHeader">The 4 byte header for this frame.</param> /// <returns>The audio output mode of this frame's audio data.</returns> private static Channel ParseChannel(byte[] frameHeader) { Channel channel; int channelValue = BitTools.MaskBits(frameHeader, 24, 2); switch (channelValue) { case 3: channel = Channel.SingleChannel; break; case 2: channel = Channel.DualChannel; break; case 1: channel = Channel.JointStereo; break; case 0: channel = Channel.Stereo; break; default: channel = Channel.SingleChannel; // ERROR CASE break; } return(channel); }
/// <summary> /// Parses which complexity layer of the MPEG standard this frame conforms to from the frame header. /// </summary> /// <param name="frameHeader">The 4 byte header for this frame.</param> /// <returns>The complexity layer this frame conforms to.</returns> private static int ParseLayer(byte[] frameHeader) { int layer; int layerValue = BitTools.MaskBits(frameHeader, 13, 2); switch (layerValue) { case 3: layer = 1; break; case 2: layer = 2; break; case 1: layer = 3; break; default: // This indicates an invalid layer. layer = -1; break; } return(layer); }
/// <summary> /// Parses the version of the MPEG standard this frame header conforms to from the frame header. /// </summary> /// <param name="frameHeader"> The 4 byte header for this frame. </param> /// <returns> /// The version of the MPEG standard this frame conforms to. /// 1 = Mpeg 1 /// 2 = Mpeg 2 /// 3 = Mpeg 2.5 /// </returns> private static int ParseVersion(byte[] frameHeader) { int version; int versionValue = BitTools.MaskBits(frameHeader, 11, 2); switch (versionValue) { case 3: version = 1; break; case 2: version = 2; break; case 0: version = 3; break; default: // This indicates an invalid version. version = -1; break; } return(version); }
/// <summary> /// Quickly checks an array of bytes to see if it represents a valid MP3 frame header. /// </summary> /// <param name="frameHeader">Bytes representing an MP3 frame header.</param> /// <returns>true if the supplied bytes are a valid frame header, otherwise, false.</returns> public static bool IsValidFrame(byte[] frameHeader) { if (frameHeader == null) { throw new ArgumentNullException("frameHeader"); } if (frameHeader.Length != 4) { throw new ArgumentException("frameHeader must be of length 4."); } int value = BitTools.MaskBits(frameHeader, 0, 11); if (value != SyncValue) { return(false); } int version = ParseVersion(frameHeader); int layer = ParseLayer(frameHeader); int bitrateIndex = BitTools.MaskBits(frameHeader, 16, 4); int samplingRateIndex = BitTools.MaskBits(frameHeader, 20, 2); if ((version == -1) || (layer == -1) || (bitrateIndex < 0) || (bitrateIndex >= 15) || (samplingRateIndex < 0) || (samplingRateIndex >= 3)) { return(false); } return(true); }
/// <summary> /// Parses the sample rate from the supplied AAC frame header. /// </summary> /// <param name="frameHeader">Byte array containing the AAC frame header.</param> /// <returns>The sample rate of the supplied AAC frame header.</returns> private static int ParseSampleRate(byte[] frameHeader) { int sampleRateValue = BitTools.MaskBits(frameHeader, 18, 4); if ((sampleRateValue < 0) || (sampleRateValue > 15)) { return(-1); } return(AacpFrame.sampleRateTable[sampleRateValue]); }
/// <summary> /// Parses the number of channels from the supplied AAC frame header. /// </summary> /// <param name="frameHeader">Byte array containing the AAC frame header.</param> /// <returns>The number of channels of the supplied AAC frame header.</returns> private static int ParseChannel(byte[] frameHeader) { int channelValue = BitTools.MaskBits(frameHeader, 23, 3); if ((channelValue < 1) || (channelValue > 7)) { // Invalid or reserved channel value return(-1); } return(AacpFrame.numberOfChannelsTable[channelValue]); }
/// <summary> /// Initializes a new instance of the MpegFrame class. /// </summary> /// <remarks> /// <para> /// This class is a partial implementation of an MPEG audio frame. The primary purpose of this class is to represent an Mpeg 1 Layer 3 /// file or MP3 file for short. Many of the features not explicitly needed /// for audio rendering are omitted from the implementation. /// </para> /// <para> /// Data on this format is readily discoverable in many books as well as by /// searching for "MP3 Frame" in your favorite search engine. As always, /// Wikipedia is well stocked in all of these areas as well. /// </para> /// </remarks> /// <param name="frameHeader">Byte array containing 4 bytes representing an MPEG Layer 3 header.</param> public MpegFrame(byte[] frameHeader) { if (frameHeader == null) { throw new ArgumentNullException("frameHeader"); } if (frameHeader.Length != 4) { throw new ArgumentException("Invalid frame header length."); } // Sync int value = BitTools.MaskBits(frameHeader, 0, 11); if (value != SyncValue) { throw new ArgumentException("Invalid sync value."); } this.Version = ParseVersion(frameHeader); this.Layer = ParseLayer(frameHeader); this.IsProtected = BitTools.MaskBits(frameHeader, 15, 1) == 1 ? false : true; this.BitrateIndex = BitTools.MaskBits(frameHeader, 16, 4); this.SamplingRateIndex = BitTools.MaskBits(frameHeader, 20, 2); this.Padding = BitTools.MaskBits(frameHeader, 22, 1); //// Private Bit = BitTools.MaskBits(_mp3FrameHeader,8,1); //USELESS this.Channels = ParseChannel(frameHeader); //// Joint Mode = ParseJoitMode(_mp3FrameHeader); //Not used by Mp3MSS //// CopyRight = BitTools.MaskBits(_mp3FrameHeader,3,1); //Not used by Mp3MSS //// Original = BitTools.MaskBits(_mp3FrameHeader,2,1); //Not used by Mp3MSS //// Emphasis = ParseEmphasis(_mp3FrameHeader); //Not used by Mp3MSS this.BitRate = MpegFrame.CalculateBitRate(this.Version, this.Layer, this.BitrateIndex); this.SamplingRate = MpegFrame.LookupSamplingRate(this.Version, this.SamplingRateIndex); this.FrameSize = MpegFrame.CalculateFrameSize(this.Version, this.Layer, this.BitRate, this.SamplingRate, this.Padding); this.NumberOfChannels = (this.Channels == Channel.SingleChannel) ? 1 : 2; if ((this.Version == -1) || (this.Layer == -1) || (this.BitrateIndex < 0) || (this.BitrateIndex >= 15) || (this.SamplingRateIndex < 0) || (this.SamplingRateIndex >= 3)) { throw new ArgumentException("Invalid header values"); } // Add in the bytes we already read if (this.FrameSize <= 0) { throw new InvalidOperationException("MpegFrame's FrameSize must be greater than zero."); } }
/// <summary> /// Initializes a new instance of the AacpFrame class. /// </summary> /// <remarks> /// <para> /// This class is a partial implementation of an AAC audio frame. The primary purpose of this class is to represent an AAC /// file. Many of the features not explicitly needed for audio rendering are omitted from the implementation. /// </para> /// <para> /// Data on this format is readily discoverable in many books as well as by /// searching for "AAC Frame" in your favorite search engine. As always, /// Wikipedia is well stocked in all of these areas as well. /// </para> /// </remarks> /// <param name="frameHeader">Byte array containing 4 bytes representing an AAC header.</param> public AacpFrame(byte[] frameHeader) : base() { if (frameHeader == null) { throw new ArgumentNullException("frameHeader"); } // Sync int value = BitTools.MaskBits(frameHeader, 0, 12); if (value != syncValue) { throw new ArgumentException("Invalid sync value."); } this.NumberOfChannels = AacpFrame.ParseChannel(frameHeader); this.SamplingRate = AacpFrame.ParseSampleRate(frameHeader); this.BitRate = AacpFrame.CalculateBitRate(this.SamplingRate, this.NumberOfChannels); this.FrameSize = AacpFrame.ParseFrameSize(frameHeader); int objectTypeId = BitTools.MaskBits(frameHeader, 16, 2); }
/// <summary> /// Parses the AAC frame header to find the actual size of the header. /// </summary> /// <param name="frameHeader">Byte array containing the AAC frame header.</param> /// <returns>Actual size of the supplied AAC frame header.</returns> private static int ParseFrameSize(byte[] frameHeader) { int value = BitTools.MaskBits(frameHeader, 30, 13); return(value); }