尊重原创,这篇文章是我转载的原文地址 http://blog.csdn.net/xyz_lmn/article/details/8013490

***********************************************************************

* 转载务必在明显处注明:http://blog.csdn.net/xyz_lmn

* 作者:张兴业

* 邮箱:xy-zhang@163.com

***********************************************************************

以前在应用中使用到了Speex编解码,近来总结了一下Speex在Android上的实现。Speex是一套主要针对语音的开源免费,无专利保护的音频压缩格式。Speex工程着力于通过提供一个可以替代高性能语音编解码来降低语音应用输入门槛 。另外,相对于其它编解码,Speex也很适合网络应用,在网络应用上有着自己独特的优势。同时,Speex还是GNU工程的一部分,在改版的BSD协议中得到了很好的支持。Speex是基于CELP并且专门为码率在2-44kbps的语音压缩而设计的。Speex源码是基于c语音实现的(也有Java实现,效率相对较低)。

1、去Speex官网下载最新Speex源码。

2、创建新的android工程,并创建jni文件夹。

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

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

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

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

[plain] view plain copy print ?
  1. APP_ABI := armeabi armeabi-v7a
APP_ABI := armeabi armeabi-v7a  

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

[html] view plain copy print ?
  1. 01.#ifndef __SPEEX_TYPES_H__
  2. 02.#define __SPEEX_TYPES_H__
  3. 03.typedef short spx_int16_t;
  4. 04.typedef unsigned short spx_uint16_t;
  5. 05.typedef int spx_int32_t;
  6. 06.typedef unsigned int spx_uint32_t;
  7. 07.#endif
01.#ifndef __SPEEX_TYPES_H__
02.#define __SPEEX_TYPES_H__
03.typedef short spx_int16_t;
04.typedef unsigned short spx_uint16_t;
05.typedef int spx_int32_t;
06.typedef unsigned int spx_uint32_t;
07.#endif

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

[cpp] view plain copy print ?
  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_trunkbow_speextest_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_trunkbow_speextest_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_trunkbow_speextest_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_trunkbow_speextest_Speex_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_trunkbow_speextest_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. }
#include <jni.h>#include <string.h>
#include <unistd.h>#include <speex/speex.h>static int codec_open = 0;static int dec_frame_size;
static int enc_frame_size;static SpeexBits ebits, dbits;
void *enc_state;
void *dec_state;static JavaVM *gJavaVM;extern "C"
JNIEXPORT jint JNICALL Java_com_trunkbow_speextest_Speex_open(JNIEnv *env, jobject obj, jint compression) {int tmp;if (codec_open++ != 0)return (jint)0;speex_bits_init(&ebits);speex_bits_init(&dbits);enc_state = speex_encoder_init(&speex_nb_mode);dec_state = speex_decoder_init(&speex_nb_mode);tmp = compression;speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &tmp);speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &enc_frame_size);speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &dec_frame_size);return (jint)0;
}extern "C"
JNIEXPORT jint Java_com_trunkbow_speextest_Speex_encode(JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {jshort buffer[enc_frame_size];jbyte output_buffer[enc_frame_size];int nsamples = (size-1)/enc_frame_size + 1;int i, tot_bytes = 0;if (!codec_open)return 0;speex_bits_reset(&ebits);for (i = 0; i < nsamples; i++) {env->GetShortArrayRegion(lin, offset + i*enc_frame_size, enc_frame_size, buffer);speex_encode_int(enc_state, buffer, &ebits);}//env->GetShortArrayRegion(lin, offset, enc_frame_size, buffer);//speex_encode_int(enc_state, buffer, &ebits);tot_bytes = speex_bits_write(&ebits, (char *)output_buffer,enc_frame_size);env->SetByteArrayRegion(encoded, 0, tot_bytes,output_buffer);return (jint)tot_bytes;
}extern "C"
JNIEXPORT jint JNICALL Java_com_trunkbow_speextest_Speex_decode(JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {jbyte buffer[dec_frame_size];jshort output_buffer[dec_frame_size];jsize encoded_length = size;if (!codec_open)return 0;env->GetByteArrayRegion(encoded, 0, encoded_length, buffer);speex_bits_read_from(&dbits, (char *)buffer, encoded_length);speex_decode_int(dec_state, &dbits, output_buffer);env->SetShortArrayRegion(lin, 0, dec_frame_size,output_buffer);return (jint)dec_frame_size;
}extern "C"
JNIEXPORT jint JNICALL Java_com_trunkbow_speextest_Speex_getFrameSize(JNIEnv *env, jobject obj) {if (!codec_open)return 0;return (jint)enc_frame_size;}extern "C"
JNIEXPORT void JNICALL Java_com_trunkbow_speextest_Speex_close(JNIEnv *env, jobject obj) {if (--codec_open != 0)return;speex_bits_destroy(&ebits);speex_bits_destroy(&dbits);speex_decoder_destroy(dec_state);speex_encoder_destroy(enc_state);
}

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

[java] view plain copy print ?
  1. package com.trunkbow.speextest;
  2. public 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. }
package com.trunkbow.speextest;public class Speex {/* quality * 1 : 4kbps (very noticeable artifacts, usually intelligible) * 2 : 6kbps (very noticeable artifacts, good intelligibility) * 4 : 8kbps (noticeable artifacts sometimes) * 6 : 11kpbs (artifacts usually only noticeable with headphones) * 8 : 15kbps (artifacts not usually noticeable) */  private static final int DEFAULT_COMPRESSION = 8;   Speex() {  }  public void init() {  load();   open(DEFAULT_COMPRESSION);   }  private void load() {  try {  System.loadLibrary("speex");  } catch (Throwable e) {  e.printStackTrace();  }  }  public native int open(int compression);  public native int getFrameSize();  public native int decode(byte encoded[], short lin[], int size);  public native int encode(short lin[], int offset, byte encoded[], int size);  public native void close();
}

9、使用cygwin编译,生成so文件。

参考:

http://code.google.com/p/android-recorder/downloads/list  这个是一个android recorder ,使用speex编码(这个例子我在转载时就不能用了 ),

音频压缩工具——Speex的使用相关推荐

  1. 音频压缩工具——Speex的使用(AndroidiOS语音录音技术预演)

    要在Android/iOS端实现语音对讲,原型为微信与米聊,开始预演所用技术,找到以下资料. 在Android开发中,需要录音并发送到对方设备上.这时问题来了,手机常会是GPRS.3G等方式上网,所以 ...

  2. 音频压缩SPEEX应用,对讲机

    音频压缩SPEEX应用,对讲机 转载于:https://www.cnblogs.com/LittleTiger/p/10979563.html

  3. 音频编码-speex库的使用方法

    音频编码-speex库的使用方法 Speex是近年来开发出的一套功能强大的语音引擎,能够实现高质量和低比特率的编码.它不仅提供了基于码激励线性预测(CELP)算法的编/解码模块,而且在其最新发布的版本 ...

  4. php 调用speex解码库,音频算法speex中的aec分析以及解析

    算法原理: Speex的AEC是以NLMS(Normalized Least Mean Square)为基础,用MDF(multidelay block frequency domain)频域实现,最 ...

  5. node.js 用typescript实现 图片,音频压缩工具

    首先让美术爸爸,帮给导出两张图片,分别为jpg和png格式 我们再来看看压缩前后的图片和音频质量,大小 我们发现图片质量不变,内存却减少了很多 我们再从网上下载一首笔主喜欢听的歌曲来压缩一下试试 我们 ...

  6. 采集音频和摄像头视频并实时H264编码及AAC编码

    0. 前言 我在前两篇文章中写了DirectShow捕获音视频然后生成avi,再进行264编码的方法.那种方法有一些局限性,不适合实时性质的应用,如:视频会议.视频聊天.视频监控等.本文所使用的技术, ...

  7. 采集音频和摄像头视频并实时H264编码及AAC编码[转]

    0. 前言 我在前两篇文章中写了DirectShow捕获音视频然后生成avi,再进行264编码的方法.那种方法有一些局限性,不适合实时性质的应用,如:视频会议.视频聊天.视频监控等.本文所使用的技术, ...

  8. Speex 一个开源的声学回声消除器(Acoustic Echo Cancellation)

    在一般的VOIP软件或视频会议系统中,假设我们只有A和B两个人在通话,首先,A的声音传给B,B然后用喇叭放出来,而这时B的MIC呢则会采集到喇叭放出来的声音,然后传回给A,如果这个传输的过程中时延足够 ...

  9. 音频编辑开发SDK Audio DJ Studio for .NET Crack

    11.7版本--Audio DJ Studio for .NET是 MultiMedia Soft 开发的 .NET Windows Forms 自定义控件,可以轻松地向使用Microsoft Vis ...

最新文章

  1. centos查看特定程序占用端口情况
  2. Interview:算法岗位面试—11.15下午上海某航天***公司(国企)技术面之工业机器视觉认知、计算机视觉算法的理解、目标检测相关项目案例
  3. 3DSlicer9:FAQ-3
  4. AutoDim:自动Embedding维度寻优,如何节省70%的存储空间同时还能大幅提效?
  5. 计算机网络资料篇(二)——快速理解网络协议
  6. php js 复选框选中,为每个选中的复选框显示相同的一组问题。 (PHP和JS / Jquery)...
  7. 你知道考的是平方数吗(记洛谷P1876题RE+WA的经历,Java语言描述)
  8. 【Interfacenavigation】按钮(29)
  9. 使用 Design Pattern Toolkit 进行模型驱动的开发入门
  10. 王道 计算机网络试题讲解_王道考研 计算机网络(7)学习笔记
  11. matlab信号探测,信号检测与估matlab仿真报告.doc
  12. mtk开机声音与关机声音修改(原创)
  13. 关于STC8H8K64U单片机IAP升级过程
  14. 基于HTML+CSS+JavaScript的在线图书阅读网页设计
  15. 如何零成本实现微信公众号自助查券返利机器人(六)
  16. 金弘同创:拼多多怎么退保证金
  17. 微信如何群发不封号?
  18. Pandas数据可视化的备忘录
  19. linux查看进程并kill
  20. 3.高精度加法(使用C++的string实现高精度加法运算的实例代码)包含auto解决办法

热门文章

  1. 可重构/大规模智能反射表面reconfigurable/large intelligent surface综述
  2. RHEL5使用3322动态域名方法
  3. Linux系统从零到高手的进阶心得
  4. 【巧用dm工具解决硬盘低格问题】
  5. 2020美团面试真题解析
  6. nvidia控制面板打不开解决方法教学
  7. 表格标题中方正小标宋简体为什么显示不一样?
  8. math_三角升幂/降幂/微积分公式填空
  9. 岁月的剪影【三月dayday欢乐】
  10. 如何成为优秀开发人员 系列文章 - by 编程随想