Public Access
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using MeetingAssistant.Transcription;
|
||||
using NAudio.Wave;
|
||||
|
||||
namespace MeetingAssistant.Speakers;
|
||||
|
||||
internal static class SpeakerCompositeWav
|
||||
{
|
||||
public static WaveFileReader? OpenFirstReadableWave(IEnumerable<byte[]> snippets)
|
||||
{
|
||||
foreach (var bytes in snippets)
|
||||
{
|
||||
if (bytes.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new WaveFileReader(new MemoryStream(bytes));
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TimeSegment? AppendSnippet(
|
||||
WaveFileWriter writer,
|
||||
WaveFormat targetFormat,
|
||||
byte[] snippet,
|
||||
TimeSpan start)
|
||||
{
|
||||
if (snippet.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using var reader = new WaveFileReader(new MemoryStream(snippet));
|
||||
if (!WaveFormatsMatch(reader.WaveFormat, targetFormat))
|
||||
{
|
||||
throw new InvalidDataException("Speaker identity snippets must use the same WAV format.");
|
||||
}
|
||||
|
||||
reader.CopyTo(writer);
|
||||
return new TimeSegment(start, start + reader.TotalTime);
|
||||
}
|
||||
|
||||
public static void WriteSilence(
|
||||
WaveFileWriter writer,
|
||||
WaveFormat format,
|
||||
TimeSpan duration)
|
||||
{
|
||||
if (duration <= TimeSpan.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bytes = new byte[(int)(format.AverageBytesPerSecond * duration.TotalSeconds)];
|
||||
writer.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
public static string? FindBestSpeaker(
|
||||
TimeSegment segment,
|
||||
IReadOnlyList<TranscriptionSegment> segments)
|
||||
{
|
||||
var bestOverlap = 0d;
|
||||
string? bestSpeaker = null;
|
||||
foreach (var transcriptSegment in segments)
|
||||
{
|
||||
var overlap = Math.Min(segment.End.TotalSeconds, transcriptSegment.End.TotalSeconds)
|
||||
- Math.Max(segment.Start.TotalSeconds, transcriptSegment.Start.TotalSeconds);
|
||||
if (overlap > bestOverlap)
|
||||
{
|
||||
bestOverlap = overlap;
|
||||
bestSpeaker = transcriptSegment.Speaker;
|
||||
}
|
||||
}
|
||||
|
||||
return bestSpeaker;
|
||||
}
|
||||
|
||||
public static void TryDelete(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static bool WaveFormatsMatch(WaveFormat left, WaveFormat right)
|
||||
{
|
||||
return left.Encoding == right.Encoding
|
||||
&& left.SampleRate == right.SampleRate
|
||||
&& left.Channels == right.Channels
|
||||
&& left.BitsPerSample == right.BitsPerSample;
|
||||
}
|
||||
}
|
||||
|
||||
internal readonly record struct TimeSegment(TimeSpan Start, TimeSpan End);
|
||||
Reference in New Issue
Block a user