То что примерно получилось. Громкость сэмпла прокидывается вверх приложения, дальше анализ идет по текущим данным.
using Android.Media;
using Android.Util;
using PeakMeter.Code;
using System;
using System.Threading;
[assembly: Xamarin.Forms.Dependency(typeof(AudioRecorder))]
// ReSharper disable once CheckNamespace
namespace PeakMeter.Code
{
public class AudioRecorder : IAudioRecorder
{
private AudioRecord _audioRecord;
public const string TAG = "PeakMeter";
private float _maxPeak = 0f;
private bool _shouldContinue;
public void Start()
{
_shouldContinue = true;
var thread = new Thread(new ThreadStart(ThreadWorker));
thread.Start();
}
private void ThreadWorker()
{
const int sampleRate = 44100;
const ChannelIn channelConfig = ChannelIn.Mono;
const Encoding audioFormat = Encoding.Pcm16bit;
var bufferSize = AudioRecord.GetMinBufferSize(sampleRate,
channelConfig,
audioFormat);
if (bufferSize == (int)TrackStatus.Error || bufferSize == (int)TrackStatus.ErrorBadValue)
{
bufferSize = sampleRate * 2;
}
Log.Debug(TAG, $"bufferSize = {bufferSize}");
var audioBuffer = new short[bufferSize / 2];
_audioRecord = new AudioRecord(AudioSource.Default,
sampleRate,
channelConfig,
audioFormat,
bufferSize);
if (_audioRecord.State != State.Initialized)
{
Log.Error(TAG, "Audio Record can't initialize!");
return;
}
_audioRecord.StartRecording();
Log.Verbose(TAG, "Start recording");
long shortsRead = 0;
while (_shouldContinue)
{
var numberOfShort = _audioRecord.Read(audioBuffer, 0, audioBuffer.Length);
shortsRead += numberOfShort;
foreach (var s in audioBuffer)
{
if (s > _maxPeak)
NewPeak?.Invoke(this, (float)s);
_maxPeak = Math.Max(_maxPeak, s);
}
PeakLevel?.Invoke(this, _maxPeak);
}
_audioRecord.Stop();
_audioRecord.Release();
_audioRecord = null;
Log.Verbose(TAG, $"Recording stopped. Samples read: {shortsRead}");
}
public void Stop()
{
_shouldContinue = false;
}
public event EventHandler<float> PeakLevel;
public event EventHandler<float> NewPeak;
}
}