Example #1
0
        /// <summary>
        /// Copy field values from another <see cref="WaveFormat"/> object.
        /// </summary>
        /// <param name="other">The <see cref="WaveFormat"/> object to copy from.</param>
        public override void CopyFrom(WaveFormat other)
        {
            base.CopyFrom(other);

            WaveFormatEx otherEx = other as WaveFormatEx;

            if (otherEx != null)
            {
                this.ExtraInfo = (byte[])otherEx.ExtraInfo?.Clone();
            }
        }
Example #2
0
        /// <summary>
        /// Reads from a stream to create a WaveFormat object.
        /// </summary>
        /// <param name="stream">
        /// The stream to read the WaveFormat from (e.g. a file). The stream should already
        /// be positioned on the first byte of the WaveFormat header (i.e. the format tag).
        /// Note that the stream is not disposed after the header has been read.
        /// </param>
        /// <param name="formatLength">
        /// The total number of bytes in the stream that represent the WaveFormat header.
        /// </param>
        /// <returns>
        /// A new WaveFormat header constructed from the stream.
        /// </returns>
        public static WaveFormat FromStream(Stream stream, int formatLength)
        {
            if (formatLength < 16)
            {
                throw new InvalidDataException("A WaveFormat must contain at least 16 bytes");
            }

            BinaryReader reader     = new BinaryReader(stream);
            WaveFormat   waveFormat = new WaveFormat();

            waveFormat.FormatTag      = (WaveFormatTag)reader.ReadUInt16();
            waveFormat.Channels       = reader.ReadUInt16();
            waveFormat.SamplesPerSec  = reader.ReadUInt32();
            waveFormat.AvgBytesPerSec = reader.ReadUInt32();
            waveFormat.BlockAlign     = reader.ReadUInt16();
            waveFormat.BitsPerSample  = reader.ReadUInt16();

            if (formatLength > 16)
            {
                // Format may contain extra bytes
                waveFormat.ExtraSize = reader.ReadUInt16();

                // Sanity check and size limit
                if (waveFormat.ExtraSize > formatLength - 18)
                {
                    throw new FormatException("Format extra size too large");
                }

                if (waveFormat.ExtraSize > 0)
                {
                    // Promote to a WaveFormatEx object to hold the extra info
                    waveFormat = new WaveFormatEx()
                    {
                        FormatTag      = waveFormat.FormatTag,
                        SamplesPerSec  = waveFormat.SamplesPerSec,
                        BitsPerSample  = waveFormat.BitsPerSample,
                        Channels       = waveFormat.Channels,
                        BlockAlign     = waveFormat.BlockAlign,
                        AvgBytesPerSec = waveFormat.AvgBytesPerSec,
                        ExtraSize      = waveFormat.ExtraSize,

                        // Read in the extended format extra bytes
                        ExtraInfo = reader.ReadBytes(waveFormat.ExtraSize)
                    };
                }
            }

            return(waveFormat);
        }
Example #3
0
        /// <summary>
        /// Gets the appropriate Media Foundation audio media subtype from the specified wave format.
        /// </summary>
        /// <param name="format">
        /// Input wave format to convert.
        /// </param>
        /// <returns>
        /// Media Foundation audio subtype resulting from conversion.
        /// </returns>
        internal static Guid GetMediaSubtype(WaveFormat format)
        {
            switch (format.FormatTag)
            {
            case WaveFormatTag.WAVE_FORMAT_PCM:
            case WaveFormatTag.WAVE_FORMAT_IEEE_FLOAT:
            case WaveFormatTag.WAVE_FORMAT_DTS:
            case WaveFormatTag.WAVE_FORMAT_DOLBY_AC3_SPDIF:
            case WaveFormatTag.WAVE_FORMAT_DRM:
            case WaveFormatTag.WAVE_FORMAT_WMAUDIO2:
            case WaveFormatTag.WAVE_FORMAT_WMAUDIO3:
            case WaveFormatTag.WAVE_FORMAT_WMAUDIO_LOSSLESS:
            case WaveFormatTag.WAVE_FORMAT_WMASPDIF:
            case WaveFormatTag.WAVE_FORMAT_WMAVOICE9:
            case WaveFormatTag.WAVE_FORMAT_MPEGLAYER3:
            case WaveFormatTag.WAVE_FORMAT_MPEG:
            case WaveFormatTag.WAVE_FORMAT_MPEG_HEAAC:
            case WaveFormatTag.WAVE_FORMAT_MPEG_ADTS_AAC:
            {
                // These format tags map 1-to-1 to Media Foundation formats.
                // The MSDN topic http://msdn.microsoft.com/en-us/library/aa372553(VS.85).aspx indicates that
                // to create an audio subtype GUID one can:
                // 1. Start with the value MFAudioFormat_Base
                // 2. Replace the first DWORD of this GUID with the format tag
                return(new Guid((uint)format.FormatTag, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71));
            }

            case WaveFormatTag.WAVE_FORMAT_EXTENSIBLE:
            {
                WaveFormatEx formatEx = (WaveFormatEx)format;

                // We only support PCM and IEEE float subtypes for extensible wave formats
                if (formatEx.SubFormat == Guids.KSDataFormatSubTypePCM)
                {
                    return(new Guid((uint)WaveFormatTag.WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71));
                }
                else if (formatEx.SubFormat == Guids.KSDataFormatSubTypeIeeeFloat)
                {
                    return(new Guid((uint)WaveFormatTag.WAVE_FORMAT_IEEE_FLOAT, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71));
                }

                break;
            }
            }

            return(Guid.Empty);
        }
Example #4
0
        /// <summary>
        /// Creates a copy of an existing <see cref="WaveFormat"/>.
        /// </summary>
        /// <param name="other">The <see cref="WaveFormat"/> to copy</param>
        /// <returns>The WaveFormat object</returns>
        public static WaveFormat Create(WaveFormat other)
        {
            if (other == null)
            {
                return(null);
            }

            WaveFormat waveFormat = null;

            if (other is WaveFormatEx)
            {
                waveFormat = new WaveFormatEx();
            }
            else
            {
                waveFormat = new WaveFormat();
            }

            waveFormat.CopyFrom(other);
            return(waveFormat);
        }
Example #5
0
        /// <summary>
        /// Indicates whether the current object is equal to another object.
        /// </summary>
        /// <param name="other">
        /// An object to compare with this object.
        /// </param>
        /// <returns>
        /// true if the current object is equal to the other parameter; otherwise, false.
        /// </returns>
        public override bool Equals(object other)
        {
            if (base.Equals(other))
            {
                // extra size is zero for both, so extra bytes are irrelevant
                if (this.ExtraSize == 0)
                {
                    return(true);
                }

                // Downcast other to WaveFormatEx to compare extra bytes
                WaveFormatEx format = other as WaveFormatEx;

                // sanity checks for extra bytes
                if ((format == null) ||
                    (this.ExtraInfo == null) ||
                    (format.ExtraInfo == null) ||
                    (this.ExtraInfo.Length < this.ExtraSize) ||
                    (format.ExtraInfo.Length < format.ExtraSize))
                {
                    return(false);
                }

                // byte-wise comparison of extra bytes
                for (int i = 0; i < this.ExtraSize; ++i)
                {
                    if (this.ExtraInfo[i] != format.ExtraInfo[i])
                    {
                        return(false);
                    }
                }

                // equality
                return(true);
            }

            return(false);
        }
Example #6
0
        /// <summary>
        /// Marshals a <see cref="WaveFormat"/> object to a native WAVEFORMATEX structure.
        /// </summary>
        /// <param name="format">The <see cref="WaveFormat"/> object to marshal.</param>
        /// <param name="ptr">A pointer to an unmanaged block of memory, which must be allocated before this method is called.</param>
        public static void MarshalToPtr(WaveFormat format, IntPtr ptr)
        {
            // If format is of a derived type, demote it to the base WaveFormat to ensure
            // that the base structure marshal correctly and does not overflow the allocated
            // memory. The extra info bytes will be marshaled separately.
            WaveFormat baseFormat = format;

            if (format.GetType() != typeof(WaveFormat))
            {
                baseFormat = new WaveFormat();
                baseFormat.CopyFrom(format);
            }

            Marshal.StructureToPtr(baseFormat, ptr, false);
            if (format.ExtraSize > 0)
            {
                WaveFormatEx waveFormatEx = format as WaveFormatEx;

                if ((waveFormatEx == null) ||
                    (waveFormatEx.ExtraInfo == null))
                {
                    throw new InvalidOperationException("WaveFormat has non-zero extra bytes but no extra bytes field was present.");
                }

                if (waveFormatEx.ExtraInfo.Length < format.ExtraSize)
                {
                    throw new InvalidOperationException($"WaveFormat extra size field and extra byte count mismatch. "
                                                        + "Expected {format.ExtraSize} bytes but ExtraInfo only contains {waveFormatEx.ExtraInfo.Length} bytes.");
                }

                if (waveFormatEx != null)
                {
                    // Write out extra info
                    IntPtr extraInfoPtr = new IntPtr(ptr.ToInt64() + Marshal.SizeOf <WaveFormat>());
                    Marshal.Copy(waveFormatEx.ExtraInfo, 0, extraInfoPtr, format.ExtraSize);
                }
            }
        }
Example #7
0
        /// <summary>
        /// Marshals a native WAVEFORMATEX structure to a <see cref="WaveFormat"/> object.
        /// </summary>
        /// <param name="ptr">Pointer to a WAVEFORMATEX structure.</param>
        /// <returns>A <see cref="WaveFormat"/> object representing the WAVEFORMATEX structure.</returns>
        public static WaveFormat MarshalFromPtr(IntPtr ptr)
        {
            WaveFormat waveFormat = null;

            if (ptr != IntPtr.Zero)
            {
                waveFormat = Marshal.PtrToStructure <WaveFormat>(ptr);
                if (waveFormat.ExtraSize > 0)
                {
                    WaveFormatEx waveFormatEx = new WaveFormatEx();
                    waveFormatEx.CopyFrom(waveFormat);
                    IntPtr extraInfoPtr = new IntPtr(ptr.ToInt64() + Marshal.SizeOf <WaveFormat>());

                    // Read extra info
                    waveFormatEx.ExtraInfo = new byte[waveFormatEx.ExtraSize];
                    Marshal.Copy(extraInfoPtr, waveFormatEx.ExtraInfo, 0, waveFormatEx.ExtraSize);

                    // Return the WaveFormatEx object
                    waveFormat = waveFormatEx;
                }
            }

            return(waveFormat);
        }