Вопросы по Android AudioRecord? - PullRequest
       49

Вопросы по Android AudioRecord?

5 голосов
/ 16 января 2011

Я возился с функцией AudioRecord в Android API и обнаружил странное поведение с ней.

Справочная информация: Мой телефон HTC Incredible Я использую плагин Eclipse для разработки под Android с помощью эмулятора. Целевая платформа или ОС - 2.2 ... Так как это то, что использует мой телефон.

Какой-то код:

bufferSize = AudioRecord.getMinBufferSize(FREQUENCY, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);

Это код, который я использую для настройки AudioRecord API. Теперь эмулятору нравится, когда для FREQUENCY установлено значение 8000, чтобы он работал. Возвращается с размером буфера 640. Для телефона я использую 44100. Одна из проблем здесь, кажется, что получающиеся в результате данные PCM для волны кажутся восьмибитными знаковыми волнами. Я получаю значения от -127 до 128. Я думал, что значение AudioFormat.ENCODING_PCM_16BIT даст что-то другое.

Я обрабатываю аудио с помощью потока,

public void run() {
  while(isRecording) {
    audioRecord.startRecording();
    byte[] data = new byte[bufferSize];
    audioRecord.read(data, 0, bufferSize);
    listener.setData(data);
    handleData(data);
  }
  audioRecord.release();
}

У меня есть способ графически отобразить соответствующую волну в режиме реального времени, используя SurfaceView. Кажется, от микрофона много шума. Я получаю этот шум от эмулятора и телефона, а также. Нужно ли запускать данные через какие-то фильтры? Я хотел бы использовать эти данные для вычисления некоторого забавного БПФ и прочего, чтобы просто поиграть с волной. Но мне нужно как-то уменьшить шум.

Кто-нибудь еще испытывал это? У кого-нибудь есть решение?

Я ценю ваше время и ответы, Спасибо, дк

Ответы [ 4 ]

12 голосов
/ 30 ноября 2011

Когда вы читаете байты из потока «AudioFormat.ENCODING_PCM_16BIT», он фактически дает вам как верхний, так и нижний байты каждого сэмпла как 2 последовательных байта.Это будет казаться очень шумным, если вы просто возьмете каждый байт в качестве образца (вместо того, чтобы на самом деле считать половину сэмпла), плюс подпись будет неправильной для первого байта (в младшем порядке).

Чтобы получить значимые данные из потока, прочитайте через шорты, например,

public void run() {
  while(isRecording) {
    audioRecord.startRecording();
    short[] data = new short[bufferSize/2];
    audioRecord.read(data, 0, bufferSize/2);
    listener.setData(data);
    handleData(data);
  }
  audioRecord.release();
}
9 голосов
/ 28 июня 2011

Прошло много времени с тех пор, как этот вопрос был задан, поэтому я не знаю, является ли ответ на него более актуальным.

Причина, по которой вы получаете значения от -127 до 128, заключается в том, что вычтение в массив байтов, каждый из которых содержит 8-битное число со знаком.Для 16-битного звука прочитайте массив шортов.

Боюсь, я не могу помочь с проблемой шума.

3 голосов
/ 24 января 2011

Я мог бы помочь немного. Однако я нахожусь в той же ситуации, что и вы, поэтому могу рассказать вам только о своем опыте.

Я полагаю, что вы можете получить предпочтительный sampleRate вашего устройства, например, так:

int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);

Режим кодирования 16 бит является единственным, который работает с AudioRecord. Я не уверен, почему вы получаете 8-битный вывод (верно?). Может кто знает.

Я также не уверен, как вы извлекаете амплитуду из извлеченных байтов, вы это сделали?

Наконец, я считаю, что вам нужно использовать функции периодического прослушивателя, например:

int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);
int channelMode = AudioFormat.CHANNEL_IN_MONO;
int encodingMode = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelMode, encodingMode);

AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelMode, encodingMode, bufferSize);

recorder.setPositionNotificationPeriod(intervalFrames);
recorder.setRecordPositionUpdateListener(recordListener);
recorder.startRecording();

private RecordListener recordListener = new RecordListener();
private class RecordListener implements AudioRecord.OnRecordPositionUpdateListener {
    public void onMarkerReached(AudioRecord recorder) {
        Log.v("MicInfoService", "onMarkedReached CALL");
    }

    public void onPeriodicNotification(AudioRecord recorder) {
        Log.v("MicInfoService", "onPeriodicNotification CALL");
    }
}

Здесь есть два больших вопроса, на которые я не могу ответить, и я тоже хочу знать ответ от себя:

  1. Что следует установить в качестве intervalFrames?
  2. Почему методы слушателя никогда не вызываются?

Хотелось бы помочь больше.

2 голосов
/ 07 июня 2012

Этот проект с открытым исходным кодом имеет большое количество вспомогательных классов, которые помогут вам получить аудиоданные и поэкспериментировать с их анализом:

https://github.com/gast-lib/gast-lib

Имеет AsyncTask

В нем есть что-то, что контролирует AudioRecorder

Он даже имеет простой алгоритм оценки частоты

...