Android libmp3lame详解
来源:互联网 发布:如何自学linux 编辑:程序博客网 时间:2024/05/03 06:04
转自:http://wenku.baidu.com/view/70cebd3e580216fc700afd51?from_page=view&from_mod=download
练习Jni项目
一 下载 lame-3.98.4.tar.gz
二 创建 android 项目 lame
创建jni目录 并
复制 lame-3.98.4 包下的libmp3lame 目录下的所有 .c和.h文件和 include目录下的lame.h
三 在jni目录下创建 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
include $(BUILD_SHARED_LIBRARY)
四, 编辑 jni/utils.h,
把 extern ieee754_float32_t fast_log2(ieee754_float32_t x); 替换为 extern float fast_log2(float x);
五 ndk-build
六 导入libmp3lame.so, 并创建native方法 然后生成头文件 cn_kq_lame_LameActivity.h
七 创建hello.c文件并将其加入Andorid.mk文件中的源代码位置后面, 然后按上面的步骤重新编译
好了我的测试通过 了, 现在来为它加入新的功能 mp3转码的功能
********************************************************************************
一 修改LameActivity 为其加入新的本地执行方法 并加入访问sdcard卡和外部存储权限
package cn.kq.lame;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/**
* @author zhaopan - 2011-10-5
*/
public class LameActivity extends Activity {
static{
System.loadLibrary("mp3lame");
}
EditText etInput;
EditText etOutput;
private ProgressDialog pd;
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
//主线程收到通知消毁对话框
pd.dismiss();
super.handleMessage(msg);
}
};
public native String getVersion();
public native void convert(String input, String output);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
etInput = (EditText) this.findViewById(R.id.input);
etOutput = (EditText) this.findViewById(R.id.output);
}
public void getVersion(View v){
Toast.makeText(this, getVersion(), 1).show();
}
//完成从源文件到目标文件的转换
public void convert(View v){
final String input = etInput.getText().toString();
final String output = etOutput.getText().toString();
//调用c代码来完成 文件的转换
pd = new ProgressDialog(this);
pd.setMessage("转换中");
pd.show();
//起动一个线程来完成 这个耗时的操作
new Thread(new Runnable(){
public void run() {
convert(input, output);
//转换工作完成 后发送一条消息到主线程
handler.sendEmptyMessage(0);
}
}).start();
}
}
<?xmlversion="1.0"encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="cn.kq.lame"
android:versionCode="1"
android:versionName="1.0">
<applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
<activityandroid:name=".LameActivity"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
<uses-sdkandroid:minSdkVersion="8"/>
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
</manifest>
二 产生新的头文件cn_kq_lame_LameActivity.h 并将其复制到jni目录下
三 为Android.mk文件加入日志处理的库文件并 修改 hello.c文件加入新的处理方法 然后重新编译
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 hello.c
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)
#include "lame.h"
#include "cn_kq_lame_LameActivity.h"
#include <jni.h>
#include<android/log.h>
#define LOG_TAG"System.out"
#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; //rtn 一块能够存放char类型内存的首地址
// 找到 jvm里面 String类
jclass clsstring = (*env)->FindClass(env,"java/lang/String");
// 创建一个jstring的字符串内容 GB2312
jstring strencode = (*env)->NewStringUTF(env,"GB2312");
// 寻找 String类的一个方法 getBytes getBytes方法的参数 Ljava/lang/String;
// getBytes 方法的返回值 [B
jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B");
// "String".getBytes("GB2312");
jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode);
//获取到barr的长度
jsize alen = (*env)->GetArrayLength(env,barr);
//获取到的jbyte数据放入到以ba为开始地址的内存空间中
jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
if(alen > 0)
{
rtn = (char*)malloc(alen+1); //new char[alen+1]; "\0" 字符串的结束
//内存拷贝的操作 ,
memcpy(rtn,ba,alen);
//给字符数组最后一个元素 表示字符串结束
rtn[alen]=0;
}
(*env)->ReleaseByteArrayElements(env,barr,ba,0);
return rtn;
}
JNIEXPORT jstring JNICALL Java_cn_kq_lame_LameActivity_getVersion
(JNIEnv * env, jobject obj){
//把 lame版本号返回给java
return (*env)->NewStringUTF(env, get_lame_version());
}
JNIEXPORT void JNICALL Java_cn_kq_lame_LameActivity_convert
(JNIEnv * env, jobject obj, jstring input, jstring output, jint channel , jint sample){
//把java的string类型的文件转化成c能识别的char字符串
char* inputfile = Jstring2CStr(env,input);
LOGI("%s",inputfile);
char* outputfile = Jstring2CStr(env,output);
LOGI("%s",outputfile);
FILE *pcm = fopen(inputfile, "rb");
FILE *mp3 = fopen(outputfile, "wb");
int read, write;
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short int pcm_buffer[PCM_SIZE*2];
unsigned char mp3_buffer[MP3_SIZE];
//初始化lame解码器
lame_t lame = lame_init();
// 设置音频的采样率
lame_set_in_samplerate(lame, 44100);
// 设置lame编码器的声道
lame_set_num_channels(lame,2);
// vbr 设置采样压缩格式
lame_set_VBR(lame, vbr_default);
//初始化lame的编码器
lame_init_params(lame);
LOGI("INIT LAME FININSH ");
do {
read = fread(pcm_buffer, 2*sizeof(shortint), PCM_SIZE, pcm);
//读出来的pcm数据放在 pcm_buffer里面
//从pcm文件里面读PCM_SIZE个 2*sizeof(short int)个数据,放倒pcm_buffer
if (read == 0)
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
else
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
//pcm_buffer 是pcm数据
//read /* number of samples per channel,
//mp3_buffer 编码后mp3数据
// 要写入多少个数据
fwrite(mp3_buffer, 1, write, mp3);
//mp3_buffer 缓冲区
// 1是一个字节
//write是要写的长度
//mp3 是写入的文件名
} while (read != 0);
LOGI("LAME ENCODE FININSH");
lame_close(lame);
fclose(mp3);
fclose(pcm);
}
四
由于后面在convert方法中多加了两个参数指定采样率和通道的入参来替换c代码中的 441000 和2
所以报了下面的错误 , 把那两个参数加入或删除就行了, 28和30的warning不用管。
- Android libmp3lame详解
- Android libmp3lame详解
- Building FFmpeg with libmp3lame for Android
- Building FFmpeg with libmp3lame for Android
- Android 采用libmp3lame录制MP3文件
- Android 使用libmp3lame开源库 解决录音文件转换成mp3文件
- Android变录音边转换为mp3格式的声音---libmp3lame库的使用
- ffmpeg开启libfdk_aac跟libmp3lame
- ffmpeg 安装libmp3lame 编码集
- 使用libmp3lame库编码mp3
- 使用libmp3lame库编码mp3
- Mac上编译 libmp3lame 并转转码
- 解决libmp3lame转换wav单声道变快
- 关于libmp3lame库的使用小记
- CentOS7源码安装MP3编码库libmp3lame
- 多媒体编程——编译libmp3Lame for ios armv7
- FFmpeg碰到安装libmp3lame后提示没有找到的问题解决
- IMX.6Q 移植FFmpeg libx264软件编码 libmp3lame
- shell-function
- Scale9Sprite
- WPF技术触屏上的应用系列(五): 图片列表异步加载、手指进行缩小、放大、拖动 、惯性滑入滑出等效果
- cocos2d-x AnchorPoint锚点
- Service层在分层中的作用
- Android libmp3lame详解
- HashMap,LinkedHashMap,TreeMap的区别
- Excel vba 求助。
- tiny4412 裸机程序 三、关闭看门狗和调用C程序
- STL常用知识
- Linux内核通用链表 <linux/list.h>阅读
- shell-case
- home键无反应分析处理(资料搜集)
- 四色电视:大趋势与微革命