Android录音转为MP2的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012741756/article/details/64520183

Android录音转为MP2的实现

利用Android提供的AudioRecord类以及开源编码库twolame,实现了android手机边录音边编码,录音完成直接得到MP2音频文件。由于Android本身不支持MP2的编码,所以要借助NDK将mp2编码库twolame移植到android工程中。MP
2的帧格式参见另一篇博文MP2帧格式介绍

源码下载地址

http://download.csdn.net/detail/u012741756/9789885

  • 开发环境:Windows
  • 开发工具:Android Studio 2.2.3和NDK
  • 开发包:twolame 0.3.13 twolame下载地址

一 设计思路

利用Android提供的AudioRecord类,采集声音样本PCM数据,MP2规定1152个声音样本构成一帧,所以在新的线程中循环读1152个样本数据,当读到数据后立即进行编码,将1152个PCM数据转为一帧MP2,保存到文件中,录音结束直接得到MP2音频文件。其中编码部分采用开源MP2编码库twolame,利用JNI将twolame整合到Android工程中。如果想存为MP3音频文件,将twolame编码库换成lame编码库,再修改一些地方即可。

二 twolame的Android平台移植,生成.so文件

2.1 新建Android工程

  • 新建android empty project,工程目录切换到Project视图,app右键新建jni文件夹,如下图:
    新建JNI文件夹

  • 找到你的工程目录,比如我的在F:\AndroidStudioProjects\RecMicToMp2Doc\app\src\main\jni,将twolame 0.3.13文件夹下的libtwolame文件夹拷贝到jni文件夹下,此时你的工程目录应该是这样子的:
    这里写图片描述

2.2 引用c代码,生成.so库

强大的JNI使得我们可以在Android中使用C/C++语言编写代码,JNI提供了一种方式使得在java中能够调用C/C++函数。大致意思就是通过编写符合JNI要求的C/C++代码,配合Android.mk和Application.mk,生成.so文件(动态链接库),例如本文生成了libmp2twolame.so,在java类中通过System.loadLibrary(“mp2twolame”);就能在这个java类中调用.so中包含的c函数了。

  • 编写twolame.java:详情参见源码。这个类里面包含了要用到的native方法,native方法的代码在后面的userTwolame.c中编写。
  • 生成头文件:在Android Studio的Terminal中,cd到java目录下,本例: cd F:\AndroidStudioProjects\RecMicToMp2Doc\app\src\main\java
    再输入命令:javah -jni com.example.administrator.recmictomp2doc.twolame
    即可得到com_example_administrator_recmictomp2doc_twolame.h头文件,打开这个头文件,可以看到Java_com_example_administrator_recmictomp2doc_twolame_init等方法名,这些方法名将在userTwolame.c的编写中用到,JNI要求userTwolame.c中的函数名必须与此相同,这是为什么要生成h头文件的原因。
  • 编写userTwolame.c
    在jni下新建C source file,命名为userTwolame,详情参见源码。
  • 编写Android.mk和Application.mk
    在jni目录下新建连个File,分别命名为Android.mk和Application.mk,代码如下,给出了注释便于理解。
LOCAL_PATH := $(call my-dir)  #给出当前文件的路径

include $(CLEAR_VARS) #把CLEAR_VARS变量所指向的脚本文件包含进来

LIBTWOLAME_DIR := libtwolame

LOCAL_MODULE    := mp2twolame #生成的so文件名

#将要编译打包进so中的源代码文件
LOCAL_SRC_FILES := $(LIBTWOLAME_DIR)/ath.c $(LIBTWOLAME_DIR)/availbits.c $(LIBTWOLAME_DIR)/bitbuffer.c $(LIBTWOLAME_DIR)/crc.c $(LIBTWOLAME_DIR)/dab.c $(LIBTWOLAME_DIR)/encode.c $(LIBTWOLAME_DIR)/energy.c $(LIBTWOLAME_DIR)/fft.c $(LIBTWOLAME_DIR)/get_set.c $(LIBTWOLAME_DIR)/mem.c $(LIBTWOLAME_DIR)/psycho_0.c $(LIBTWOLAME_DIR)/psycho_1.c $(LIBTWOLAME_DIR)/psycho_2.c $(LIBTWOLAME_DIR)/psycho_3.c $(LIBTWOLAME_DIR)/psycho_4.c $(LIBTWOLAME_DIR)/psycho_n1.c $(LIBTWOLAME_DIR)/subband.c $(LIBTWOLAME_DIR)/twolame.c $(LIBTWOLAME_DIR)/util.c userTwoLame.c

include $(BUILD_SHARED_LIBRARY)

Application.mk中代码如下,armeabi改为all即生成所有平台的so库:

APP_ABI :=armeabi

此时jni目录下应该包含这些文件:
这里写图片描述

  • 编译生成so,在Android Studio的Terminal中先定位到jni文件夹所在目录,本例输入命令:cd F:\AndroidStudioProjects\RecMicToMp2Doc\app\src\main
    然后输入命令 ndk-build,编译成功如下:
    这里写图片描述
    然后找到app/src/main下生成的libs文件夹,重命名为jniLibs。
    在gradle.properties 文件末尾加入一句代码():android.useDeprecatedNdk=true
    因为存在c文件,所以工程编译会报错,所以要在app(build.gradle)的android标签下加入
//remove the default jni source code directory
sourceSets {
    main {
        jni.srcDirs = []
    }
}
  • 在AndroidMaitfest.xml中开启麦克风权限和存储权限:
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • 至此,工程可以编译成功,由于使用了麦克风,不要在模拟机上运行,直接在真机上运行。

三 总结

本文对代码细节方面没有过多解释,源码中有详细注释,看源码就能理解。本文重点在于学会在Android Studio下使用C/C++代码,对于新手来说,值得参考。

猜你喜欢

转载自blog.csdn.net/u012741756/article/details/64520183