Public Access
72 lines
2.0 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|