Android录音并进行本地转码为MP3

版权声明:个人原创文章,欢迎点评,有错希望指出来,新手,谢谢大家--。-- https://blog.csdn.net/u013009808/article/details/81806891

**

Android录音并进行本地转码

**
通过安卓手机进行录音,
录音后,使用lame进行转码操作

开发中需要使用这个功能,只是一个简单的进行转码的工具,具体的代码信息如下
项目的基本结构图
项目的结构图
1、下载工具包
下载lame工具包
使用的最新版本
安装NDK环境
这里写图片描述
这里写图片描述

2、lame内容复制
首先在 src/main/目录下新建一个 cpp文件夹,Lame源码中 libmp3lame拷贝到 cpp文件夹下,可以重命名,例如我命名为 lamemp3
将Lame源码中的 include文件夹下的 lame.h复制到 lamemp3文件夹中
剔除 lamemp3中不必要的文件和目录,.rc/am/in文件都可以删除,Android这里用不到,只保留 .c和 .h文件
修改 util.h的源码。在570行找到 ieee754_float32_t数据类型,将其修改为 float类型,因为 ieee754_float32_t是Linux或者是Unix下支持的数据类型,在Android下并不支持。
set_get.h中24行将 include<lame.h>改为 include"lame.h"
在 id3tag.c和 machine.h两个文件里,將 HAVE_STRCHR和 HAVE_MEMCPY的ifdef结构体注释掉,不然编译会报错。

3、build.gradle配置
因为Androidstudio已经更新到最新

defaultConfig {
        applicationId "com.example.gz.testmp3"
        minSdkVersion 23
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild{
            cmake{
                cppFlags "-frtti -fexceptions" //设置cpp配置参数,c文件请使用CFlags
                abiFilters 'armeabi-v7a', "armeabi"
            }
        }
        ndk{
            abiFilters 'armeabi-v7a',"armeabi"
        }
    }
    sourceSets{
        main{
            jniLibs.srcDirs = ['libs']
        }
    }

如果下载的是最新的NDK与cmake,报出了一下的错误,

abis [mips64, armeabi, mips] are not supported for platform. supported
abis are [armeabi-v7a, arm64-v8a, x86, x86_64].

解决办法将gradle中cmake abiFilters配置改为:abiFilters ‘x86’, ‘x86_64’,’arm64-v8a’, ‘armeabi-v7a’
Google NDK r18解释: Support for ARMv5 (armeabi), MIPS, and MIPS64 has been removed. Attempting to build any of these ABIs will result in an error
我这里的abiFilters 只写了两个

4、编写Java native方法 MP3Converter

public class MP3Converter {
    static {
        System.loadLibrary("lame-mp3-utils");//这里一定要写对名称
    }
    //测试lame环境是否安装成功
    public static native String getLameVersion();
    /**
     * init lame
     * @param inSampleRate
     *              input sample rate in Hz
     * @param channel
     *              number of channels
     * @param mode
     *              0 = CBR, 1 = VBR, 2 = ABR.  default = 0
     * @param outSampleRate
     *              output sample rate in Hz
     * @param outBitRate
     *              rate compression ratio in KHz
     * @param quality
     *              quality=0..9. 0=best (very slow). 9=worst.<br />
     *              recommended:<br />
     *              2 near-best quality, not too slow<br />
     *              5 good quality, fast<br />
     *              7 ok quality, really fast
     */
    public native static void init(int inSampleRate, int channel, int mode,
                                   int outSampleRate, int outBitRate, int quality);
    /**
     * file convert to mp3
     * it may cost a lot of time and better put it in a thread
     * @param inputPath
     *          file path to be converted
     * @param mp3Path
     *          mp3 output file path
     */
    public native  static void convertMp3(String inputPath, String mp3Path);
    /**
     * get converted bytes in inputBuffer
     * @return
     *          converted bytes in inputBuffer
     *          to ignore the deviation of the file size,when return to -1 represents convert complete
     */
    public native static long getConvertBytes();
}

5、编写调用C/C++的cpp
这个直接使用的是百度上的,仅限于能看懂,对于c++不懂

extern "C"
JNIEXPORT void JNICALL
Java_jaygoo_library_converter_MP3Converter_convertMp3(JNIEnv * env, jobject obj, jstring jInputPath, jstring jMp3Path) {
    const char* cInput = env->GetStringUTFChars(jInputPath, 0);
    const char* cMp3 = env->GetStringUTFChars(jMp3Path, 0);
    //open input file and output file
    FILE* fInput = fopen(cInput,"rb");
    FILE* fMp3 = fopen(cMp3,"wb");
    short int inputBuffer[BUFFER_SIZE * 2];
    unsigned char mp3Buffer[BUFFER_SIZE];//You must specified at least 7200
    int read = 0; // number of bytes in inputBuffer, if in the end return 0
    int write = 0;// number of bytes output in mp3buffer.  can be 0
    long total = 0; // the bytes of reading input file
    nowConvertBytes = 0;
    //if you don't init lame, it will init lame use the default value
    if(lame == NULL){
        lameInit(44100, 2, 0, 44100, 96, 7);
    }

    //convert to mp3
    do{
        read = static_cast<int>(fread(inputBuffer, sizeof(short int) * 2, BUFFER_SIZE, fInput));
        total +=  read * sizeof(short int)*2;
        nowConvertBytes = total;
        if(read != 0){
            write = lame_encode_buffer_interleaved(lame, inputBuffer, read, mp3Buffer, BUFFER_SIZE);
            //write the converted buffer to the file
            fwrite(mp3Buffer, sizeof(unsigned char), static_cast<size_t>(write), fMp3);
        }
        //if in the end flush
        if(read == 0){
            lame_encode_flush(lame,mp3Buffer, BUFFER_SIZE);
        }
    }while(read != 0);

    //release resources
    resetLame();
    fclose(fInput);
    fclose(fMp3);
    env->ReleaseStringUTFChars(jInputPath, cInput);
    env->ReleaseStringUTFChars(jMp3Path, cMp3);
    nowConvertBytes = -1;
}

6、剩下就是调用了

/**
     * 开始录音
     * @param mFlag
     */
    public void recode(int mFlag){
        if(mState != -1){
            Log.e(mState+"1", "mState: "+mState );
            Message msg = new Message();
            Bundle b = new Bundle();// 存放数据
            b.putInt("cmd",CMD_RECORDFAIL);
            b.putInt("msg", ErrorCode.E_STATE_RECODING);
            msg.setData(b);
            uiHandler.sendMessage(msg); // 向Handler发送消息,更新UI
            return;
        }
        int mResult = -1;
        AudioRecorderWav mRecord_1 = AudioRecorderWav.getInstance();
        mResult = mRecord_1.startRecordAndFile(MainActivity.this);
        if(mResult == ErrorCode.SUCCESS){
            mState = mFlag;
            uiThread = new UIThread();
            new Thread(uiThread).start();
        }else{
            Message msg = new Message();
            Bundle b = new Bundle();// 存放数据
            b.putInt("cmd",CMD_RECORDFAIL);
            b.putInt("msg", mResult);
            msg.setData(b);
            uiHandler.sendMessage(msg); // 向Handler发送消息,更新UI
        }
    }

可能遇到的问题:

rg.gradle.api.internal.tasks.compile.CompilationFailedException:
Compilation failed

Compilation failed; see the compiler error output for details.

解决过程
terminal 输入
gradlew compileDebugSources
查看错误信息

代码下载地址
TestMp3

参考文章:
教你如何使用Android NDK实现一个MP3转码库
Android NDK开发(六)——使用开源LAME转码mp3

应用界面如下
首页
开始录音
停止录音
转码结束

猜你喜欢

转载自blog.csdn.net/u013009808/article/details/81806891