Воспроизведение звука с микрофона в режиме реального времени - PullRequest
30 голосов
/ 20 апреля 2011

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

Я использую классы 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 бит, и он работал правильно, создавая правильный звук.

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

Ответы [ 3 ]

29 голосов
/ 21 апреля 2011

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

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

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

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

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

3 голосов
/ 20 октября 2011

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

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

0 голосов
/ 15 октября 2012

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

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