You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将字节数组读写到SharedPreferences?麦克风数据存储后失真问题

声音失真问题分析与修复

核心问题

  1. 保存时冗余数据写入:录音时recorder.read()返回的实际有效字节数被忽略,你直接对整个buffer进行Base64编码,包含了buffer中未被采集填充的无效数据,播放时混入冗余内容导致节奏混乱。
  2. 播放时固定写入长度:强制写入1280字节,但每个片段的有效数据长度不一定等于该值,破坏了音频的采样速率,最终出现类似小黄人的失真音效。

修正后的保存代码

int index = 0;
// 提前获取编辑器,避免循环内重复创建
SharedPreferences.Editor editor = getSharedPreferences(PREF_NAME, MODE_PRIVATE).edit();
while(index != 1000) {
    index++;
    // 获取实际采集到的有效字节数
    int actualReadSize = recorder.read(buffer, 0, buffer.length);
    if (actualReadSize <= 0) {
        break; // 读取失败或结束时退出循环
    }
    // 仅编码实际有效数据,而非整个buffer
    byte[] validData = Arrays.copyOf(buffer, actualReadSize);
    String saveThis = Base64.encodeToString(validData, Base64.DEFAULT);
    
    // 同时保存每个片段的有效长度,供播放时使用
    editor.putString("data_" + index, saveThis);
    editor.putInt("size_" + index, actualReadSize);
    
    System.out.println("Actual Read Size: " + actualReadSize);
}
editor.apply(); // 统一提交修改,提升性能

修正后的读取代码

int index = 0;
// 提前获取SharedPreferences实例
SharedPreferences prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
while(index != 1000) {
    index++;
    String dataName = "data_"+ index;
    String sizeKey = "size_" + index;
    
    String data = prefs.getString(dataName, null);
    Integer actualSize = prefs.getInt(sizeKey, -1);
    
    if (data == null || actualSize == -1) {
        break; // 无有效数据时退出循环
    }
    
    bufferPlay = Base64.decode(data, Base64.DEFAULT);
    // 写入对应长度的有效数据,而非固定值
    speaker.write(bufferPlay, 0, actualSize);
    
    Log.d("T", String.valueOf(index));
}

额外注意事项

  • 确保录音MediaRecorder和播放AudioTrack的参数(采样率、声道数、编码格式)完全一致,参数不匹配也会导致音频失真。
  • 循环内频繁操作SharedPreferences会影响性能,统一提交修改能减少IO开销。

内容的提问来源于stack exchange,提问作者CodeBlack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 18:35:27