码迷,mamicode.com
首页 > 移动开发 > 详细

Android JNI Lame编解码实现wav到MP3的转换

时间:2015-08-13 12:10:14      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:native   编辑器   android   jni   lame   

1、JNI简介
JNI全称为Java Native Interface(JAVA本地调用)。从Java1.1开始,JNI成为java平台的一部分,它允许Java代码和其他语言写的代码(如C&C++)进行交互。并非从Android发布才引入JNI的概念的。
2、JNI与NDK
简单来说,Android的NDK提供了一些交叉编译工具链和Android自带的库,这些Android的库可以让开发者在编写本地语言的程序时调用。而NDK提供的交叉编译工具链就对已经编写好的C&C++代码进行编译,生成库。
当然了,你也可以自己搭建交叉编译环境,而不用NDK的工具和库。然后生成库,只要规范操作,一样可以生成能让JAVA层成功调用的库文件的。

    使用JNI技术,其实就是在Java程序中,调用C语言的函数库中提供的函数,来完成一些Java语言无法完成的任务。由于Java语言和C语言结构完全不相同,因此若想让它们二者交互,则需要制定一系列的规范。JNI就是这组规范,此时    Java只和JNI交互,而由JNI去和C语言交互。

JNI技术分为两部分:Java端和C语言端。且以Java端为主导。
|- 首先,Java程序员在Java端定义一些native方法,并将这些方法以C语言头文件的方式提供给C程序员。
|- 然后,C程序员使用C语言,来实现Java程序员提供的头文件中定义的函数。
|- 接着,C程序员将函数打包成一个库文件,并将库文件交给Java程序员。

在Java程序执行的时候,若在某个类中调用了native方法,则虚拟机会通过JNI来转调用库文件中的C语言代码。提示:C代码最终是在Linux进程中执行的,而不是在虚拟机中。

下面是一个Android调用JNI实现通过LAME转码器实现wav格式到MP3格式的转换.

准备:首先下载lame源码文件。
需要三个条件 :cgywin,cdt,ndk才能实现JNI的开发。
开发lame需要从http://lame.sourceforge.net/选择Using Lame 下载源代码。

新建工程
1、Android主界面布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >



    <EditText
        android:id="@+id/editText1"
        android:hint="源wav文件的路径"
        android:text="/sdcard/118/ccc.wav"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

    </EditText>

    <EditText
        android:id="@+id/editText2"
                android:hint="目标MP3文件的路径"
        android:layout_width="match_parent"
                android:text="/sdcard/118/ccccc.mp3"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="转化" 
        android:onClick="convert"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="获取lame版本号"
        android:onClick="getversion"
         />

</LinearLayout>

首先是建立JNI目录

1、把lameC语言源码导入jni中
2、创建Android.mk文件

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := Hello
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 Hello.c
LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

3、编写C语言文件

#include <stdio.h>
#include <jni.h>
#include "com_example_ndkpassdata_DataProvider.h"
#include <android/log.h>
#include<malloc.h>

#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

char* Jstring2CStr(JNIEnv* env, jstring jstr) {
    char* rtn = NULL;
    jclass clsstring = (*env)->FindClass(env, "java/lang/String"); //String
    jstring strencode = (*env)->NewStringUTF(env, "GB2312"); // 得到一个java字符串 "GB2312"
    jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
            "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
    jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
            strencode); // String .getByte("GB2312");
    jsize alen = (*env)->GetArrayLength(env, barr); // byte数组的长度
    jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char*) malloc(alen + 1);         //"\0"
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (*env)->ReleaseByteArrayElements(env, barr, ba, 0);  //
    return rtn;
}

JNIEXPORT jint JNICALL Java_com_example_ndkpassdata_DataProvider_add(
        JNIEnv *env, jobject obj, jint x, jint y) {
    LOGD("x=%d", x);
    LOGD("y=%d", y);
    return x + y;
}
JNIEXPORT jstring JNICALL Java_com_example_ndkpassdata_DataProvider_sayHelloInc(
        JNIEnv *env, jobject obj, jstring jstr) {
    char *cstr = Jstring2CStr(env, jstr);
    LOGD("cstr=%s", cstr);
    char arr[7] = { ‘ ‘, ‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘, ‘/0‘ };
    strcat(cstr, arr);
    LOGD("newcstr=%s", cstr);
    return (*env)->NewStringUTF(env, cstr);
}

JNIEXPORT jintArray JNICALL Java_com_example_ndkpassdata_DataProvider_intMethod(
        JNIEnv *env, jobject obj, jintArray arr) {
    int len = (*env)->GetArrayLength(env, arr);
    LOGD("SHUZU length-=%d", len);
    jint *intarr = (*env)->GetIntArrayElements(env, arr, 1);
    int i = 0;
    for (; i < len; i++) {
        LOGD("intarr[%d]=%d", i, intarr[i]);
        *(intarr + i) += 10;
        //intarr[i] += 10;
    }
    (*env)->ReleaseIntArrayElements(env, arr, intarr, len);
    return arr;
}

JNIEXPORT jint JNICALL Java_com_example_ndkpassdata_DataProvider_sub(
        JNIEnv *env, jclass clazz, jint x, jint y) {
    LOGD("x=%d", x);
    LOGD("Y=%d", y);
    return x - y;
}

4、使用cgywin工具进行ndk-build编译
成功之后
5、编写Activity文件

package cn.itcast.lame;

import java.io.File;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;


public class LameActivity extends Activity {

    private EditText et_wav;
    private EditText et_mp3;
    private ProgressDialog pd;
    public native void convertmp3(String wav,String mp3);
    public native String getLameVersion();
    public native void stop();
    static{
        System.loadLibrary("Hello");
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        et_wav =  (EditText) this.findViewById(R.id.editText1);
        et_mp3 = (EditText) this.findViewById(R.id.editText2);
        pd = new ProgressDialog(this);
    }


    public void convert(View view){
        final String mp3name = et_mp3.getText().toString().trim();
        final String wavname = et_wav.getText().toString().trim();
        File file = new File(wavname);
        int size = (int) file.length();
        System.out.println("文件大小 "+ size);
        if("".equals(mp3name)||"".equals(wavname)){
            Toast.makeText(this, "路径不能为空", 1).show();
            return;
        }
        //convertmp3(wavname,mp3name);
        pd.setMessage("转换中....");
        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        pd.setMax(size); // 设置进度条的最大值
        //pd.setCancelable(false);
        pd.show();
        new Thread(){

            @Override
            public void run() {
                convertmp3(wavname,mp3name);
                pd.dismiss();
            }

        }.start();
    }

    public void setConvertProgress(int progress){
        pd.setProgress(progress);
    }


    public void getversion(View view){
        String version = getLameVersion();
        Toast.makeText(this, version, 0).show();
    }
}

6、运行程序

源码地址:
http://download.csdn.net/detail/kai46385076/8999373

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android JNI Lame编解码实现wav到MP3的转换

标签:native   编辑器   android   jni   lame   

原文地址:http://blog.csdn.net/kai46385076/article/details/47609495

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!