obtainBuffer超时(是CPU挂钩?)



我正在使用我自己的应用程序同时播放和捕获音频数据。

我正在使用音乐文件进行播放并捕获该数据以测试android中的渲染延迟,但我正在获得日志

obtainBuffer超时(是CPU挂钩?)

我的文件是:

MainActivity.java
public class MainActivity extends Activity implements OnClickListener {

@SuppressLint("NewApi")
class AudioTask implements Runnable {
    /**
     * Queue on which audio blocks are placed.
     */
    LinkedBlockingQueue<byte[]> mQueue;
    VoiceAudioRecord mAudioRecord;
    int block_size;
    boolean done;
    static final int DEFAULT_BLOCK_SIZE = 1024;
    AudioTask(LinkedBlockingQueue<byte[]> q, int block_size) {
        this.done = false;
        mQueue = q;
        this.block_size = block_size;
        int intSize = android.media.AudioTrack.getMinBufferSize(8000, channelConfig,
                audioFormat);
        mAudioRecord = new VoiceAudioRecord(8000, intSize, true, true, true);
        boolean isAvailable = AcousticEchoCanceler.isAvailable();
        Log.i(LOG_TAG, "AEC available : "+isAvailable);
        if(mAecToggle.isChecked()) {
            Log.i("TOGGLE_BUTTON_AEC", "STARTED AEC PROCESS");
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    int audioId = mAudioRecord.getAudioSessionId();
                    mAec = AcousticEchoCanceler.create(audioId);
                    Log.i(LOG_TAG, "AEC created " + mAec);
                    try {
                        mAec.setEnabled(true);
                        Log.i(LOG_TAG, "AEC getEnabled  : " + mAec.getEnabled());
                    } catch (IllegalStateException e) {
                        Log.i(LOG_TAG, "setEnabled() in wrong state");
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    public void stop() {
        this.done = true;
    }
    public void run() {
        if (mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
            mAudioRecord.startRecording();
            while (!this.done) {
                int nshorts = this.readBlock();
                if (nshorts == AudioRecord.ERROR_INVALID_OPERATION) {
                    Log.i("AUDIO_REC","read: ERROR_INVALID_OPERATION");
                    break;
                } else if (nshorts == AudioRecord.ERROR_BAD_VALUE) {
                    Log.i("AUDIO_REC","read: ERROR_BAD_VALUE");
                    break;
                } else if (nshorts <= 0) {
                    Log.i("AUDIO_REC","read: " + nshorts);
                    break;
                }
            }
            mAudioRecord.stop();
        } else {
            Log.i("AUDIO_REC","AudioRecord not initialized");
        }
        mAudioRecord.release();
    }
    private int readBlock() {
        byte[] buffer = new byte[this.block_size];
        int nshorts = mAudioRecord.read(buffer, 0, buffer.length);
        if (nshorts > 0) {
            Log.i("AUDIO_REC","Posting " + nshorts + " samples to queue");
            mQueue.add(buffer);
        }
        return nshorts;
    }
}
/**
 * Audio recording task.
 */
AudioTask mAudioTask;
/**
 * Thread associated with recording task.
 */
Thread audio_thread;
/**
 * Queue of audio buffers.
 */
LinkedBlockingQueue<byte[]> mAudioQ;

short[] audioShorts, recvShorts, recordedShorts, filteredShorts;
byte[] audioBytes, recvBytes;
int shortsRead;
byte[][] fullTrack;
AudioRecord recorder;
AudioTrack player;
Boolean isInterrupted = true;
int indexOfArray = 0;
// ---------------------------------
@SuppressWarnings("deprecation")
private int channelConfig = AudioFormat.CHANNEL_IN_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private Button mRecordButton, mPlayButton;
private boolean isRecording = false;
PlayAudioFile audioFile;
private RecordedAudioFile mRecordedFile;
private MediaPlayer mMediaPlayer;
private AcousticEchoCanceler mAec;
private ToggleButton mAecToggle;
private boolean isPlaying = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mRecordButton = (Button)findViewById(R.id.button1);
    mRecordButton.setOnClickListener(this);
    //findViewById(R.id.button2).setOnClickListener(this);
    mPlayButton = (Button)findViewById(R.id.button3);
    mPlayButton.setOnClickListener(this);
    mPlayButton.setVisibility(View.INVISIBLE);
    mAecToggle = (ToggleButton) findViewById(R.id.aecButton);
    audioFile = new PlayAudioFile(getApplicationContext());
    mAudioQ = new LinkedBlockingQueue<byte[]>();
    mRecordedFile = new RecordedAudioFile();
    mMediaPlayer = null;
}
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button1: {
            if (isRecording) {
                stopRecording();
                mRecordButton.setText("Record");
                mPlayButton.setVisibility(View.VISIBLE);
                mAecToggle.setVisibility(View.VISIBLE);
            } else {
                new RecordAudio().execute();
                if(mMediaPlayer != null) {
                    mMediaPlayer.stop();
                    mMediaPlayer.release();
                    mMediaPlayer = null;
                }
                mRecordButton.setText("Stop");
                mPlayButton.setVisibility(View.INVISIBLE);
                mAecToggle.setVisibility(View.INVISIBLE);
                playAudio();
            }
            break;
        }
        case R.id.button3:
            if(!isPlaying) {
                playRecordedAudio();
            }
            break;
        default:
            break;
    }
}
private void playAudio() {
    audioFile.playAudio();
}
private void stopRecording() {
    assert mAudioTask != null;
    mAudioTask.stop();
    try {
        this.audio_thread.join();
    }
    catch (InterruptedException e) {
        Log.e("AUDIO_REC","Interrupted waiting for audio thread, shutting down");
    }
    if(mAecToggle.isChecked()) {
        if (mAec != null) {
            Log.i("AUDIO_REC", "Releasing AEC");
            mAec.release();
        }
        Log.i("TOGGLE_BUTTON_AEC", "COMPLETE AEC PROCESS");
    }

    isRecording = false;
    audioFile.stopAudio();
    mRecordedFile.processAndSaveAudioQueue(mAudioQ);
}
private void playRecordedAudio() {
    final Thread filePlayThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                playAdioTrack(new File(mRecordedFile.getFilename()).getPath());
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    },"File Play Thread");
    filePlayThread.start();
}
private void playAdioTrack(String filePath) throws IOException
{
    // We keep temporarily filePath globally as we have only two sample sounds now..
    if (filePath==null)
        return;
    int intSize = android.media.AudioTrack.getMinBufferSize(44100,        aAudioFormat.CHANNEL_IN_STEREO,
            AudioFormat.ENCODING_PCM_16BIT);
    AudioTrack mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_IN_STEREO,
            AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);

    if (mAudioTrack ==null){
        Log.d("TCAudio", "audio track is not initialised ");
        return;
    }
    int count = 1024 * 1024; // 512 kb
    byte[] byteData = null;
    File file = null;
    file = new File(filePath);
    byteData = new byte[(int)count];
    FileInputStream in = null;
    try {
        in = new FileInputStream( file );
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    int bytesread = 0, ret = 0;
    int size = (int) file.length();
    mAudioTrack.play();
    isPlaying = true;
    while (bytesread < size && isPlaying) {
        ret = in.read( byteData,0, count);
        if (ret != -1 && mAudioTrack != null) { // Write the byte array to the track
            mAudioTrack.write(byteData,0, ret);
            bytesread += ret;
        } else
            break;
    }
    in.close();
    mAudioTrack.release();
}
public class RecordAudio extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... params) {
        startRecdording();
        return null;
    }
}
void startRecdording() {
    mAudioTask = new AudioTask(mAudioQ, 1024);
    this.audio_thread = new Thread(mAudioTask);
    this.audio_thread.start();
    isRecording = true;
}

}

PlayAudiofile.java

public class PlayAudioFile {
private Thread filePlayThread = null;
private Context mContext;
private AudioTrack mAudioTrack;
private boolean isPlaying = false;
public PlayAudioFile (Context context) {
    this.mContext = context;
}
public void playAudio() {
    filePlayThread = new Thread(new Runnable() {
        @Override
        public void run() {
            File f = new File(mContext.getCacheDir()+"/male.wav");
            if (!f.exists()) try {
                InputStream is = mContext.getAssets().open("male.wav");
                int size = is.available();
                Log.i("PLAY_AUDIO","size "+size);
                byte[] buffer = new byte[size];
                is.read(buffer);
                is.close();
                FileOutputStream fos = new FileOutputStream(f);
                fos.write(buffer);
                fos.close();
            } catch (Exception e) { throw new RuntimeException(e); }
            try {
                playAdioTrack(f.getPath());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    },"File Play Thread");
    filePlayThread.start();
}
private void playAdioTrack(String filePath) throws IOException
{
    // We keep temporarily filePath globally as we have only two sample sounds now..
    if (filePath==null)
        return;
    int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT);
    mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,   AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);

    if (mAudioTrack ==null){
        Log.d("TCAudio", "audio track is not initialised ");
        return;
    }
    int count = 512 * 1024; // 512 kb
    byte[] byteData = null;
    File file = null;
    file = new File(filePath);
    byteData = new byte[(int)count];
    FileInputStream in = null;
    try {
        in = new FileInputStream( file );
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    int bytesread = 0, ret = 0;
    int size = (int) file.length();
    mAudioTrack.play();
    isPlaying = true;
    while (bytesread < size && isPlaying) {
        ret = in.read( byteData,0, count);
        if (ret != -1 && mAudioTrack != null) { // Write the byte array to the track
            mAudioTrack.write(byteData,0, ret);
            bytesread += ret;
        } else
            break;
    }
    in.close();
    mAudioTrack.release();
    mAudioTrack = null;
}
public void stopAudio () {
    if(mAudioTrack == null) return;
    mAudioTrack.stop();
    isPlaying = false;
}
}

RecordedAudioFile.java

public class RecordedAudioFile {

//variables are declared and defined here 
public RecordedAudioFile() {
    bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
}
public void processAndSaveAudioQueue(LinkedBlockingQueue<byte[]> audioQ) {
    this.mAudioQ = audioQ;
    fileWriteThread = new Thread(new Runnable() {
        @Override
        public void run() {
            writeAudioDataToFile();
        }
    },"File Write Thread");

    fileWriteThread.start();
}

private void writeAudioDataToFile(){
    byte data[] = new byte[bufferSize];
    String filename = getTempFilename();
    FileOutputStream os = null;
    try {
        os = new FileOutputStream(filename);
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    int read = 0;
    if(null != os){
        byte[] buf;
        while ((buf = mAudioQ.poll()) != null) {
                try {
                    os.write(buf);
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
        try {
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    copyWaveFile(getTempFilename(),getFilename());
    deleteTempFile();
}
private String getTempFilename(){
//tempfile for storing temporary data        
}
private void copyWaveFile(String inFilename,String outFilename){
 //we will copy the captured data into a file here
}
private void WriteWaveFileHeader(
        FileOutputStream out, long totalAudioLen,
        long totalDataLen, long longSampleRate, int channels,
        long byteRate) throws IOException {
    //writing wave header here to the file
}
public String getFilename(){
    //getting the file name for copying the captured data into it
}
private void deleteTempFile() {
    File file = new File(getTempFilename());
    file.delete();
}
}

VoiceAudioRecord.java

public VoiceAudioRecord(int sampleRateInHz, int bufferSizeInBytes,
                        boolean noise, boolean gain, boolean echo)
        throws IllegalArgumentException {
    this(MediaRecorder.AudioSource.MIC, sampleRateInHz,
            AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,
            bufferSizeInBytes, noise, gain, echo);
}
......
public VoiceAudioRecord(int audioSource, int sampleRateInHz,
                        int channelConfig, int audioFormat, int bufferSizeInBytes,
                        boolean noise, boolean gain, boolean echo)
        throws IllegalArgumentException {
    super(audioSource, sampleRateInHz, channelConfig, audioFormat,
            bufferSizeInBytes);
}
}

我得到这样的日志

W/AudioRecord( 2118): obtainBuffer timed out (is the CPU pegged?) user=00027e84, server=00027e84
W/AudioRecord( 2118): obtainBuffer timed out (is the CPU pegged?) user=00027e84, server=00027e84
W/AudioTrack( 2118): obtainBuffer timed out (is the CPU pegged?) 0x5c2d4d68 name=0x1user=00077730, server=000765c6
W/AudioTrack( 2118): obtainBuffer timed out (is the CPU pegged?) 0x5c2d4d68 name=0x1user=00077730, server=000765c6
W/AudioRecord( 2118): obtainBuffer timed out (is the CPU pegged?) user=00027e84, server=00027e84
W/AudioFlinger( 1371): write blocked for 1817 msecs, 2 delayed writes, thread 0x40ae5008

,然后我的捕获和播放不像我预期的那样好。

即使我将cpu速度设置为高模式,日志也会重复。

可能是什么问题?

我正在使用低速设备,这对我来说不是很好。这就是为什么我得到这个错误。当我在我的设备上升级到最新的android时,我解决了这个问题

相关内容

  • 没有找到相关文章

最新更新