android, AudioRecord.read () -> bufferoverflow, как обработать буфер? - PullRequest
1 голос
/ 07 марта 2011

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

Сначала я создаю Activity, где у меня есть только две кнопки, одна для запуска AsyncTask и одна для его остановки. Я имею в виду, что я просто установил логическое значение isRecording на false, все остальное обрабатывается в AsyncTask, который прикреплен в качестве исходного кода.

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

03-07 11:34:02.474: INFO/buffer 247:(558): 40
03-07 11:34:02.484: WARN/AudioFlinger(33): RecordThread: buffer overflow
03-07 11:34:02.484: INFO/MutantAudioRecorder:doInBackground()(558): isRecoding
03-07 11:34:02.484: INFO/MutantAudioRecorder:doInBackground()(558): isRecoding
03-07 11:34:02.494: WARN/AudioFlinger(33): RecordThread: buffer overflow
03-07 11:34:02.494: INFO/buffer 248:(558): -50
  1. Я записываю буфер, как вы можете видеть, но почему-то я думаю, что допустил ошибку в правильной настройке AudioRecord, кто-нибудь может сказать, почему я получаю переполнение буфера?

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

Заранее спасибо за помощь.

Исходный код AsyncTask:

package nomihodai.audio;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.os.AsyncTask;
import android.util.Log;



public class MutantAudioRecorder extends AsyncTask<Void, Void, Void> {

private boolean isRecording = false;
public AudioRecord audioRecord = null;
public int mSamplesRead;
public int buffersizebytes;
public int buflen;
public int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
public static short[] buffer;
public static final int SAMPLESPERSEC = 8000;


@Override
protected Void doInBackground(Void... params) {

    while(isRecording) {

        audioRecord.startRecording();
        mSamplesRead = audioRecord.read(buffer, 0, buffersizebytes);

        if(!readerT.isAlive())
            readerT.start();

        Log.i("MutantAudioRecorder:doInBackground()", "isRecoding");
    }

    readerT.stop();

    return null;
}


Thread readerT = new Thread() {
    public void run() {
        for(int i = 0; i < 256; i++){ 
            Log.i("buffer " + i + ": ", Short.toString(buffer[i]));
        }
    }
};


@Override
public void onPostExecute(Void unused) {
    Log.i("MutantAudioRecorder:onPostExecute()", "try to release the audio hardware");

    audioRecord.release();

    Log.i("MutantAudioRecorder:onPostExecute()", "released...");
}


public void setRecording(boolean rec) {
    this.isRecording = rec;

    Log.i("MutantAudioRecorder:setRecording()", "isRecoding set to " + rec);
}


@Override
protected void onPreExecute() {

    buffersizebytes = AudioRecord.getMinBufferSize(SAMPLESPERSEC, channelConfiguration, audioEncoding);
    buffer = new short[buffersizebytes];
    buflen = buffersizebytes/2;

    Log.i("MutantAudioRecorder:onPreExecute()", "buffersizebytes: " + buffersizebytes
                                                + ", buffer: " + buffer.length
                                                + ", buflen: " + buflen);

    audioRecord = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,
            SAMPLESPERSEC,
            channelConfiguration,
            audioEncoding,
            buffersizebytes);

    if(audioRecord != null)
        Log.i("MutantAudioRecorder:onPreExecute()", "audiorecord object created");
    else
        Log.i("MutantAudioRecorder:onPreExecute()", "audiorecord NOT created");
}

}

Ответы [ 2 ]

4 голосов
/ 25 июля 2012

Вероятно, это какой-то процесс анализа в реальном времени, работающий с записанными аудиобайтами?

Поскольку размер буфера для записи ограничен, как только ваш «процесс анализа» будет медленнее скорости записи, данные в буферебудет зависать, но байты записи всегда поступают, поэтому переполнение буфера.

Попробуйте использовать потоки при записи и другой процесс на записанных байтах, для этого подхода есть пример кода с открытым исходным кодом: http://musicg.googlecode.com/files/musicg_android_demo.zip

0 голосов
/ 15 апреля 2011

Как мы обсуждали в чате, декодирование аудиоданных и их отображение на экране должно быть простым. Вы упомянули, что аудиобуфер имеет 8000 сэмплов в секунду, каждый сэмпл 16-битный, и это монофонический звук.

Отображение этого должно быть простым. Рассматривайте каждый образец как вертикальное смещение в вашем представлении. Вам нужно масштабировать диапазон от -32k до + 32k до вертикальной высоты вашего обзора. Начиная с левого края представления, нарисуйте один образец на столбец. Когда вы дойдете до правого края, снова обернитесь вокруг (стирая предыдущую строку при необходимости).

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

Последнее замечание: вы будете рисовать 8000 раз в секунду, плюс еще, чтобы убрать предыдущие образцы. Возможно, вам придется предпринять некоторые сокращения, чтобы убедиться, что частота кадров не отстает от звука. Возможно, вам придется пропустить образцы.

...