Подтвердить что ты не робот

Воспроизведение звука, поступающего с микрофона в режиме реального времени

Я пытаюсь заставить приложение записывать звук, поступающий с микрофона, и воспроизводить его обратно (примерно) в режиме реального времени, однако без успеха.

Я использую классы AudioRecord и AudioTrack для записи и воспроизведения, соответственно. Я пробовал разные подходы, я пытался записать входящий звук и записать его в файл, и он работал нормально. Я также пытался воспроизвести звук из этого файла ПОСЛЕ с помощью AudioTrack, и он тоже работал отлично. Проблема в том, что я пытаюсь воспроизвести звук в режиме реального времени, вместо того, чтобы читать файл после его написания.

Вот код:

//variables
private int audioSource = MediaRecorder.AudioSource.MIC;
private int samplingRate = 44100; /* in Hz*/
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private int bufferSize = AudioRecord.getMinBufferSize(samplingRate, channelConfig, audioFormat);
private int sampleNumBits = 16;
private int numChannels = 1;

// …

AudioRecord recorder = new AudioRecord(audioSource, samplingRate, channelConfig, audioFormat, bufferSize);
                recorder.startRecording();
                isRecording = true;

AudioTrack audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                        AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);

if(audioPlayer.getPlayState() != AudioTrack.PLAYSTATE_PLAYING)
    audioPlayer.play();

//capture data and record to file
int readBytes=0, writtenBytes=0;
do{
   readBytes = recorder.read(data, 0, bufferSize);

   if(AudioRecord.ERROR_INVALID_OPERATION != readBytes){
      writtenBytes += audioPlayer.write(data, 0, readBytes);
   }
}
while(isRecording);

Вызывается исключение java.lang.IllegalStateException, вызванное тем, что "play() вызван неинициализированным AudioTrack".

Однако, если я изменяю инициализацию AudioTrack, например, чтобы использовать частоту дискретизации 8000 Гц и формат выборки 8 бит (вместо 16), он больше не генерирует исключение, и приложение работает, хотя оно вызывает ужасные шумы.

Когда я проигрываю AudioTrack из файла, нет никаких проблем с инициализацией AudioTrack, я пробовал 44100 и 16 бит, и он работал правильно, создавая правильный звук.

Любая помощь?

4b9b3361

Ответ 1

Все родные Android-аудио закодированы. Вы можете воспроизводить только форматы PCM в режиме реального времени или использовать специальный streaming кодек, который я не считаю тривиальным для Android.

Дело в том, что если вы хотите одновременно записывать/воспроизводить аудио, вам нужно будет создать свой собственный звуковой буфер и хранить в нем необработанные аудиофайлы, закодированные в PCM (я не уверен, что вы думаете о духе! или все это на вас, голова, поэтому я постараюсь быть ясной, но не пережевывать вашу резину).

PCM - это цифровое представление аналогового сигнала, в котором ваши аудио образцы представляют собой набор "моментальных снимков" исходной акустической волны. Поскольку все виды умных математиков и инженеров видели потенциал в попытке уменьшить количество бит, с которыми вы представляете эти данные, они придумали всевозможные кодеры. Кодированный (сжатый) сигнал представляется очень по-разному от необработанного сигнала ИКМ и должен быть декодирован (en-cod-er + dec-oder = codec). Если вы не используете специальные алгоритмы и медиатекстовые кодеки, невозможно воспроизвести закодированный сигнал, как вы пытаетесь, потому что он не кодирует образец по образцу, а скорее кадр за кадром, где вам нужен весь кадр образцов, если не полный сигнал, чтобы декодировать этот кадр.

Способ сделать это - это вручную хранить образцы звука, поступающие из буфера микрофона, и вручную подавать их в выходной буфер. Вам нужно будет сделать некоторую кодировку для этого, но я считаю, что есть некоторые приложения с открытым исходным кодом, на которые вы можете посмотреть и взять пик в своем источнике (если вы не захотите продать свое приложение позже, конечно, но это целое другое обсуждение).

Если вы разрабатываете Android 2.3 или новее и не слишком боитесь программирования в родном коде, вы можете попробовать использовать OpelSL ES. Android-особенности OpenSL ES перечислены здесь. Эта платформа позволяет вам несколько более гибко манипулировать аудио, и вы можете найти именно то, что вам нужно, если ваше приложение будет сильно полагаться на обработку звука.

Надеюсь, что это поможет. Ура! =)

Ответ 2

Вызывается исключение java.lang.IllegalStateException с тем, что вызванный "play(), вызванный неинициализированным AudioTrack".

Это потому, что размер буфера слишком мал. Я попробовал "bufferSize + = 2048;", тогда это нормально.

Ответ 3

У меня была аналогичная проблема, и я решил ее, добавив это разрешение в файл манифеста:

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>