I develop a Xamarin.Android app where I need to record an audio file in a .wav and to display the related spectrogram in the same time.
I'm able to perform the 2 tasks separately but not to combine them.
I use an AudioRecord
to record the sound through the microphone:
public async Task StartRecording() { audioRecord = new AudioRecord(AudioSource.Mic, 44100, ChannelIn.Mono, Android.Media.Encoding.Pcm16bit, bufferSize); if (audioRecord.State == State.Initialized) audioRecord.StartRecording(); isRecording = true; recordingThread = new System.Threading.Thread(new ThreadStart( WriteAudioDataToFile )); recordingThread.Start(); }
The file writing is done in WriteAudioDataToFile()
and works fine:
private void WriteAudioDataToFile() { byte[] data = new byte[bufferSize]; string filename = GetTempFilename(); FileOutputStream fos = null; try { fos = new FileOutputStream(filename); } catch (Java.IO.FileNotFoundException e) { } int read = 0; if (null != fos) { while (isRecording) { read = audioRecord.Read(data, 0, bufferSize); if ((int)RecordStatus.ErrorInvalidOperation != read) { try { fos.Write(data); } catch (Java.IO.IOException e) { } } } try { fos.Close(); } catch (Java.IO.IOException e) { } } }
I would like to do the other task after the file is written:
void OnNext() { short[] audioBuffer = new short[2048]; audioRecord.Read(audioBuffer, 0, audioBuffer.Length); int[] result = new int[audioBuffer.Length]; for (int i = 0; i < audioBuffer.Length; i++) { result[i] = (int)audioBuffer[i]; } samplesUpdated(this, new SamplesUpdatedEventArgs(result)); }
If I call OnNext()
from StartRecording()
, without writing the file this works fine and I get the expected values for the spectrogram:
public async Task StartRecording() { audioRecord = new AudioRecord(AudioSource.Mic, 44100, ChannelIn.Mono, Android.Media.Encoding.Pcm16bit, bufferSize); if (audioRecord.State == State.Initialized) audioRecord.StartRecording(); isRecording = true; while (audioRecord.RecordingState == RecordState.Recording) { OnNext(); } }
But as I need to combine both file writing and other task, I tried to move the OnNext()
method after the file writing:
private void WriteAudioDataToFile() { //... try { fos.Write(data); short[] dataShort = new short[bufferSize]; dataShort = Array.ConvertAll(data, d => (short)d); int[] result = new int[dataShort.Length]; for (int i = 0; i < dataShort.Length; i++) { result[i] = (int)dataShort[i]; } samplesUpdated(this, new SamplesUpdatedEventArgs(result)); } catch (Java.IO.IOException e) { } //... }
But this doesn't work at all as expected:
byte[]
to short[]
conversionI don't see how to manage audioRecord.Read(data, 0, bufferSize)
:
byte[]
for the file writing: fos.Write(data);
short[]
for the other taskI've already tried these approaches but this didn't change anything:
I've also looked if it is possible to wirte the file after the AudioRecord has stopped, but it doesn't seem possible too...
=> What should be the better approach to achieve this?
Answers
Hi @Pierre-ChristopheDus ,
You could try to use BitConverter to convert
byte
toshort
. Or you could use Convert.ToByte() to makeshort
convert tobyte
.Does the recorded file still corrupted after you using another thread? Could you provide a demo project?
Hi @BillyLiu
I've already tried to convert
byte
toshort
, this didn't work. I think that the problem comes that there are parallel treatments:SamplesUpdatedEventArgs()
You can found the demo project link there.
But you will have to create a SciChart trial license to launch the app....