如何将字节数组读写到SharedPreferences?麦克风数据存储后失真问题
声音失真问题分析与修复
核心问题
- 保存时冗余数据写入:录音时
recorder.read()返回的实际有效字节数被忽略,你直接对整个buffer进行Base64编码,包含了buffer中未被采集填充的无效数据,播放时混入冗余内容导致节奏混乱。 - 播放时固定写入长度:强制写入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
相关产品推荐
相关产品推荐

