【问题标题】:Android - Audio Clipping when recording audio (crest/peak clipping and periodic 0 bit values in between)Android - 录制音频时的音频剪辑(波峰/峰值剪辑和中间的周期性 0 位值)
【发布时间】:2021-06-25 07:45:50
【问题描述】:

我正在尝试通过蓝牙设备录制音频流。我正在使用蓝牙 SCO 获取蓝牙音频和 AudioRecord 类来录制音频。 我正在使用 MONO 通道以 16000 的采样率录制 RAW .PCM 文件

我正在像这样计算 BufferSize

    private static final int BUFFER_SIZE_FACTOR = 2;
    private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLING_RATE_IN_HZ,CHANNEL_CONFIG, AUDIO_FORMAT) * BUFFER_SIZE_FACTOR;

这就是我目前获取/写入音频的方式,

private class RecordingRunnable implements Runnable {

    @Override
    public void run() {
        setFileNameAndPath();
        
        final ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
        try (final FileOutputStream outStream = new FileOutputStream(mFilePath)) {
            while (recordingInProgress.get()) {
                int result = recorder.read(buffer, BUFFER_SIZE);
                if (result < 0) {
                    throw new RuntimeException("Reading of audio buffer failed: " +
                            getBufferReadFailureReason(result));
                }
                outStream.write(buffer.array(), 0, BUFFER_SIZE);
                buffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("Writing of recorded audio failed", e);
        }

    }

我做了一点研究,发现剪裁效果可能是因为错误的字节顺序(LITTLE_ENDIAN or BIG_ENDIAN) 或因为糟糕的多线程。但是在当前的实现中,我无法理解字节是如何排序和保存的,以及我可以做些什么来解决剪辑/噪声问题。

我正在启动我的记录器,像这样运行

    recordingThread = new Thread(new RecordingRunnable(), "Recording Thread");
    recordingThread.start();
    recordingThread.setPriority(Thread.MAX_PRIORITY);

【问题讨论】:

    标签: java android bytebuffer audiorecord android-audiorecord


    【解决方案1】:

    我遇到了同样的问题,我用下面的代码解决了这个问题。

        private byte[] short2byte(short[] sData, int size) {
            int shortArrsize = size;
            byte[] bytes = new byte[shortArrsize * 2];
            for (int i = 0; i < shortArrsize; i++) {
                bytes[i * 2] = (byte) (sData[i] & 0x00FF);
                bytes[(i * 2) + 1] = (byte) (sData[i] >> 8);
                sData[i] = 0;
            }
            return bytes;
    
        }
    

    ......

                int bufferSize = AudioRecord.getMinBufferSize(48000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
                short[] buffer = new short[bufferSize];
    
                int source = MediaRecorder.AudioSource.VOICE_RECOGNITION;
    
                mAudioRecorder = new AudioRecord(source, 48000,
                        AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
                int state = mAudioRecorder.getState();
                if (state != AudioRecord.STATE_INITIALIZED) {
                    Log.e(TAG, "Can not support");
                    return;
                }
    
                mAudioRecorder.startRecording();
    
                while (mIsRecording) {
                    int bufferReadResult = mAudioRecorder.read(buffer, 0, bufferSize);
                    if (bufferReadResult < 0) {
                        continue;
                    }
    
                    try {
                        byte data[] = short2byte(buffer, bufferReadResult);
                        fos.write(data, 0, bufferReadResult * 2);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    

    【讨论】:

    • 非常感谢这个答案它解决了我的剪辑问题,但是当我将原始数据绘制为大胆时,我仍然有一些周期性的 0 位值,这些值在音频中也可以作为滴答声背景噪声听到。但还是比以前好多了。
    猜你喜欢
    • 1970-01-01
    • 2012-06-14
    • 2015-07-14
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多