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;
}
}
[Serializable]
public class FilmShow
{
[Serializable]
public class Place
{
public Place() { }
public int? UserId { get; set; }
public bool IsReserved { get; set; }
}
[Serializable]
public class Row
{
public Row() { }
public Place[] Places { get; set; }
}
public DateTime Date { get; set; }
public string Name { get; set; }
public Row[] Rows { get; set; }
public FilmShow()
{
}
public FilmShow(DateTime date, string name, int row, int column)
{
Date = date;
Name = name;
Rows = new Row[row];
for (var i = 0; i < Rows.Length; i++)
{
var item = new Row() { Places = new Place[column] };
for (var j = 0; j < item.Places.Length; j++)
{
item.Places[j] = new Place();
}
Rows[i] = item;
}
}
public static void Save(FilmShow filmShow, string path)
{
var formatter = new XmlSerializer(typeof(FilmShow));
using var fs = new FileStream(path, FileMode.OpenOrCreate);
formatter.Serialize(fs, filmShow);
}
public static FilmShow Load(string path)
{
var formatter = new XmlSerializer(typeof(FilmShow));
using var fs = new FileStream(path, FileMode.OpenOrCreate);
return (FilmShow)formatter.Deserialize(fs);
}
}