/* ========================================================================
* Copyright (c) 2005-2026 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
* ======================================================================*/
using System;
using Opc.Ua;
namespace Quickstarts.ConsoleDataChannelAudio
{
///
/// Supplies complete sample-aligned opaque PCM messages from the existing generated melody.
/// Network lifecycle and buffer ownership belong to the common flow facade, not this audio source.
///
internal sealed class AudioStreamingSource
{
///
/// Renders the melody once without introducing a media codec or binary fixture.
///
public AudioStreamingSource(int frameMilliseconds)
{
m_pcm = MelodyGenerator.Render();
m_messageBytes = AudioFormat.BytesForDuration(frameMilliseconds);
}
///
/// Returns one complete immutable message, including across a melody loop boundary.
///
public ByteString GetMessage(int sequence)
{
byte[] message = new byte[m_messageBytes];
int offset = checked((int)((long)sequence * m_messageBytes % m_pcm.Length));
int written = 0;
while (written < message.Length)
{
int count = Math.Min(message.Length - written, m_pcm.Length - offset);
m_pcm.Span.Slice(offset, count).CopyTo(message.AsSpan(written));
written += count;
offset = (offset + count) % m_pcm.Length;
}
return new ByteString(message);
}
private readonly ByteString m_pcm;
private readonly int m_messageBytes;
}
}