Запись звука при помощи MediaRecorder и AudioRecord

Ответить
Alexei
Сообщения: 6
Зарегистрирован: 28 июн 2012, 16:51

Запись звука при помощи MediaRecorder и AudioRecord

Сообщение Alexei » 06 июл 2012, 01:40

Всем доброго времени суток )
Надеюсь не перепутал раздел для темы.
Решил я тут поковыряться со звукозаписью на Андройде и наткнулся на массу интересного)
В Android SDK существует пара классов для работы со звуком, а именно MediaRecorder и AudioRecord.
С MediaRecorder всё достаточно просто. Создаете экзмпляр этого класса, указываете параметры для записи, формат выходного файла, вызываете метод для начала записи и вуоля - файлик с записанным звуком у вас готов (тут даже есть небольшой пример).
Единственный минус этого класса - форматы выходных файлов ограничены, поэтому если вам требуется простой(не сжатый) *.wav файлик, то этого сделать не получиться.
Тут на помощь приходит AudioRecord, но с некоторыми оговорками. Формировать выходной файл вам придется самому. Тут вам и карты в руки )
Я нашел очень хороший пример, где детально расписана работа с обоими классми. Вот тут можно найти исходный код(я, к сожаленью, не знаю как тут прикреплять файлики).
Всё работает хоршо, но поковырявшись внутри возникла куча вопросов "как?" и "зачем?".
Т.к. автор статьи не особо отзывается, то решил обратиться к вам.
Знающие люди, помогите разобраться )
1. Непонятно зачем в методе start()
после вызова метода audioRecorder.startRecording();
вызывается метод audioRecorder.read(buffer, 0, buffer.length); причем дальше ни чего не делается.
еще раз метод audioRecorder.read(buffer, 0, buffer.length); вызывается в onPeriodicNotification(AudioRecord recorder), но тут это логично( буффер recorder`a заполнился, он вызвал обработчик(Listener) и мы его благополучно освободили, переписав в файл).
интересно, что если убрать вызов audioRecorder.read(buffer, 0, buffer.length) после audioRecorder.startRecording(), то файлик создается с нулевым размером =\
2. Так же немного не ясно почему размер буфера, в который мы считываем данные, сделан в 2 раза меньше чем буфер для recorder`а.
3. В методе reset()
после
audioRecorder = new AudioRecord(aSource, sRate, nChannels, aFormat, bufferSize);
не хватает
if (audioRecorder.getState() != AudioRecord.STATE_INITIALIZED)
throw new Exception("AudioRecord initialization failed");
audioRecorder.setRecordPositionUpdateListener(updateListener);
audioRecorder.setPositionNotificationPeriod(framePeriod);
или это мне только так кажется? тогда не понятно как новый обък поймет что ему вызывать при достижении NotificationPeriod?

Ну и наконец, самый последний вопрос.
Не могу понять почему, при вызоме мотода release() в логе выскакивает ошибка записи в файл.
В методе release() сначала вызывается метод stop(), там останавливается recorder ( audioRecorder.stop(); ), дописывается необходимая инфа в наш файлик и он закрывается, и уже после этого(уже в методе release() ) убивается recorder ( audioRecorder.release(); ).
Видимо после того, как мы остановили recorder и закрыли файлик, успевает вызваться обработчик(Listener) и выдать сообщение об ошибке записи.
Это мне кажется странноватым, ведь мы остановили работу recorder`a. Этотя этот вызов может быть связан с тем, что мы вызвали release() до наступления очередного NotificationPeriod. Тогда немного не ясно почему мы успеваем закрыть файл раньше, чем обработчик успеет в него что-то записать =\
В общем, вот такие дела. Надеюсь на вышу помощь )

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Запись звука при помощи MediaRecorder и AudioRecord

Сообщение damager82 » 11 июл 2012, 10:53

Ниче так вопросы ))
Я, к сожалению, с записью звука не работал. Если разберетесь, что к чему, то обязательно напишите об этом в разделе Наработки. Очень полезная инфа будет.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

djdance
Сообщения: 48
Зарегистрирован: 04 дек 2012, 15:33

Re: Запись звука при помощи MediaRecorder и AudioRecord

Сообщение djdance » 20 дек 2012, 17:13

Alexei,

у меня этот класс не хочет работать - не инициализируется. Причем compressed инициализируется, а uncompressed - нет.
Цикл перебирает все четыре варианта samplerate, но всегда с ошибкой создания.
Пермишны установлены, телефон с микрофоном, CHANNEL_IN_MONO ставил, - никак.
Может я его не так создаю?

ExtAudioRecorder extAudioRecorder;
extAudioRecorder = ExtAudioRecorder.getInstanse(false); // Uncompressed recording (WAV)
Log.d(TAG, "state="+extAudioRecorder.getState().toString()); // <- тут всегда 0 , а в логе - четыре раза AudioRecord initialization failed!


UPD Понял. Любопытно, чужой сервис держал занятым аудиоустройства. Интересно, можно ли это как-то отлавливать (указывать на того кто занимает)...

djdance
Сообщения: 48
Зарегистрирован: 04 дек 2012, 15:33

Re: Запись звука при помощи MediaRecorder и AudioRecord

Сообщение djdance » 10 фев 2013, 13:42

ничего не гуглится, придется опять спрашивать безмолвствующую толпу :)

вот audioRecorder.setPositionNotificationPeriod(framePeriod); работает с некими фреймами. Нигде не написано, что это за ферймы, равны ли они байтам буффера, почему они так странно считаются в некоторых реализациях, типа: framePeriod = bufferSize / ( 2 * bSamples * nChannels / 8 );

tserg
Сообщения: 4
Зарегистрирован: 18 фев 2013, 11:06

Re: Запись звука при помощи MediaRecorder и AudioRecord

Сообщение tserg » 11 мар 2013, 09:49

А у меня такая задача: захватить звук с аудиовыхода, т.е. звук воспроизводимый устройством. Среди AudioSource -ов такого нет. Может быть есть вариант с перехватом сигнала, который идет на динамики? Может кто-нибудь знает как это делается?


Ответить