http://blog.csdn.net/chenfeng0104/article/details/7088138
在Android开发中,需要录音并发送到对方设备上。这时问题来了,手机常会是GPRS、3G等方式上网,所以节省流量是非常关键的,使用Speex来压缩音频文件,可以将音频压文件小数倍。

1.去Speex官网下载最新Speex源码

2.创建一个新的应用(我创建的应用名为Audio),并创建一个jni目录($project/jni)。

3.把speex源码目录下的libspeex和include目录及其子目录文件全部拷贝到$project/jni目录下($project/jni/libspeex and $project/jni/include)。

4.在jni目录下新增Android.mk文件,编辑内容如下

  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE    := libspeex
  4. LOCAL_CFLAGS = -DFIXED_POINT -DUSE_KISS_FFT -DEXPORT="" -UHAVE_CONFIG_H
  5. LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
  6. LOCAL_SRC_FILES :=  \
  7. ./speex_jni.cpp \
  8. ./libspeex/bits.c \
  9. ./libspeex/buffer.c \
  10. ./libspeex/cb_search.c \
  11. ./libspeex/exc_10_16_table.c \
  12. ./libspeex/exc_10_32_table.c \
  13. ./libspeex/exc_20_32_table.c \
  14. ./libspeex/exc_5_256_table.c \
  15. ./libspeex/exc_5_64_table.c \
  16. ./libspeex/exc_8_128_table.c \
  17. ./libspeex/fftwrap.c \
  18. ./libspeex/filterbank.c \
  19. ./libspeex/filters.c \
  20. ./libspeex/gain_table.c \
  21. ./libspeex/gain_table_lbr.c \
  22. ./libspeex/hexc_10_32_table.c \
  23. ./libspeex/hexc_table.c \
  24. ./libspeex/high_lsp_tables.c \
  25. ./libspeex/jitter.c \
  26. ./libspeex/kiss_fft.c \
  27. ./libspeex/kiss_fftr.c \
  28. ./libspeex/lpc.c \
  29. ./libspeex/lsp.c \
  30. ./libspeex/lsp_tables_nb.c \
  31. ./libspeex/ltp.c \
  32. ./libspeex/mdf.c \
  33. ./libspeex/modes.c \
  34. ./libspeex/modes_wb.c \
  35. ./libspeex/nb_celp.c \
  36. ./libspeex/preprocess.c \
  37. ./libspeex/quant_lsp.c \
  38. ./libspeex/resample.c \
  39. ./libspeex/sb_celp.c \
  40. ./libspeex/scal.c \
  41. ./libspeex/smallft.c \
  42. ./libspeex/speex.c \
  43. ./libspeex/speex_callbacks.c \
  44. ./libspeex/speex_header.c \
  45. ./libspeex/stereo.c \
  46. ./libspeex/vbr.c \
  47. ./libspeex/vq.c \
  48. ./libspeex/window.c
  49. include $(BUILD_SHARED_LIBRARY)

5.在jni目录下新增Application.mk文件,编辑内容如下

  1. APP_ABI := armeabi armeabi-v7a

6.在$project/jni/include/speex/目录下新增speex_config_types.h文件,编辑内容如下

  1. #ifndef __SPEEX_TYPES_H__
  2. #define __SPEEX_TYPES_H__
  3. typedef short spx_int16_t;
  4. typedef unsigned short spx_uint16_t;
  5. typedef int spx_int32_t;
  6. typedef unsigned int spx_uint32_t;
  7. #endif

7.创建JNI包装类speex_jni.cpp,用来调用Speex中的C代码函数,编辑内容如下

  1. #include <jni.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <speex/speex.h>
  5. static int codec_open = 0;
  6. static int dec_frame_size;
  7. static int enc_frame_size;
  8. static SpeexBits ebits, dbits;
  9. void *enc_state;
  10. void *dec_state;
  11. static JavaVM *gJavaVM;
  12. extern "C"
  13. JNIEXPORT jint JNICALL Java_com_audio_Speex_open
  14. (JNIEnv *env, jobject obj, jint compression) {
  15. int tmp;
  16. if (codec_open++ != 0)
  17. return (jint)0;
  18. speex_bits_init(&ebits);
  19. speex_bits_init(&dbits);
  20. enc_state = speex_encoder_init(&speex_nb_mode);
  21. dec_state = speex_decoder_init(&speex_nb_mode);
  22. tmp = compression;
  23. speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &tmp);
  24. speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &enc_frame_size);
  25. speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &dec_frame_size);
  26. return (jint)0;
  27. }
  28. extern "C"
  29. JNIEXPORT jint Java_com_audio_Speex_encode
  30. (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {
  31. jshort buffer[enc_frame_size];
  32. jbyte output_buffer[enc_frame_size];
  33. int nsamples = (size-1)/enc_frame_size + 1;
  34. int i, tot_bytes = 0;
  35. if (!codec_open)
  36. return 0;
  37. speex_bits_reset(&ebits);
  38. for (i = 0; i < nsamples; i++) {
  39. env->GetShortArrayRegion(lin, offset + i*enc_frame_size, enc_frame_size, buffer);
  40. speex_encode_int(enc_state, buffer, &ebits);
  41. }
  42. //env->GetShortArrayRegion(lin, offset, enc_frame_size, buffer);
  43. //speex_encode_int(enc_state, buffer, &ebits);
  44. tot_bytes = speex_bits_write(&ebits, (char *)output_buffer,
  45. enc_frame_size);
  46. env->SetByteArrayRegion(encoded, 0, tot_bytes,
  47. output_buffer);
  48. return (jint)tot_bytes;
  49. }
  50. extern "C"
  51. JNIEXPORT jint JNICALL Java_com_audio_Speex_decode
  52. (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {
  53. jbyte buffer[dec_frame_size];
  54. jshort output_buffer[dec_frame_size];
  55. jsize encoded_length = size;
  56. if (!codec_open)
  57. return 0;
  58. env->GetByteArrayRegion(encoded, 0, encoded_length, buffer);
  59. speex_bits_read_from(&dbits, (char *)buffer, encoded_length);
  60. speex_decode_int(dec_state, &dbits, output_buffer);
  61. env->SetShortArrayRegion(lin, 0, dec_frame_size,
  62. output_buffer);
  63. return (jint)dec_frame_size;
  64. }
  65. extern "C"
  66. JNIEXPORT jint JNICALL Java_com_audio_getFrameSize
  67. (JNIEnv *env, jobject obj) {
  68. if (!codec_open)
  69. return 0;
  70. return (jint)enc_frame_size;
  71. }
  72. extern "C"
  73. JNIEXPORT void JNICALL Java_com_audio_Speex_close
  74. (JNIEnv *env, jobject obj) {
  75. if (--codec_open != 0)
  76. return;
  77. speex_bits_destroy(&ebits);
  78. speex_bits_destroy(&dbits);
  79. speex_decoder_destroy(dec_state);
  80. speex_encoder_destroy(enc_state);
  81. }

8.在Java层创建Speex工具类,内容如下

  1. package com.audio;
  2. class Speex  {
  3. /* quality
  4. * 1 : 4kbps (very noticeable artifacts, usually intelligible)
  5. * 2 : 6kbps (very noticeable artifacts, good intelligibility)
  6. * 4 : 8kbps (noticeable artifacts sometimes)
  7. * 6 : 11kpbs (artifacts usually only noticeable with headphones)
  8. * 8 : 15kbps (artifacts not usually noticeable)
  9. */
  10. private static final int DEFAULT_COMPRESSION = 8;
  11. Speex() {
  12. }
  13. public void init() {
  14. load();
  15. open(DEFAULT_COMPRESSION);
  16. }
  17. private void load() {
  18. try {
  19. System.loadLibrary("speex");
  20. } catch (Throwable e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. public native int open(int compression);
  25. public native int getFrameSize();
  26. public native int decode(byte encoded[], short lin[], int size);
  27. public native int encode(short lin[], int offset, byte encoded[], int size);
  28. public native void close();
  29. }

9.打开cygwin工具,切换到项目目录(我项目是在F:\workspace\Audio),输入$NDK/ndk-build

cygwin工具的安装与配置,可以看这篇文章——使用NDK与环境搭建

会在项目中生成libs目录和libspeex.so文件,这就是Speex类中System.loadLibrary("speex");代码引用的,系统会根据操作系统由"speex"找到对应的动态库libspeex.so,Windows下是.dll文件,linux下是.so文件。

当前,我的项目结构如下图

Speex for Android的更多相关文章

  1. speex编解码在android上实现

    以前在应用中使用到了Speex编解码,近来总结了一下Speex在android上的实现.Speex是一套主要针对语音的开源免费,无专利保护的音频压缩格式.Speex工程着力于通过提供一个可以替代高性能 ...

  2. Android中使用speex将PCM录音格式转Wav格式

    Android中使用speex将PCM录音格式转Wav格式 2013-09-17 17:24:00|  分类: android |  标签:android  speex  wav  |举报|字号 订阅 ...

  3. Android - 基于 Speex 的高度封装语音库,0 耦合使用

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  4. Android 基于 Speex 的高度封装语音库,0 耦合,没三方jar包

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  5. Android 开发:开源库Speex支持arm64的动态库文件

    随着处理器制造工艺的不断进步,和Android系统的不断发展,最近出了arm64-v8a的架构,由于项目中用到了speex的第三方语音编解码的动态库,其他架构的处理器暂不用说,一切正常,唯独到arm6 ...

  6. Android 5.0 到 Android 6.0 + 的深坑之一 之 .so 动态库的适配

    (原创:http://www.cnblogs.com/linguanh) 目录: 前序 一,问题描述 二,为何会如此"无情"? 三,目前存在该问题的知名SDK 四,解决方案,1 对 ...

  7. Android源码目录结构详解(转载)

    转自:http://blog.csdn.net/xiangjai/article/details/9012387 在学习Android的过程中,学习写应用还好,一开始不用管太多代码,直接调用函数就可以 ...

  8. android源码的目录结构

    android源码的目录结构 [以下网络摘抄] |-- Makefile ! l/ a5 n% S% @- `0 d# z# a$ P4 V3 o7 R|-- bionic              ...

  9. Android 4.0 源代码结构

    Android源码的第一级目录结构   Android/abi (abi相关代码.ABI:application binary interface,应用程序二进制接口)   Android/bioni ...

随机推荐

  1. Cookie操作类 实现记住用户名和密码的功能

    import java.util.Hashtable;import java.util.Iterator;import java.util.Set;import javax.servlet.http. ...

  2. c#调用系统资源大集合-2

    public static void 打开格式化对话框() { Process.Start("rundll32.exe"," shell32.dll,SHFormatDr ...

  3. JQuery操作Ajax

    一.jQuery - AJAX 简介 AJAX = 异步 JavaScript 和 XML(Asynchronous JavaScript and XML). AJAX 是与服务器交换数据的艺术,它在 ...

  4. content management system

    Defination of CMS: The definition of a CMS is an application (more likely web-based), that provides ...

  5. HDU 3573 Buy Sticks (逻辑)

    题意:a,b,c三种棍子长度分别为20,28,32,现需要这三种棍子数根,欲买长为75的棍子来剪成这三种(不够长的就废弃) ,问需要买多少根. 思路:将所有棍子尽可能和其他搭配起来,使得数量减到最少. ...

  6. android 相对布局

    RelativeLayout布局 android:layout_marginTop="25dip" //顶部距离 android:gravity="left" ...

  7. linux的命令(1)

    系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...

  8. Hive技术文档

    Hive是什么? Hive是蜂房的意思,为什么hadoop上的这层数据仓库叫Hive? 因为生物学上蜂房是一个结构相当精良的建筑,取名Hive足见则个数据仓库在数据存储上也是堪称精良的.Hive是Fa ...

  9. nodejs学习--express篇

    express篇:http://www.runoob.com/nodejs/nodejs-express-framework.html Express 提供了内置的中间件 express.static ...

  10. javac 命令用法

    引用自己写的Class 在java中手动编译时,总提示找不到类,调试成功后,特把目录结构与编译成功的命令列出: 样例一: 文件名 MessageStore.java Hello.java 源码 pac ...