MP3 录音开发

NDK环境配置

这里主要是介绍Eclipse的NDK开发环境配置,至于Android Studio的配置比较简单,自行Google吧。。。

下载安装CDT

多的不解释,Eclipse插件安装

https://dl.google.com/android/eclipse/

安装完成重启即可

下载安装NDK

同样,上官网下载相应的NDK

NDK下载地址

下载完成解压放在适当的目录下

若出现下面的情况

说明NDK版本过高,请下载低一些的版本,正确后如下

到此NDK开发环境就配置完成了,当然这是基于安装的jdk版本是1.7以上的情况,若是1.6的话,还要安装cygwin,当然也还有其他一些配置

实在是必须在1.6环境下进行NDK开发,可以看这篇文章
Android NDK开发(一)——环境搭建

LAME编译

Lame在线下载地址

  1. 新建的项目根目录下建立jni目录
  2. 解压下载的lame-3.99.5.tar.gz文件,拷贝libmp3lame文件夹下的文件到jni目录下
  3. 拷贝 lame.h到jni目录 (include目录下)
  4. 删除非.c /.h文件
  5. 编辑 jni/util.h,在574行把 extern ieee754_float32_t fast_log2(ieee754_float32_t x);替换为 extern float fast_log2(float x);。
  6. 创建Android.mk
    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE := mp3lame

    LOCAL_SRC_FILES := bitstream.c fft.c id3tag.c mpglib_interface.c presets.c quantize.c reservoir.c tables.c util.c VbrTag.c encoder.c gain_analysis.c lame.c newmdct.c psymodel.c quantize_pvt.c set_get.c takehiro.c vbrquantize.c version.c lame_util.c

    LOCAL_LDLIBS += -llog

    include $(BUILD_SHARED_LIBRARY)

  7. 创建Application.mk

    APP_PLATFORM := android-9

    APP_ABI := all //输出的.so版本,all表示全部

    APP_CFLAGS += -DSTDC_HEADERS

在Java层编写调用C端的代码

    public class LameUtil {
    
    
        static{
            System.loadLibrary("mp3lame");
        }

    /**
     * Initialize LAME.
     */
    public native static void init(int inSamplerate, int inChannel,
                int outSamplerate, int outBitrate, int quality);


    /**
     * Encode buffer to mp3.
     */
    public native static int encode(short[] bufferLeft, short[] bufferRight,
                                    int samples, byte[] mp3buf);

    /**
     * Flush LAME buffer.
     */
    public native static int flush(byte[] mp3buf);

    /**
     * Close LAME.
     */
    public native static void close();
    }

编译头文件

jdk_1.7 及以上版本直接到项目src目录,以下到class目录

如此成功后会在jni目录下生成如下文件

看下生成的文件内容


    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_autolink_mp3library_util_LameUtil */

    #ifndef _Included_com_autolink_mp3library_util_LameUtil
    #define _Included_com_autolink_mp3library_util_LameUtil
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_autolink_mp3library_util_LameUtil
     * Method:    init
     * Signature: (IIIII)V
     */
    JNIEXPORT void JNICALL Java_com_autolink_mp3library_util_LameUtil_init
      (JNIEnv *, jclass, jint, jint, jint, jint, jint);

    /*
     * Class:     com_autolink_mp3library_util_LameUtil
     * Method:    encode
     * Signature: ([S[SI[B)I
     */
    JNIEXPORT jint JNICALL Java_com_autolink_mp3library_util_LameUtil_encode
      (JNIEnv *, jclass, jshortArray, jshortArray, jint, jbyteArray);

    /*
     * Class:     com_autolink_mp3library_util_LameUtil
     * Method:    flush
     * Signature: ([B)I
     */
    JNIEXPORT jint JNICALL Java_com_autolink_mp3library_util_LameUtil_flush
      (JNIEnv *, jclass, jbyteArray);

    /*
     * Class:     com_autolink_mp3library_util_LameUtil
     * Method:    close
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_com_autolink_mp3library_util_LameUtil_close
      (JNIEnv *, jclass);

    #ifdef __cplusplus
    }
    #endif
    #endif

编写本地C语言代码,实现音频文件的转码


    #include "lame.h"
    #include "com_autolink_mp3library_util_LameUtil.h"
    #include <stdio.h>
    #include <jni.h>

    static lame_global_flags *lame = NULL;

    JNIEXPORT void JNICALL Java_com_autolink_mp3library_util_LameUtil_init(
            JNIEnv *env, jclass cls, jint inSamplerate, jint inChannel, jint outSamplerate, jint outBitrate, jint quality) {
        if (lame != NULL) {
            lame_close(lame);
            lame = NULL;
        }
        lame = lame_init();
        lame_set_in_samplerate(lame, inSamplerate);
        lame_set_num_channels(lame, inChannel);//杈撳叆娴佺殑澹伴亾
        lame_set_out_samplerate(lame, outSamplerate);
        lame_set_brate(lame, outBitrate);
        lame_set_quality(lame, quality);
        lame_init_params(lame);
    }

    JNIEXPORT jint JNICALL Java_com_autolink_mp3library_util_LameUtil_encode(
            JNIEnv *env, jclass cls, jshortArray buffer_l, jshortArray buffer_r,
            jint samples, jbyteArray mp3buf) {
        jshort* j_buffer_l = (*env)->GetShortArrayElements(env, buffer_l, NULL);

        jshort* j_buffer_r = (*env)->GetShortArrayElements(env, buffer_r, NULL);

        const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
        jbyte* j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);

        int result = lame_encode_buffer(lame, j_buffer_l, j_buffer_r,
                samples, j_mp3buf, mp3buf_size);

        (*env)->ReleaseShortArrayElements(env, buffer_l, j_buffer_l, 0);
        (*env)->ReleaseShortArrayElements(env, buffer_r, j_buffer_r, 0);
        (*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);

        return result;
    }

    JNIEXPORT jint JNICALL Java_com_autolink_mp3library_util_LameUtil_flush(
            JNIEnv *env, jclass cls, jbyteArray mp3buf) {
        const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
        jbyte* j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);

        int result = lame_encode_flush(lame, j_mp3buf, mp3buf_size);

        (*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);

        return result;
    }

    JNIEXPORT void JNICALL Java_com_autolink_mp3library_util_LameUtil_close
    (JNIEnv *env, jclass cls) {
        lame_close(lame);
        lame = NULL;
    }

新建C++编译器

右键项目Properties->Builders在右边的选项卡中点击“New”新建编译器(选择Program):

配置Main、Refresh和Build Options选项卡,如图

如此之后,clean一下工程即会自动编译获得.so文件

最后给项目加上下面两个权限

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

如何使用呢


    package com.autolink.mp3library;

    import java.io.File;
    import java.io.IOException;

    import com.autolink.mp3library.util.MP3Recorder;

    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Environment;
    import android.view.View;
    import android.view.View.OnClickListener;


    public class MainActivity extends Activity {
    
    

        private MP3Recorder mRecorder = new MP3Recorder(new File(Environment.getExternalStorageDirectory(), "test.mp3"));

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            findViewById(R.id.StartButton).setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    try {
                        mRecorder.start();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });

            findViewById(R.id.StopButton).setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    mRecorder.stop();
                }
            });
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            mRecorder.stop();
        }

    }

参考链接:

http://blog.csdn.net/allen315410/article/details/42456661

http://blog.csdn.net/whurs/article/details/45487521

Android studio 可看下面这个

http://www.cnblogs.com/ct2011/p/4080193.html

猜你喜欢

转载自blog.csdn.net/hehota/article/details/69942080