public static void WriteWavHeader(Stream output, AudioFormatEx audioFormat, uint rawDataLength) { if (audioFormat == null) throw new ArgumentException("No audio available."); //this may occur if there is no audio hardware if (audioFormat.WaveFormat != WaveFormatType.Pcm) throw new ArgumentException("Only PCM coding is supported."); var bwOutput = new BinaryWriter(output); // Write down the WAV header. // Refer to http://technology.niagarac.on.ca/courses/ctec1631/WavFileFormat.html (broken link: see https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ instead) // for details on the format. // Note that we use ToCharArray() when writing fixed strings // to force using the char[] overload because // Write(string) writes the string prefixed by its length. // -- RIFF chunk bwOutput.Write("RIFF".ToCharArray()); // Total Length Of Package To Follow // Computed as data length plus the header length without the data // we have written so far and this data (44 - 4 ("RIFF") - 4 (this number)) bwOutput.Write(rawDataLength + WAV_HEADER_SIZE - 4 - 4); bwOutput.Write("WAVE".ToCharArray()); //RIFF data type // -- FORMAT chunk bwOutput.Write("fmt ".ToCharArray()); // Length Of FORMAT Chunk (Binary, always 0x10) bwOutput.Write((uint) 0x10); // Always 0x01 bwOutput.Write((ushort) 0x01); // Channel Numbers (Always 0x01=Mono, 0x02=Stereo) bwOutput.Write((ushort) audioFormat.Channels); // Sample Rate (Binary, in Hz) bwOutput.Write((uint) audioFormat.SamplesPerSecond); // Calculate Bytes/Sample and Bytes/Second var bytesPerSample = (ushort) (audioFormat.BitsPerSample*audioFormat.Channels/8); // 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo var bytesPerSecond = (uint) (bytesPerSample*audioFormat.SamplesPerSecond); // Bytes Per Second bwOutput.Write(bytesPerSecond); // Bytes Per Sample bwOutput.Write(bytesPerSample); // Bits Per Sample bwOutput.Write((ushort) audioFormat.BitsPerSample); // -- DATA chunk bwOutput.Write("data".ToCharArray()); // Length Of Data To Follow bwOutput.Write(rawDataLength); }
public static void SavePcmToWav(Stream[] rawData, Stream output, AudioFormatEx audioFormat, uint offset = 0, long maxLength = -1) //Saves WAV concatenating multiple raw data streams (each optionally starting at offset and cropped at maxLength) { // Get total raw data stream length uint len = 0; foreach (Stream s in rawData) { uint lengthAfterOffset = (uint) s.Length - offset; len += (lengthAfterOffset <= maxLength) ? lengthAfterOffset : (uint) maxLength; } // Write WAV header WriteWavHeader(output, audioFormat, len); // Write raw PCM data streams in sequence foreach (Stream s in rawData) WriteRawData(s, output, offset, maxLength); }
public static AudioFormat PickAudioFormat(ReadOnlyCollection<AudioFormat> audioFormats, AudioFormatEx desiredFormat) { return audioFormats.FirstOrDefault(audioFormat => desiredFormat.Equals(audioFormat)); }
public static void SavePcmToWav(Stream rawData, Stream output, AudioFormatEx audioFormat, uint offset = 0, long maxLength = -1) //TODO: add optional maxSeconds parameter { WriteWavHeader(output, audioFormat, (uint) rawData.Length); WriteRawData(rawData, output, offset, maxLength); //raw PCM data }
/// <summary> /// Determines whether the specified <see cref="System.Object" }, is equal to this instance. /// </summary> /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param> /// <returns> /// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>. /// </returns> public override bool Equals(object obj) { if (obj == null) return false; AudioFormatEx formatObj = null; if (obj.GetType() == typeof (AudioFormatEx)) formatObj = (AudioFormatEx) obj; else if (obj.GetType() == typeof (AudioFormat)) formatObj = new AudioFormatEx((AudioFormat) obj); else if (obj.GetType() == typeof (WAVEFORMATEX)) formatObj = new AudioFormatEx((WAVEFORMATEX) obj); return (_format == formatObj._format) && (_bitsPerSample == formatObj._bitsPerSample) && (_channels == formatObj._channels) && (_samplesPerSecond == formatObj._samplesPerSecond); }