Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make recording in-place and fix the WAV header on the Android platform #151

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 21 additions & 37 deletions src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ partial class AudioRecorder : IAudioRecorder
public bool IsRecording => audioRecord?.RecordingState == RecordState.Recording;

AudioRecord? audioRecord;
string? rawFilePath;
string? audioFilePath;

int bufferSize;
Expand Down Expand Up @@ -101,20 +100,7 @@ public Task<IAudioSource> StopAsync()
throw new InvalidOperationException("'audioFilePath' is null, this really should not happen.");
}

CopyWaveFile(rawFilePath, audioFilePath);

try
{
// lets delete the temp file with the raw data, after we have created the WAVE file
if (System.IO.File.Exists(rawFilePath))
{
System.IO.File.Delete(rawFilePath);
}
}
catch
{
Trace.TraceWarning("delete raw wav file failed.");
}
UpdateAudioHeaderToFile();

return Task.FromResult(GetRecording());
}
Expand Down Expand Up @@ -145,13 +131,11 @@ void WriteAudioDataToFile()
{
var data = new byte[bufferSize];

rawFilePath = GetTempFilePath();

FileOutputStream? outputStream;

try
{
outputStream = new FileOutputStream(rawFilePath);
outputStream = new FileOutputStream(audioFilePath);
}
catch (Exception ex)
{
Expand All @@ -160,6 +144,9 @@ void WriteAudioDataToFile()

if (audioRecord is not null && outputStream is not null)
{
var header = GetWaveFileHeader(0, 0, sampleRate, channels, bitDepth);
outputStream.Write(header, 0, 44);

while (audioRecord.RecordingState == RecordState.Recording)
{
var read = audioRecord.Read(data, 0, bufferSize);
Expand All @@ -170,43 +157,40 @@ void WriteAudioDataToFile()
}
}

void CopyWaveFile(string? sourcePath, string destinationPath)
void UpdateAudioHeaderToFile()
{
long byteRate = sampleRate * bitDepth * channels / 8;

var data = new byte[bufferSize];

try
{
FileInputStream inputStream = new(sourcePath);
FileOutputStream outputStream = new(destinationPath);
RandomAccessFile randomAccessFile = new(audioFilePath, "rw");

if (inputStream?.Channel is not null)
if (randomAccessFile is not null)
{
var totalAudioLength = inputStream.Channel.Size();
var totalAudioLength = randomAccessFile.Length();
var totalDataLength = totalAudioLength + 36;

WriteWaveFileHeader(outputStream, totalAudioLength, totalDataLength, sampleRate, channels, byteRate);
var header = GetWaveFileHeader(totalAudioLength, totalDataLength, sampleRate, channels, bitDepth);

while (inputStream.Read(data) != -1)
{
outputStream.Write(data);
}
randomAccessFile.Seek(0);
randomAccessFile.Write(header, 0, 44);

inputStream.Close();
outputStream.Close();
randomAccessFile.Close();
}
}
catch (Exception ex)
{
// Trace the exception
Trace.WriteLine($"An error occurred while copying the wave file: {ex.Message}");
Trace.WriteLine($"An error occurred while updating the wave header: {ex.Message}");
Trace.WriteLine($"Stack Trace: {ex.StackTrace}");
}
}

static void WriteWaveFileHeader(FileOutputStream outputStream, long audioLength, long dataLength, long sampleRate, int channels, long byteRate)
static byte[] GetWaveFileHeader(long audioLength, long dataLength, long sampleRate, int channels, int bitDepth)
{
int blockAlign = (int)(channels * (bitDepth / 8));
long byteRate = sampleRate * blockAlign;

byte[] header = new byte[44];

header[0] = Convert.ToByte('R'); // RIFF/WAVE header
Expand Down Expand Up @@ -241,9 +225,9 @@ static void WriteWaveFileHeader(FileOutputStream outputStream, long audioLength,
header[29] = (byte)((byteRate >> 8) & 0xff);
header[30] = (byte)((byteRate >> 16) & 0xff);
header[31] = (byte)((byteRate >> 24) & 0xff);
header[32] = (byte)(2 * 16 / 8); // block align
header[32] = (byte)(blockAlign); // block align
header[33] = 0;
header[34] = Convert.ToByte(16); // bits per sample
header[34] = Convert.ToByte(bitDepth); // bits per sample
header[35] = 0;
header[36] = Convert.ToByte('d');
header[37] = Convert.ToByte('a');
Expand All @@ -254,7 +238,7 @@ static void WriteWaveFileHeader(FileOutputStream outputStream, long audioLength,
header[42] = (byte)((audioLength >> 16) & 0xff);
header[43] = (byte)((audioLength >> 24) & 0xff);

outputStream.Write(header, 0, 44);
return header;
}

static Android.Media.Encoding SharedEncodingToAndroidEncoding(Encoding type, BitDepth bitDepth, bool throwIfNotSupported)
Expand Down