Как добиться воспроизведения PCM на .NET Android с помощью AudioTrackC#

Место общения программистов C#
Anonymous
Как добиться воспроизведения PCM на .NET Android с помощью AudioTrack

Сообщение Anonymous »

Я пытаюсь реализовать простой проигрыватель PCM для некоторых синтезаторных нот, которые должны воспроизводиться независимо.

Код: Выделить всё

  public void Play()
{
var playToken = new CancellationTokenSource();
playToken.CancelAfter(3000);
Task.Run(() =>
{
var left = new float[1024]; //smaller buffer because rendering to larger ones causes android to freeze
var right = new float[1024];

var minBufferSize = AudioTrack.GetMinBufferSize(
SAMPLE_RATE,
ChannelOut.Stereo,
AndroidMedia.Encoding.Pcm16bit);

var audioAttributes = new AudioAttributes.Builder()
.SetUsage(AudioUsageKind.Media)
.SetContentType(AudioContentType.Music)
.Build()!;

var audioFormat = new AudioFormat.Builder()
.SetEncoding(AndroidMedia.Encoding.Pcm16bit)
.SetSampleRate(SAMPLE_RATE)
.SetChannelMask(ChannelOut.Stereo)
.Build()!;

_audioTrack = new AudioTrack.Builder()
.SetAudioAttributes(audioAttributes)
.SetAudioFormat(audioFormat)
.SetTransferMode(AudioTrackMode.Stream)
.SetBufferSizeInBytes(minBufferSize)
.Build();

_audioTrack.Play();

_inner.NoteOn(0, 60, 100); //generate noteon event

while (!playToken.IsCancellationRequested)
{
lock(mutex){
_inner.Render(left, right); //render to left and right
var pcm = Helper.InterlacePcm(left, right); //interlace to one buffer
_audioTrack.Write(pcm, 0, pcm.Length); //write to AudioTrack sync
}
}
});
}

public static short[] InterlacePcm(float[] left, float[] right)
{
var pcm = new short[left.Length * 2];
for (int i = 0; i < left.Length; i++)
{
pcm[i * 2] = (short)(Math.Clamp(left[i], -1f, 1f) * short.MaxValue);
pcm[i * 2 + 1] = (short)(Math.Clamp(right[i], -1f, 1f) * short.MaxValue);
}

return pcm;
}
Предполагается, что мы вызываем Play несколько раз, когда захотим, чтобы каждый вызов создавал собственный экземпляр AudioTrack. Synth _inner — это экземпляр MetylSynth, генерирующий простую форму сигнала PCM. Это ведет себя беспорядочно: звук агрессивно буферизуется, заикается при последовательных вызовах Play с любым интервалом. Любая помощь в этом будет оценена по достоинству.

Вернуться в «C#»