当前位置:首页 » 《关注互联网》 » 正文

Android Studio开发引入Speex_p413768973的博客

22 人参与  2021年09月08日 13:03  分类 : 《关注互联网》  评论

点击全文阅读


 

首先配置Android Studio NDK以及下载Speex源码放入main/cpp/speex目录

在cpp目录下更改根CMakeList.tet文件:

  一下是包含子目录得形式,

#指定需要CMAKE的最小版本
cmake_minimum_required(VERSION 3.4.1)


#C 的编译选项是 CMAKE_C_FLAGS
# 指定编译参数,可选
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#设置生成的so动态库最后输出的路径
#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

#设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)

#指定用到的系统库或者NDK库或者第三方库的搜索路径,可选。
#LINK_DIRECTORIES(/usr/local/lib)


#添加子目录,将会调用子目录中的CMakeLists.txt
ADD_SUBDIRECTORY(speex)

在cpp/speex增加子文件:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
set(CMAKE_C_FLAGS "-DFIXED_POINT -DUSE_KISS_FFT -DEXPORT="" -UHAVE_CONFIG_H")

add_library( # Sets the name of the library.
        speex-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        speex_jni.cpp
        ./libspeex/bits.c
        ./libspeex/cb_search.c
        ./libspeex/buffer.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_lbr.c
        ./libspeex/gain_table.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_tables_nb.c
        ./libspeex/lsp.c
        ./libspeex/ltp.c
        ./libspeex/mdf.c
        ./libspeex/modes_wb.c
        ./libspeex/modes.c
        ./libspeex/nb_celp.c
        ./libspeex/preprocess.c
        ./libspeex/quant_lsp.c
        ./libspeex/sb_celp.c
        ./libspeex/scal.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)

#target_include_directories(speex-lib
#        PRIVATE
#        /include)
include_directories(include)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        speex-lib

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

在gradle下:

    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11 -frtti"
                abiFilters 'armeabi-v7a', "arm64-v8a", 'x86', 'x86_64'
                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_STL=c++_static"
            }

        }

    }
android {
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

若使用Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_LDLIBS :=-llog

LOCAL_MODULE    := libspeex
LOCAL_CFLAGS = -DFIXED_POINT -DUSE_KISS_FFT -DEXPORT="" -UHAVE_CONFIG_H
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include

LOCAL_SRC_FILES := speex_jni.cpp \
        ./libspeex/bits.c \
        ./libspeex/cb_search.c \
        ./libspeex/buffer.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_lbr.c \
        ./libspeex/gain_table.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_tables_nb.c \
        ./libspeex/lsp.c \
        ./libspeex/ltp.c \
        ./libspeex/mdf.c \
        ./libspeex/modes_wb.c \
        ./libspeex/modes.c \
        ./libspeex/nb_celp.c \
        ./libspeex/preprocess.c \
        ./libspeex/quant_lsp.c \
        ./libspeex/sb_celp.c \
        ./libspeex/scal.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)

application.mk

APP_ABI := armeabi

gradle也不一样:

android{
    externalNativeBuild {
        ndkBuild {
            path 'src/main/cpp/Android.mk'
        }
   }
}

speex_jni.cpp

#include <jni.h>

#include <string.h>
#include <unistd.h>

#include <speex/speex.h>
#include<Android/log.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;
#define TAG "JNI" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG ,__VA_ARGS__) // 定义LOGD类型
extern "C"
JNIEXPORT jint JNICALL Java_包名_NativeCodec_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;
}
float encoder_input[160];
extern "C"
JNIEXPORT jint Java_包名_NativeCodec_encode
        (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {
    jshort buffer[enc_frame_size];
    jbyte output_buffer[20];
    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_包名_NativeCodec_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;

    speex_bits_reset(&dbits);

    env->GetByteArrayRegion(encoded, 0, encoded_length, buffer);
    speex_bits_read_from(&dbits, (char *)buffer, encoded_length);
//    speex_decode_int(dec_state, &dbits, output_buffer);



    float decoder_output[dec_frame_size];
    speex_decode(dec_state, &dbits, decoder_output);
    for (int i = 0; i < dec_frame_size; i++)
    {
        output_buffer[i] = decoder_output[i];
    }





    env->SetShortArrayRegion(lin, 0, dec_frame_size,
                             output_buffer);

    return (jint)dec_frame_size;
}

extern "C"
JNIEXPORT jint JNICALL Java_包名_NativeCodec_getFrameSize
        (JNIEnv *env, jobject obj) {

    if (!codec_open)
        return 0;
    return (jint)enc_frame_size;

}

extern "C"
JNIEXPORT void JNICALL Java_包名_NativeCodec_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);
}
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();
解码参数 1 encodedData, 编码数据
        2 decodedData, 解码数据,可通过getFrameSize获取长度
        3 encodedData.length

编码参数1 audioData,原始参数

                2 0

                3 encodedData,

                4 audioData.length

 


点击全文阅读


本文链接:http://zhangshiyu.com/post/27336.html

路径  可选  参数  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1