/// <summary> /// WaveStream to resample using the DMO Resampler /// </summary> /// <param name="inputProvider">Input Stream</param> /// <param name="outputFormat">Desired Output Format</param> public ResamplerDmoStream(IWaveProvider inputProvider, WaveFormat outputFormat) { this.inputProvider = inputProvider; inputStream = inputProvider as WaveStream; this.outputFormat = outputFormat; resampler = new Resampler(); if (!resampler.MediaObject.SupportsInputWaveFormat(0, inputStream.WaveFormat)) { throw new ArgumentException("Unsupported Input Stream format", "inputStream"); } resampler.MediaObject.SetInputWaveFormat(0, inputStream.WaveFormat); if (!resampler.MediaObject.SupportsOutputWaveFormat(0, outputFormat)) { throw new ArgumentException("Unsupported Output Stream format", "outputStream"); } resampler.MediaObject.SetOutputWaveFormat(0, outputFormat); if (inputStream != null) { position = InputToOutputPosition(inputStream.Position); } inputMediaBuffer = new MediaBuffer(inputProvider.WaveFormat.AverageBytesPerSecond); outputBuffer = new DmoOutputDataBuffer(outputFormat.AverageBytesPerSecond); }
/// <summary> /// Creates a stream that can convert to PCM /// </summary> /// <param name="sourceStream">The source stream</param> /// <returns>A PCM stream</returns> public static WaveStream CreatePcmStream(WaveStream sourceStream) { if (sourceStream.WaveFormat.Encoding == WaveFormatEncoding.Pcm) { return sourceStream; } WaveFormat pcmFormat = AcmStream.SuggestPcmFormat(sourceStream.WaveFormat); return new WaveFormatConversionStream(pcmFormat, sourceStream); }
/// <summary> /// Create a new simple compressor stream /// </summary> /// <param name="sourceStream">Source stream</param> public SimpleCompressorStream(WaveStream sourceStream) { this.sourceStream = sourceStream; channels = sourceStream.WaveFormat.Channels; bytesPerSample = sourceStream.WaveFormat.BitsPerSample/8; simpleCompressor = new SimpleCompressor(5.0, 10.0, sourceStream.WaveFormat.SampleRate); simpleCompressor.Threshold = 16; simpleCompressor.Ratio = 6; simpleCompressor.MakeUpGain = 16; }
/// <summary> /// Create a new WaveFormat conversion stream /// </summary> /// <param name="targetFormat">Desired output format</param> /// <param name="sourceStream">Source stream</param> public WaveFormatConversionStream(WaveFormat targetFormat, WaveStream sourceStream) { this.sourceStream = sourceStream; this.targetFormat = targetFormat; conversionStream = new AcmStream(sourceStream.WaveFormat, targetFormat); // work out how many bytes the entire input stream will convert to length = SourceToDest((int) sourceStream.Length); blockAlign = SourceToDest(sourceStream.BlockAlign); position = 0; }
/// <summary> /// Creates a new Wave32To16Stream /// </summary> /// <param name="sourceStream">the source stream</param> public Wave32To16Stream(WaveStream sourceStream) { if (sourceStream.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat) throw new ApplicationException("Only 32 bit Floating point supported"); if (sourceStream.WaveFormat.BitsPerSample != 32) throw new ApplicationException("Only 32 bit Floating point supported"); waveFormat = new WaveFormat(sourceStream.WaveFormat.SampleRate, 16, sourceStream.WaveFormat.Channels); volume = 1.0f; this.sourceStream = sourceStream; length = sourceStream.Length/2; position = sourceStream.Position/2; }
/// <summary> /// Creates a new WaveOffsetStream /// </summary> /// <param name="sourceStream">the source stream</param> /// <param name="startTime">the time at which we should start reading from the source stream</param> /// <param name="sourceOffset">amount to trim off the front of the source stream</param> /// <param name="sourceLength">length of time to play from source stream</param> public WaveOffsetStream(WaveStream sourceStream, TimeSpan startTime, TimeSpan sourceOffset, TimeSpan sourceLength) { if (sourceStream.WaveFormat.Encoding != WaveFormatEncoding.Pcm) throw new ApplicationException("Only PCM supported"); // TODO: add support for IEEE float + perhaps some others - // anything with a fixed bytes per sample this.sourceStream = sourceStream; position = 0; bytesPerSample = (sourceStream.WaveFormat.BitsPerSample/8)*sourceStream.WaveFormat.Channels; StartTime = startTime; SourceOffset = sourceOffset; SourceLength = sourceLength; }
/// <summary> /// Creates a new WaveChannel32 /// </summary> /// <param name="sourceStream">the source stream</param> /// <param name="volume">stream volume (1 is 0dB)</param> /// <param name="pan">pan control (-1 to 1)</param> public WaveChannel32(WaveStream sourceStream, float volume, float pan) { PadWithZeroes = true; if (sourceStream.WaveFormat.Encoding != WaveFormatEncoding.Pcm) throw new ApplicationException("Only PCM supported"); if (sourceStream.WaveFormat.BitsPerSample != 16) throw new ApplicationException("Only 16 bit audio supported"); // always outputs stereo 32 bit waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(sourceStream.WaveFormat.SampleRate, 2); destBytesPerSample = 8; // includes stereo factoring this.sourceStream = sourceStream; this.volume = volume; this.pan = pan; sourceBytesPerSample = sourceStream.WaveFormat.Channels*sourceStream.WaveFormat.BitsPerSample/8; length = SourceToDest(sourceStream.Length); position = 0; }
/// <summary> /// Disposes this stream /// </summary> /// <param name="disposing">true if the user called this</param> protected override void Dispose(bool disposing) { if (disposing) { // Release managed resources. if (sourceStream != null) { sourceStream.Dispose(); sourceStream = null; } } // Release unmanaged resources. // Set large fields to null. // Call Dispose on your base class. base.Dispose(disposing); }
/// <summary> /// Disposes this stream /// </summary> /// <param name="disposing">true if the user called this</param> protected override void Dispose(bool disposing) { if (disposing) { // Release managed resources. if (conversionStream != null) { conversionStream.Dispose(); conversionStream = null; } if (sourceStream != null) { sourceStream.Dispose(); sourceStream = null; } } else { Debug.Assert(false, "WaveFormatConversionStream was not disposed"); } // Release unmanaged resources. // Set large fields to null. // Call Dispose on your base class. base.Dispose(disposing); }
/// <summary> /// Disposes this WaveStream /// </summary> protected override void Dispose(bool disposing) { if (disposing) { if (sourceStream != null) { sourceStream.Dispose(); sourceStream = null; } } base.Dispose(disposing); }
/// <summary> /// Creates a WaveOffsetStream with default settings (no offset or pre-delay, /// and whole length of source stream) /// </summary> /// <param name="sourceStream">The source stream</param> public WaveOffsetStream(WaveStream sourceStream) : this(sourceStream, TimeSpan.Zero, TimeSpan.Zero, sourceStream.TotalTime) { }
/// <summary> /// Disposes this WaveStream /// </summary> protected override void Dispose(bool disposing) { if (disposing) { if (sourceStream != null) { sourceStream.Dispose(); sourceStream = null; } } else { Debug.Assert(false, "WaveOffsetStream was not Disposed"); } base.Dispose(disposing); }
/// <summary> /// Creates a new BlockAlignReductionStream /// </summary> /// <param name="sourceStream">the input stream</param> public BlockAlignReductionStream(WaveStream sourceStream) { this.sourceStream = sourceStream; circularBuffer = new CircularBuffer(sourceStream.WaveFormat.AverageBytesPerSecond*4); }
/// <summary> /// Disposes this WaveStream /// </summary> protected override void Dispose(bool disposing) { if (disposing) { if (sourceStream != null) { sourceStream.Dispose(); sourceStream = null; } } else { Debug.Assert(false, "BlockAlignReductionStream was not Disposed"); } base.Dispose(disposing); }
/// <summary> /// Creates a WaveChannel32 with default settings /// </summary> /// <param name="sourceStream">The source stream</param> public WaveChannel32(WaveStream sourceStream) : this(sourceStream, 1.0f, 0.0f) { }
/// <summary> /// Add a new input to the mixer /// </summary> /// <param name="waveStream">The wave input to add</param> public void AddInputStream(WaveStream waveStream) { if (waveStream.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat) throw new ArgumentException("Must be IEEE floating point", "waveStream.WaveFormat"); if (waveStream.WaveFormat.BitsPerSample != 32) throw new ArgumentException("Only 32 bit audio currently supported", "waveStream.WaveFormat"); if (inputStreams.Count == 0) { // first one - set the format int sampleRate = waveStream.WaveFormat.SampleRate; int channels = waveStream.WaveFormat.Channels; waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels); } else { if (!waveStream.WaveFormat.Equals(waveFormat)) throw new ArgumentException("All incoming channels must have the same format", "inputStreams.WaveFormat"); } lock (this) { inputStreams.Add(waveStream); length = Math.Max(length, waveStream.Length); // get to the right point in this input file Position = Position; } }
/// <summary> /// Remove a WaveStream from the mixer /// </summary> /// <param name="waveStream">waveStream to remove</param> public void RemoveInputStream(WaveStream waveStream) { lock (this) { if (inputStreams.Remove(waveStream)) { // recalculate the length length = 0; foreach (WaveStream inputStream in inputStreams) { length = Math.Max(length, waveStream.Length); } } } }
/// <summary> /// Creates a Wave file by reading all the data from a WaveStream /// </summary> /// <param name="filename">The filename to use</param> /// <param name="stream">The source WaveStream</param> public static void CreateWaveFile(string filename, WaveStream stream) { using (var writer = new WaveFileWriter(filename, stream.WaveFormat)) { var buffer = new byte[stream.WaveFormat.SampleRate*stream.WaveFormat.Channels*16]; while (true) { int bytesRead = stream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; writer.WriteData(buffer, 0, bytesRead); } } }