diff --git a/FFMpegCore/Extend/PcmAudioSampleWrapper.cs b/FFMpegCore/Extend/PcmAudioSampleWrapper.cs
new file mode 100644
index 0000000..d67038b
--- /dev/null
+++ b/FFMpegCore/Extend/PcmAudioSampleWrapper.cs
@@ -0,0 +1,27 @@
+using FFMpegCore.Pipes;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+public class PcmAudioSampleWrapper : IAudioSample
+{
+ //This could actually be short or int, but copies would be inefficient.
+ //Handling bytes lets the user decide on the conversion, and abstract the library
+ //from handling shorts, unsigned shorts, integers, unsigned integers and floats.
+ private readonly byte[] _sample;
+
+ public PcmAudioSampleWrapper(byte[] sample)
+ {
+ _sample = sample;
+ }
+
+ public void Serialize(Stream stream)
+ {
+ stream.Write(_sample, 0, _sample.Length);
+ }
+
+ public async Task SerializeAsync(Stream stream, CancellationToken token)
+ {
+ await stream.WriteAsync(_sample, 0, _sample.Length, token);
+ }
+}
diff --git a/FFMpegCore/FFMpeg/Pipes/IAudioSample.cs b/FFMpegCore/FFMpeg/Pipes/IAudioSample.cs
new file mode 100644
index 0000000..c7dea65
--- /dev/null
+++ b/FFMpegCore/FFMpeg/Pipes/IAudioSample.cs
@@ -0,0 +1,16 @@
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FFMpegCore.Pipes
+{
+ ///
+ /// Interface for Audio sample
+ ///
+ public interface IAudioSample
+ {
+ void Serialize(Stream stream);
+
+ Task SerializeAsync(Stream stream, CancellationToken token);
+ }
+}
diff --git a/FFMpegCore/FFMpeg/Pipes/RawAudioPipeSource.cs b/FFMpegCore/FFMpeg/Pipes/RawAudioPipeSource.cs
new file mode 100644
index 0000000..40b964c
--- /dev/null
+++ b/FFMpegCore/FFMpeg/Pipes/RawAudioPipeSource.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FFMpegCore.Pipes
+{
+ ///
+ /// Implementation of for a raw audio stream that is gathered from
+ ///
+ public class RawAudioPipeSource : IPipeSource
+ {
+ private readonly IEnumerator _sampleEnumerator;
+
+ public string Format { get; set; } = "s16le";
+ public uint SampleRate { get; set; } = 8000;
+ public uint Channels { get; set; } = 1;
+
+ public RawAudioPipeSource(IEnumerator sampleEnumerator)
+ {
+ _sampleEnumerator = sampleEnumerator;
+ }
+
+ public RawAudioPipeSource(IEnumerable sampleEnumerator)
+ : this(sampleEnumerator.GetEnumerator()) { }
+
+ public string GetStreamArguments()
+ {
+ return $"-f {Format} -ar {SampleRate} -ac {Channels}";
+ }
+
+ public async Task WriteAsync(Stream outputStream, CancellationToken cancellationToken)
+ {
+ if (_sampleEnumerator.Current != null)
+ {
+ await _sampleEnumerator.Current.SerializeAsync(outputStream, cancellationToken).ConfigureAwait(false);
+ }
+
+ while (_sampleEnumerator.MoveNext())
+ {
+ await _sampleEnumerator.Current!.SerializeAsync(outputStream, cancellationToken).ConfigureAwait(false);
+ }
+ }
+ }
+}