Playback: append OutputStream playback of recorded buffer

This commit is contained in:
2026-06-12 10:00:59 +00:00
parent e2bd845abe
commit 87a85db38d
+56
View File
@@ -85,6 +85,62 @@ try
WavWriter.Write(OutWav, buf, SampleRate); WavWriter.Write(OutWav, buf, SampleRate);
Console.WriteLine($"Wrote {OutWav} ({buf.Length} frames @ {SampleRate} Hz)"); Console.WriteLine($"Wrote {OutWav} ({buf.Length} frames @ {SampleRate} Hz)");
Console.WriteLine($"Playing back through device {device}");
int playOffset = 0;
object playGate = new();
var doneEvent = new ManualResetEventSlim(false);
var outParams = new StreamParameters
{
device = device,
channelCount = Channels,
sampleFormat = SampleFormat.Int16,
suggestedLatency = PortAudio.GetDeviceInfo(device).defaultLowOutputLatency,
hostApiSpecificStreamInfo = IntPtr.Zero,
};
Stream.Callback playCb = (IntPtr _, IntPtr output, uint frameCount,
ref StreamCallbackTimeInfo _2, StreamCallbackFlags _3, IntPtr _4) =>
{
lock (playGate)
{
int remaining = buf.Length - playOffset;
int take = (int)Math.Min(frameCount, (uint)remaining);
int silence = (int)frameCount - take;
unsafe
{
short* dst = (short*)output.ToPointer();
if (take > 0)
{
fixed (short* src = &buf[playOffset])
Buffer.MemoryCopy(src, dst, take * sizeof(short), take * sizeof(short));
playOffset += take;
}
if (silence > 0)
{
for (int i = take; i < frameCount; i++) dst[i] = 0;
}
}
if (playOffset >= buf.Length)
{
doneEvent.Set();
return StreamCallbackResult.Complete;
}
}
return StreamCallbackResult.Continue;
};
using var playStream = new Stream(
null, outParams, SampleRate, BlockFrames, StreamFlags.NoFlag, playCb, IntPtr.Zero);
playStream.Start();
doneEvent.Wait();
// Give PortAudio a moment to drain the device buffer before Stop().
Thread.Sleep(200);
playStream.Stop();
} }
finally finally
{ {