(Android)翻山越岭之第一坑

坑点:录音文件的使用在小米5以上的机型 无法读取pcm流转化的wav格式录音文件

需求点:需要上传一份采样16k 单声道 mic的wav的音频
问 题:录制没有问题,但在显示播放的控件上发现并不能播放。查找原因,小米5的文件目录下录音文件用自带音乐播放器打开显示不存在。应该是小米5不支持此制式
采用过的解决方案:
1.同时录另一份非pcm流音频用作播放使用
2.将录制好的wav音频转化为amr

知识点:

1.Android 系统 Java 层提供两个 Recorder Api, MediaRecorder 与 AudioRecorder,前者能够生成编码后的录音文件,而后者则是 PCM Audio RAW Data,显然后者是我们所需的,我们能通过对 PCM 的操作,来完成需要做的任何操作。
2.pcm转amr:Google提供了官方的方法不过隐藏了,Android系统的源码中包含有一个android.media.AmrInputStream类,其内部分装了将pcm转换为amr的方法,但仅支持8k采样的转化
可以利用反射使用该类
     /**
     * 通过反射调用android系统自身AmrInputStream类进行转换
     *
     * @param inPath  源文件
     * @param outPath 目标文件
     */
    public void wav2Amr(String inPath, String outPath) {
        try {
            FileInputStream fileInputStream = new FileInputStream(inPath);
            FileOutputStream fileoutputStream = new FileOutputStream(outPath);
            // 获得Class
            Class cls = Class.forName("android.media.AmrInputStream");
            // 通过Class获得所对应对象的方法
            Method[] methods = cls.getMethods();
            // 输出每个方法名
            fileoutputStream.write(new byte[]{0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A});//amr头文件
            Constructor con = cls.getConstructor(InputStream.class);
            Object obj = con.newInstance(fileInputStream);
            for (Method method : methods) {
                Class[] parameterTypes = method.getParameterTypes();
                if ("read".equals(method.getName())
                        && parameterTypes.length == 3) {
                    byte[] buf = new byte[1024];
                    int len = 0;
                    while ((len = (int) method.invoke(obj, buf, 0, 1024)) > 0) {
                        fileoutputStream.write(buf, 0, len);
                    }
                    break;
                }
            }
            for (Method method : methods) {
                if ("close".equals(method.getName())) {
                    method.invoke(obj);
                    break;
                }
            }
            fileoutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

后话:pcm转amr可以使用opencore中的amr模块opencore-amr-android;

此项目支持amr-nb(8k采样转化)不支持amr-wb(16k采样转化),现opencore项目已支持amr-wb,此项目可做参考

你可能感兴趣的:((Android)翻山越岭之第一坑)