Android语音文件speex编码解码(一)

【Android】Speex简易使用 speex是主要用于音频压缩,降噪;减少原始数据体积,提升各端数据传输效率,最后一次更新是在2016年,已被opus代替,该篇旨在记录对speex在android上的使用过程。 阅读详情

原文地址:https://blog.youkuaiyun.com/qq_29078329/article/details/56287338

最近项目需要实现功能:用户通过语音发大幕,语音文件压缩后发送到后台,后台解析生成文本,显示文字。Android中使用AudioRecord录音后的格式为pcm,要想播放需要转换格式,可以加入44字节的头转换为wav格式后播放,并且在网络上传输最好把音频压缩,压缩为speex文件方便传输,节省流量,下面讲解如何生成speex的so库,和怎样使用so库实现wav和spx文件之间转换。

 一、在speex官网点击打开链接下载speex源码

 

 

 二、解压缩speex-1.2rc2.tar.gz

三、创建Android项目SpeexAudio,切换到Project模式,创建jni文件夹,将include、libspeex拷贝到jni下;

在jni目录下新增Android.mk文件,复制如下内容,Android.mk中记录了待编译的源文件的路径;

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)/include
 
#LOCAL_SRC_FILES :=  
LOCAL_SRC_FILES := speex_jni.cpp \
		./libspeex/bits.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/filters.c \
		./libspeex/gain_table_lbr.c \
		./libspeex/gain_table.c \
		./libspeex/hexc_10_32_table.c \
		./libspeex/hexc_table.c \
		./libspeex/high_lsp_tables.c \
		./libspeex/kiss_fft.c \
		./libspeex/kiss_fftr.c \
		./libspeex/lpc.c \
		./libspeex/lsp_tables_nb.c \
		./libspeex/lsp.c \
		./libspeex/ltp.c \
		./libspeex/modes_wb.c \
		./libspeex/modes.c \
		./libspeex/nb_celp.c \
		./libspeex/quant_lsp.c \
		./libspeex/sb_celp.c \
		./libspeex/smallft.c \
		./libspeex/speex_callbacks.c \
		./libspeex/speex_header.c \
		./libspeex/speex.c \
		./libspeex/stereo.c \
		./libspeex/vbr.c \
		./libspeex/vorbis_psy.c \
		./libspeex/vq.c \
		./libspeex/window.c \
 
include $(BUILD_SHARED_LIBRARY)
 

在jni下创建Application.mk,并添加如下内容,编译所有平台下的so文件

APP_ABI := all

在jni/include/speex/目录下新增speex_config_types.h文件,复制内容如下

#ifndef __SPEEX_TYPES_H__
#define __SPEEX_TYPES_H__
 
typedef short spx_int16_t;
typedef unsigned short spx_uint16_t;
typedef int spx_int32_t;
typedef unsigned int spx_uint32_t;
 
#endif


上述完成后,如下图所示

 

四、新建SpeexUtil类,其中定义了native方法

public class SpeexUtil {
    private static final int DEFAULT_COMPRESSION = 4;
    private static SpeexUtil speexUtil;
 
    static {
        try {
            System.loadLibrary("speex");
        } catch (Throwable var1) {
            var1.printStackTrace();
        }
 
        speexUtil = null;
    }
 
    SpeexUtil() {
        this.open(4);
    }
 
    public static SpeexUtil getInstance() {
        if(speexUtil == null) {
            Class var0 = SpeexUtil.class;
            synchronized(SpeexUtil.class) {
                if(speexUtil == null) {
                    speexUtil = new SpeexUtil();
                }
            }
        }
 
        return speexUtil;
    }
 
    public native int open(int var1);
 
    public native int getFrameSize();
 
    public native int decode(byte[] var1, short[] var2, int var3);
 
    public native int encode(short[] var1, int var2, byte[] var3, int var4);
 
    public native void close();
}

 

五、jni目录下新建speex_jni.cpp文件,该文件是SpeexUtil中native方法的具体实现代码,如下所示

#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_speex_util_SpeexUtil_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 JNICALL Java_com_speex_util_SpeexUtil_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);
	}
 
	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_speex_util_SpeexUtil_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_speex_util_SpeexUtil_getFrameSize
    (JNIEnv *env, jobject obj) {
 
	if (!codec_open)
		return 0;
	return (jint)enc_frame_size;
 
}
 
extern "C"
JNIEXPORT void JNICALL Java_com_speex_util_SpeexUtil_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); 
}

 

此处注意:speex_jni.cpp中的Java_com_speex_util_SpeexUtil_open,要改成自己的包名,也就是SpeexUtil所在的包,encode、decode、getFrameSize、close等方法一样要改成SpeexUtil所在的包的包名。

六、通过ndk-build生成so库

命令行定位到Android.mk所在目录(即jni目录),通过ndk-build生成so库,如下图

编译完成后,会生成libs和obj两个目录,其中libs就是各个平台的so文件,如下图所示,下节我们会用到。

 

 代码下载:点击下载

speexdsp回声消除模块在android中封装及使用例子 前言 本来我只是个纯写一般app的码农,奈何进了这家以音视频为主的公司。刚进公司时,还有好些牛人都没有离职(在音视频方面浸淫以久的同事)。那关于音视频方面的什么传输库,h264,aac编解码等方面的事,有专门的人员来写和维护,我作为移动端的开发人员,只需要用他们提供的传输库,使用他们在pc端的功能模块就可以了。我也可以快乐的下班。可公司发展不景气(没有挣到钱),接下来你们懂的。(人员各种流失。。。)最后,移动原生开发的就剩下两人(我也算在里面)。ios方面的开发,全走了。交接工作全给了我了,OMY,我对苹果 阅读详情

相关推荐

<开源> 基于Android的SIP电话-----Speex 回音消除 在android 平台

搞了将近一个月的时间,将Speex的编码和解码做好了,发现还不错。 参考API,又尝试了回音消除,发现最新版还提供了用于在多线程中的playback()和capture(),有了这两个函数,就可以避免在线程中不能同步的问题。 结果,发现虽然进行了回音有了部分消除,但是,还是会一点啸叫以及回声,想来还是要做一点处理,譬如去噪,减小播放或者来音的增益。 在使用了speex提供的 preproce

小脸龙的老巢 2万+

Android 回声消除

android speex AEC 回音消除 上面这篇文章,代码简单清晰 Android 回音消除(AcousticEchoCanceler)的使用 java speex回声消除_android 利用speex 音频降噪,回声消除demo android 用speex做回音消除 Speex回声消除原理深度解析 Speex回声消除代码分析 Android 平台语音通话及回音消除、噪音消除研究(转) android、ios、windows等平台回声消除的解决方案 下面几张图是这篇文章的很重要的东西 Spee

hugang的博客 1712

Speex编解码在Android上的实现

在Android平台上实现音频编解码是一项常见的任务,而Speex编解码器是一个广泛使用的开源音频编解码器。在Android项目的jniLibs目录下创建对应的CPU架构目录(如armeabi-v7a、arm64-v8a等),将解压后的库文件(.so文件)复制到对应的目录下。从Speex的官方网站(https://www.speex.org/)下载最新版本的Speex库。将Speex库的头文件(.h文件)复制到Android项目的jni目录下或其他合适的位置。将下载的库文件解压缩到合适的位置。

DevScribe的博客 826

Android语音文件speex编码解码(二)

上一边我们讲解了利用speex开源库,如何得到so库,本节我们讲解通过so库如何实现语音文件的编码与解码。 一 、新建工程TestSpeex,在main下新建jniLibs目录,在其中拷贝上节得到的so文件,注意连带平台类型一起拷贝,如下图 二、编写Java代码,实现录音、以及录音压缩,如下图 实例程序代码下载:

IT从业者,生活精致一点,工作认真一点! 1320

Android语音录制解决方案:基于Speex的实现

Speex是专为VoIP(Voice over Internet Protocol)设计的开源音频编解码器,最初由Jean-Marc Valin于2002年开发。它支持可变比特率编码,并且是完全免费和开源的,适用于互联网语音和音频通信。Speex的特点包括低延迟模式、背景噪声抑制以及宽带和窄带模式,使其能够在不同网络条件下保持良好的音频质量。JNI(Java Native Interface)是Java提供的一种标准编程接口,允许Java代码和其他语言写的代码(通常是C或C++)之间进行交互。

weixin_35756373的博客 859

Android平台Speex音频编解码实战项目详解

简介:本项目“intercom-test.zip”聚焦于Android平台上Speex音频编解码技术的实战应用,涵盖从JNI库集成到实时音频流处理的完整流程。作为一款专为VoIP设计的开源、高效音频压缩格式,Speex在低带宽环境下仍能提供高质量语音传输,广泛应用于对讲、移动通信等场景。通过该项目,开发者将掌握音频数据处理、Android音频框架使用、编码解码流程实现及性能优化等关键技术,提升在语音通信领域的开发能力。

weixin_42607969的博客 732

安卓使用speex开源库

Speex是一套主要针对语音的开源免费,无专利保护的音频压缩格式。 Speex工程着力于通过提供一个可以替代高性能语音编解码来降低语音应用输入门槛 。 另外,相对于其它编解码器,Speex也很适合网络应用,在网络应用上有着自己独特的优势。 同时,Speex还是GNU工程的一部分,在改版的BSD协议中得到了很好的支持。 它完全是C语言实现的,所以它具有很好的移植性。所以在Android当中具有很好的...

里昂的博客 3467

Android平台基于Speex的录音与语音增强实战

Android音频系统基于分层架构设计,主要由应用层、Framework层、Native层以及Linux内核音频驱动组成。音频采集流程从应用层调用或开始,经过 JNI 进入 Native 层的服务,最终通过 ALSA 或 ASoC 驱动与硬件交互。该架构支持多种音频策略与混音机制,确保多应用同时录音与播放时的资源调度与优先级控制。Speex 是一种专为语音通信设计的开源音频编码器,以其高效的语音压缩能力和低延迟特性,在 VoIP、对讲系统和移动语音应用中得到了广泛应用。

weixin_42327217的博客 426

语音编码解码speex,c代码iOS和Android平台。

android ios speex编解码

qq_17524035的博客 2290

Android平台Speex音频处理实战项目代码

htmltable {th, td {th {pre {简介:SpeexDemo是一款基于Android平台的音频处理示例程序,集成开源音频编码库Speex,实现语音的高效压缩、解码、降噪与回声消除功能。该程序利用AudioRecord和MediaPlayer等Android音频API完成音频数据的采集与播放,结合VAD、DNR和AEC等技术提升语音通信质量,适用于低带宽环境下的实时语音应用开发。

weixin_42509507的博客 1008

Android平台Speex音频编解码器集成与实战

Speex是一款专为语音通信设计的开源、免专利的音频压缩编码器,基于CELP(Code-Excited Linear Prediction)算法实现,具备高压缩比与低延迟特性。其支持窄带(8 kHz)、宽带(16 kHz)和超宽带(32 kHz)三种采样模式,适用于不同质量需求的语音场景。app/│ ├── jni/Android.mk是 NDK 提供的传统构建描述文件,基于 GNU Make 语法,用于定义如何编译 C/C++ 源码为静态库或共享库。

weixin_35756130的博客 891

speex编解码在android上实现

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

4万+

AndroidStudio 上编译speex库,进行使用

AndroidStudio 上编译speex库,进行使用

speex算法在android上的移植

最近在调speex接口参数,将speex算法的一些特性给添加进去,比如:降噪,静音检测,白噪声添加,增益等等。下面我们就先简单介绍一些spexx算 法。speex语音算法主要是针对VOIP应用的一个开源算法,他集合了多种功能,除了如上所述的,还增加了回声消除(ACE)等功能,能够在多种平台 进行应用。下面我主要介绍一下speex在android平台上的应用。 首先我们来介绍一下s

tinty_11的专栏 2232

Verilog除法器(32位无符号+带符号)

32位无符号除法器设计 恢复余数法: 恢复余数除法的基本思路是从“部分余数”中减去除数,如果结果为负(不够减),则恢复原来的部分余数,商0. 寄存器使用: reg_r 存放被除数a reg_b 存放除数b reg_r 存放余数(初始清零) 具体做法: 做减法时,减数是reg_b中的除数,被减数是reg_r中的余数左移一位,最低位由reg_q(被除数)的最高位补充。为了能够判断相减结果的正...

qq_38600065的博客 1万+

基于STM32的INA226电压电流检测仪

该功率检测装置以STM32F103C8T6微控制器为核心,集成功率检测、数据交互、状态显示和用户提示功能,通过模块化设计实现稳定运行。系统包括按键、LED指示灯、OLED屏幕、INA226电压电流检测、复位电路、晶振电路、蜂鸣器驱动、输入输出接口、调试接口和3.3V降压电路等模块。微控制器通过按键检测用户输入,启动功率检测,采集数据并通过OLED显示,异常情况触发蜂鸣器报警,LED状态指示同步反馈。3.3V降压电路为所有模块提供稳定电源,晶振电路确保时序精度。INA226芯片通过I2C接口与微控制器通信,实

a2784288164的博客 1910

Android语音——speex编码解码(二)

上文Android语音——speex编码解码(一) 已经生成了so库,本文将介绍如何使用Speex进行语音压缩和解压。1.新建项目,将生成的speex_1.2rc2.jar导入到libs目录下,在main下新建jniLibs目录,将armeabi文件夹拷贝到jniLibs目录下,完成后如下图2.项目中一共有6个类(源码不在一一贴出)3.下面提供Android Studio和Eclipse使用Spee

jianiuqi的专栏 3487

从AND到XOR:5种门控电路在PrimeTime中的检查策略差异

本文深入探讨了AND、NAND、OR、NOR和XOR五种门控电路在PrimeTime静态时序分析中的检查策略差异。重点解析了XOR门控因其非单调性而无法被工具自动推断,需要工程师手动配置的特殊性,并提供了针对各类门控的配置模板与调试技巧,以确保时钟网络的完整性与芯片设计的可靠性。

rgv2345678的博客 269

Android语音用speex编解码边录边放,求大神解决参数问题

我想要实现语音边录边放功能,其中用到speex编解码,但是播放的是噪音,我觉得是speex编解码时的音频数据参数出问题,参考网上跟官方的代码都不统一,求大神搭救 package com.embedsky.audiorecord; import com.trunkbow.speextest.Speex; import android.app.Activity; import android.

chaowu1164的博客 876

外部ADC之AD7949——14bit、8通道、250k

在实际项目中,仅靠单片机内部的ADC采样,很有可能达不到实际采样精度,这个时候就需要外接外部ADC芯片进行采样,这些外部ADC一般都是SPI接口或者是并口。单片机通过SPI接口或并口读写芯片内部寄存器,配置参考极性、采样通道、低通滤波器带宽、基准电压源、通道序列器等。本文主要对ADI家的14bit、8通道、250k的ADC7949做一个总结,这款ADC在实际项目中使用,采样精度达到要求,读取时序有点点绕,但是是一款十分常用的ADC芯片。就是价格不太友好哈哈,一块芯片快60。

cyaya6的博客 6715

2024最新Typora配置指南:从安装到打造学术写作环境(含LaTeX/参考文献解决方案)

本文提供2024年最新Typora配置指南,详细讲解如何从安装开始,结合Pandoc、Zotero和LaTeX,打造高效的学术写作环境。指南涵盖Typora深度定制、学术主题配置、参考文献自动管理以及一键生成出版级PDF的完整解决方案,旨在帮助科研人员和学生实现内容与格式分离,大幅提升论文写作效率。

weixin_29258297的博客 211
上一篇: EventBus玩转消息传递
下一篇: Android语音文件speex编码解码(二)
dodod2012
博客等级 码龄15年 244粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值