Я разрабатываю приложение Xamarin.Android , где мне нужно записать аудиофайл в формате WAV и одновременно отобразить соответствующую спектрограмму .
Я могу выполнять 2 задания отдельно , но не комбинировать их.
Я использую AudioRecord
для записи звука через микрофон:
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();
}
Запись файла выполняется в WriteAudioDataToFile()
и работает нормально:
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)
{
}
}
}
Я хотел бы выполнить другую задачу после записи файла:
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));
}
Если я позвоню OnNext()
из StartRecording()
, без записи файла , это нормально работает , и я получу ожидаемые значения для спектрограммы:
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();
}
}
Но так как мне нужно совместить как запись файла, так и другую задачу, я попытался переместить метод OnNext()
после записи файла:
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)
{
}
//...
}
Но это не работает , как и ожидалось:
- записанный файл кажется " поврежден ": звук "ускоряется", когда я его слышу
- значения, которые я получаю для спектрограммы не верны : проблема, похоже, связана с преобразованием
byte[]
в short[]
Я не понимаю, как управлять audioRecord.Read(data, 0, bufferSize)
:
- Мне нужно использовать
byte[]
для записи файла: fos.Write(data);
- Мне нужно использовать
short[]
для другой задачи
=> Каким должен быть лучший подход для достижения этой цели?
Edit:
Я уже пробовал эти подходы, но это ничего не изменило:
- создать второй поток, используя тот же AudioRecord для отображения спектрограммы
- создать второй поток, используя другую AudioRecord для отображения спектрограммы
Я также посмотрел, возможно ли записать файл после остановки AudioRecord, но это тоже не представляется возможным ...