Android车机系统-使用AudioRecord进行录音,偶发二倍速播放或播放的音频很短,解决方案

业务场景

最近遇到了一个需求中涉及到了音频的录制与播放。功能大体如下:有四个mic,可以任选其中一个先进行录音,然后进行播放。

我的做法是首先录制出一份完整的原始音频文件,然后将其拆分为四份,最终保存在车机系统中。经过上面所说的做法,最终会生成5个pcm文件,其中一个是完整的,另外4个是拆分的。

复现问题代码

while (isRecording) {
                    int read = mRecorder.read(data, 0, buffersize);
                    Log.d(TAG, " recording read: " + read);
                    if (AudioRecord.ERROR_INVALID_OPERATION != read) {
                        try {
                            for (int i = 0; i < (read / 8); i++) {
                                data1[i * 2] = data[i * 8];
                                data1[i * 2 + 1] = data[i * 8 + 1];
                                data2[i * 2] = data[i * 8 + 2];
                                data2[i * 2 + 1] = data[i * 8 + 3];
                                data3[i * 2] = data[i * 8 + 4];
                                data3[i * 2 + 1] = data[i * 8 + 5];
                                data4[i * 2] = data[i * 8 + 6];
                                data4[i * 2 + 1] = data[i * 8 + 7];
                            }
                            os.write(data);
                            os1.write(data1);
                            os2.write(data2);
                            os3.write(data3);
                            os4.write(data4);
                            Log.d(TAG, "run-----data ");
                        } catch (IOException e) {
                            e.printStackTrace();
                            Log.e(TAG, "Write data to record file error !");
                        }
                    }
                }

出现问题的关键代码如上。后来测试的时候发现,在播放录音时会偶发出现二倍速播放的情况和音频缺少只播放一点声音的情况。

对比正常log与异常log,发现read值的总和不同,初步判断在录音时就出现了问题。当时猜想会不会是缓存数据的数组大小不足,导致数据缺失。之后我将buffersize的大小设置为一个更大的值,测试后发现问题依旧存在。

解决问题

既然不是数组大小的事,那上述代码中就还剩下5个写入操作需要考虑了。仔细分析,上面的代码是存在问题的,当标志位不变时(正在录音),while循环中的代码会反复运行,每一次都要进行5个文件的写入操作,效率是低下的,可能某一次写入出现了问题就导致异常情况的发生。

因此我们需要将写入操作提到while循环的外面。

while (isRecording) {
                    int read = mRecorder.read(data, 0, buffersize);

                    Log.d(TAG, " recording read: " + read);
                    if (AudioRecord.ERROR_INVALID_OPERATION != read) {
                        for (int i = 0; i < read; i++) {
                            dataHolder[capacity + i] = data[i];
                        }
                        capacity += read;
                    }
                }

                Log.d(TAG, "run------capacity : " + capacity);
                try {
                    for (int i = 0; i < (capacity / 8); i++) {
                        data1[i * 2] = dataHolder[i * 8];
                        data1[i * 2 + 1] = dataHolder[i * 8 + 1];
                        data2[i * 2] = dataHolder[i * 8 + 2];
                        data2[i * 2 + 1] = dataHolder[i * 8 + 3];
                        data3[i * 2] = dataHolder[i * 8 + 4];
                        data3[i * 2 + 1] = dataHolder[i * 8 + 5];
                        data4[i * 2] = dataHolder[i * 8 + 6];
                        data4[i * 2 + 1] = dataHolder[i * 8 + 7];
                    }
                    os.write(dataHolder, 0, capacity);
                    os1.write(data1, 0, capacity / 4);
                    os2.write(data2, 0, capacity / 4);
                    os3.write(data3, 0, capacity / 4);
                    os4.write(data4, 0, capacity / 4);
                    Log.d(TAG, "run-----data has been written !");
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(TAG, "Write data to record file error !");
                }

最后经过测试,不再出现异常情况,问题解决。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Android中实现录音断点播放,可以使用AudioRecord进行录音,并使用MediaPlayer类进行播放。为了实现暂停和继续录音,我们需要在录音过程中使用一个标志位来控制录音和暂停状态,并在录音暂停时保存录音的状态(例如,当前录音的位置和录音数据),以便在继续录音时能够从上次暂停的位置继续录音。 以下是一个简单的实现示例: ```java public class AudioRecorder { private AudioRecord mAudioRecord; private boolean mIsRecording = false; private boolean mIsPaused = false; private int mBufferSize; private byte[] mBuffer; private File mOutputFile; private FileOutputStream mFileOutputStream; private int mBytesWritten; public AudioRecorder(File outputFile) { mOutputFile = outputFile; mBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); mBuffer = new byte[mBufferSize]; mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, mBufferSize); } public void start() { mIsRecording = true; mIsPaused = false; mAudioRecord.startRecording(); new Thread(new Runnable() { @Override public void run() { try { mFileOutputStream = new FileOutputStream(mOutputFile); while (mIsRecording) { if (!mIsPaused) { int bytesRead = mAudioRecord.read(mBuffer, 0, mBufferSize); mFileOutputStream.write(mBuffer, 0, bytesRead); mBytesWritten += bytesRead; } } mFileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } public void pause() { mIsPaused = true; } public void resume() { mIsPaused = false; } public void stop() { mIsRecording = false; mAudioRecord.stop(); mAudioRecord.release(); } public boolean isRecording() { return mIsRecording; } public boolean isPaused() { return mIsPaused; } public int getBytesWritten() { return mBytesWritten; } } ``` 在这个示例中,我们创建了一个AudioRecorder类来封装录音功能。在start()方法中,我们启动了一个新的线程来执行录音任务。在这个线程中,我们使用一个while循环来读取录音数据,并将其写入文件中。如果mIsPaused标志被设置为true,则录音任务将暂停,直到mIsPaused标志被设置为false。 在pause()和resume()方法中,我们分别设置mIsPaused标志为true和false,以控制录音任务的暂停和继续。 在stop()方法中,我们将mIsRecording标志设置为false,以停止录音任务,并释放AudioRecord资源。 最后,我们还提供了一些辅助方法,例如isRecording()、isPaused()和getBytesWritten()方法,用于查询录音状态和已写入的字节数。 请注意,这只是一个简单的示例,实际应用中可能需要更复杂的逻辑来处理录音暂停和继续的情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A-sL1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值