/// <summary> /// Constructs a new WAVE data chunk for the specified format. /// </summary> /// <param name="waveFormat"><see cref="WaveFormatChunk"/> that describes this <see cref="WaveDataChunk"/>.</param> public WaveDataChunk(WaveFormatChunk waveFormat) : base(RiffTypeID) { m_waveFormat = waveFormat; m_sampleBlocks = new List <LittleBinaryValue[]>(); m_chunkSize = -1; }
/// <summary> /// Creates a <see cref="WaveDataReader"/> instance created from a WAV stream. /// </summary> /// <param name="waveStream">The WAV stream. The data in the stream must include all headers that would be present in a WAV file.</param> /// <returns>The WaveData instance created from a WAV stream.</returns> /// <remarks> /// This method is similar to the <see cref="WaveDataReader(Stream)"/> constructor, /// however this method will first search the stream for a format chunk in order to set /// up the WaveData object with proper format info. /// </remarks> public static WaveDataReader FromStream(Stream waveStream) { RiffChunk riffChunk; WaveFormatChunk waveFormat = null; WaveDataReader waveData = null; while ((object)waveData == null) { riffChunk = RiffChunk.ReadNext(waveStream); switch (riffChunk.TypeID) { case RiffHeaderChunk.RiffTypeID: // ReSharper disable once ObjectCreationAsStatement new RiffHeaderChunk(riffChunk, waveStream, "WAVE"); break; case WaveFormatChunk.RiffTypeID: waveFormat = new WaveFormatChunk(riffChunk, waveStream); break; case WaveDataChunk.RiffTypeID: waveData = new WaveDataReader(waveFormat, waveStream); break; default: // Skip unnecessary sections waveStream.Seek(riffChunk.ChunkSize, SeekOrigin.Current); break; } } return(waveData); }
/// <summary>Reads a new WAVE format section from the specified stream.</summary> /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param> /// <param name="source">Source stream to read data from.</param> /// <param name="waveFormat">Format of the data section to be parsed.</param> /// <exception cref="InvalidOperationException">WAVE format or extra parameters section too small, wave file corrupted.</exception> public WaveDataChunk(RiffChunk preRead, Stream source, WaveFormatChunk waveFormat) : base(preRead, RiffTypeID) { m_waveFormat = waveFormat; m_sampleBlocks = new List <LittleBinaryValue[]>(); m_chunkSize = -1; int blockSize = waveFormat.BlockAlignment; int sampleSize = waveFormat.BitsPerSample / 8; int channels = waveFormat.Channels; TypeCode sampleTypeCode = m_waveFormat.GetSampleTypeCode(); LittleBinaryValue[] sampleBlock; byte[] buffer = new byte[blockSize]; int bytesRead = source.Read(buffer, 0, blockSize); while (bytesRead == blockSize) { // Create a new sample block, one little-endian formatted binary sample value for each channel sampleBlock = new LittleBinaryValue[channels]; for (int x = 0; x < channels; x++) { sampleBlock[x] = new LittleBinaryValue(sampleTypeCode, buffer, x * sampleSize, sampleSize); } m_sampleBlocks.Add(sampleBlock); bytesRead = source.Read(buffer, 0, blockSize); } }
/// <summary> /// Creates a new instance of the <see cref="WaveDataReader"/> class. /// </summary> /// <param name="waveFormat">The format of the wave stream.</param> /// <param name="waveStream">The stream containing wave data.</param> public WaveDataReader(WaveFormatChunk waveFormat, Stream waveStream) { m_format = waveFormat ?? DEFAULT_WAVE_FORMAT_CHUNK; m_waveStream = waveStream; m_blockSize = m_format.BlockAlignment; m_sampleSize = m_format.BitsPerSample / 8; m_channels = m_format.Channels; m_sampleType = m_format.GetSampleTypeCode(); }
/// <summary> /// Creates a copy of the <see cref="WaveFormatChunk"/>. /// </summary> /// <returns>A new copy of the <see cref="WaveFormatChunk"/>.</returns> public new WaveFormatChunk Clone() { WaveFormatChunk waveFormatChunk = new WaveFormatChunk(m_sampleRate, m_bitsPerSample, m_channels, m_audioFormat); if ((object)m_extraParameters != null) { byte[] extraParameters = new byte[m_extraParameters.Length]; Buffer.BlockCopy(m_extraParameters, 0, extraParameters, 0, m_extraParameters.Length); waveFormatChunk.ExtraParameters = extraParameters; } return(waveFormatChunk); }
/// <summary> /// Creates a copy of the <see cref="WaveFormatChunk"/>. /// </summary> /// <returns>A new copy of the <see cref="WaveFormatChunk"/>.</returns> public new WaveFormatChunk Clone() { WaveFormatChunk waveFormatChunk = new WaveFormatChunk(m_sampleRate, m_bitsPerSample, m_channels, m_audioFormat); if ((object)m_extraParameters != null) { byte[] extraParameters = new byte[m_extraParameters.Length]; Buffer.BlockCopy(m_extraParameters, 0, extraParameters, 0, m_extraParameters.Length); waveFormatChunk.ExtraParameters = extraParameters; } return waveFormatChunk; }
/// <summary> /// Constructs a new WAVE data chunk for the specified format. /// </summary> /// <param name="waveFormat"><see cref="WaveFormatChunk"/> that describes this <see cref="WaveDataChunk"/>.</param> public WaveDataChunk(WaveFormatChunk waveFormat) : base(RiffTypeID) { m_waveFormat = waveFormat; m_sampleBlocks = new List<LittleBinaryValue[]>(); m_chunkSize = -1; }
/// <summary>Reads a new WAVE format section from the specified stream.</summary> /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param> /// <param name="source">Source stream to read data from.</param> /// <param name="waveFormat">Format of the data section to be parsed.</param> /// <exception cref="InvalidOperationException">WAVE format or extra parameters section too small, wave file corrupted.</exception> public WaveDataChunk(RiffChunk preRead, Stream source, WaveFormatChunk waveFormat) : base(preRead, RiffTypeID) { m_waveFormat = waveFormat; m_sampleBlocks = new List<LittleBinaryValue[]>(); m_chunkSize = -1; int blockSize = waveFormat.BlockAlignment; int sampleSize = waveFormat.BitsPerSample / 8; int channels = waveFormat.Channels; TypeCode sampleTypeCode = m_waveFormat.GetSampleTypeCode(); LittleBinaryValue[] sampleBlock; byte[] buffer = new byte[blockSize]; int bytesRead = source.Read(buffer, 0, blockSize); while (bytesRead == blockSize) { // Create a new sample block, one little-endian formatted binary sample value for each channel sampleBlock = new LittleBinaryValue[channels]; for (int x = 0; x < channels; x++) { sampleBlock[x] = new LittleBinaryValue(sampleTypeCode, buffer, x * sampleSize, sampleSize); } m_sampleBlocks.Add(sampleBlock); bytesRead = source.Read(buffer, 0, blockSize); } }
/// <summary> /// Creates a new <see cref="WaveFormatExtensible"/> object based on the <see cref="WaveFormatChunk"/> settings. /// </summary> /// <param name="waveFormat">A <see cref="WaveFormatChunk"/> format.</param> public WaveFormatExtensible(WaveFormatChunk waveFormat) { m_sampleValue = (ushort)waveFormat.BitsPerSample; m_channelMask = Speakers.All; m_subFormat = DataFormatSubType.PCM; }
/// <summary> /// Creates a <see cref="WaveDataReader"/> instance created from a WAV stream. /// </summary> /// <param name="waveStream">The WAV stream. The data in the stream must include all headers that would be present in a WAV file.</param> /// <returns>The WaveData instance created from a WAV stream.</returns> /// <remarks> /// This method is similar to the <see cref="WaveDataReader.WaveDataReader(Stream)"/> constructor, /// however this method will first search the stream for a format chunk in order to set /// up the WaveData object with proper format info. /// </remarks> public static WaveDataReader FromStream(Stream waveStream) { RiffChunk riffChunk; WaveFormatChunk waveFormat = null; WaveDataReader waveData = null; while ((object)waveData == null) { riffChunk = RiffChunk.ReadNext(waveStream); switch (riffChunk.TypeID) { case RiffHeaderChunk.RiffTypeID: new RiffHeaderChunk(riffChunk, waveStream, "WAVE"); break; case WaveFormatChunk.RiffTypeID: waveFormat = new WaveFormatChunk(riffChunk, waveStream); break; case WaveDataChunk.RiffTypeID: waveData = new WaveDataReader(waveFormat, waveStream); break; default: // Skip unnecessary sections waveStream.Seek(riffChunk.ChunkSize, SeekOrigin.Current); break; } } return waveData; }