Files
meeting-assistant/MeetingAssistant.Tests/AudioMixingTests.cs
T
2026-05-20 02:06:16 +02:00

72 lines
2.0 KiB
C#

using MeetingAssistant.Recording;
using Microsoft.Extensions.Logging.Abstractions;
namespace MeetingAssistant.Tests;
public sealed class AudioMixingTests
{
[Fact]
public async Task CompositeAudioSourceMixesMicrophoneAndSystemAudioIntoOnePcmStream()
{
var microphone = new FixedAudioSource(Pcm16(10_000));
var system = new FixedAudioSource(Pcm16(20_000));
var source = new CompositeMeetingAudioSource(
microphone,
system,
NullLogger<CompositeMeetingAudioSource>.Instance);
var chunks = await ReadChunks(source);
Assert.Single(chunks);
Assert.Equal(30_000, BitConverter.ToInt16(chunks[0].Pcm));
}
[Fact]
public async Task CompositeAudioSourceClampsMixedSamples()
{
var microphone = new FixedAudioSource(Pcm16(30_000));
var system = new FixedAudioSource(Pcm16(10_000));
var source = new CompositeMeetingAudioSource(
microphone,
system,
NullLogger<CompositeMeetingAudioSource>.Instance);
var chunks = await ReadChunks(source);
Assert.Equal(short.MaxValue, BitConverter.ToInt16(chunks[0].Pcm));
}
private static async Task<IReadOnlyList<AudioChunk>> ReadChunks(IMeetingAudioSource source)
{
var chunks = new List<AudioChunk>();
await foreach (var chunk in source.CaptureAsync(CancellationToken.None))
{
chunks.Add(chunk);
}
return chunks;
}
private static byte[] Pcm16(short sample)
{
return BitConverter.GetBytes(sample);
}
private sealed class FixedAudioSource : IMeetingAudioSource
{
private readonly AudioChunk chunk;
public FixedAudioSource(byte[] pcm)
{
chunk = new AudioChunk(pcm, 16000, 1);
}
public async IAsyncEnumerable<AudioChunk> CaptureAsync(
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken)
{
await Task.Yield();
yield return chunk;
}
}
}