08.Eclipse下Ndk开发(使用fmod实现QQ变声功能)

简介: (创建于2017/12/30)1.编写nativepackage org.fmod.example;public class EffectUtils { //音效的类型 public static final int ...

(创建于2017/12/30)

1.编写native

package org.fmod.example;

public class EffectUtils {
    
    //音效的类型
    public static final int MODE_NORMAL = 0;
    public static final int MODE_LUOLI = 1;
    public static final int MODE_DASHU = 2;
    public static final int MODE_JINGSONG = 3;
    public static final int MODE_GAOGUAI = 4;
    public static final int MODE_KONGLING = 5;

    /**
     * 音效处理
     * @param path
     * @param type
     */
    public native static void fix(String path,int type);
    
    static{
        System.loadLibrary("fmodL");
        System.loadLibrary("fmod");
        System.loadLibrary("qq_voice");
    }
}

2.进入src目录下,使用命令行生成头文件

javah 包名+类名

3.创建项目根目录下jni文件夹,将头文件拷贝进去
4.下载fmod源码,复制api中lowlevel中的inc中的头文件到jni目录下
5.复制fmod jar包到根目录下libs文件夹并添加依赖
6.复制需要的api平台的so文件到jni目录下
7.修改报错的地方,比如头文件的路径等问题
8.Android Tools -> Add native support 添加本地支持(在此之前,确认你的项目中已经配置了ndk相关的头文件目录支持,参考前边的笔记),填写你要生成的
so库的文件名,确认和loadLibrary中加载的(如qq_voice)保持一致
9.配置mk文件:
Android.mk

LOCAL_PATH := $(call my-dir)

//编译libfmod.so
include $(CLEAR_VARS)
LOCAL_MODULE := fmod
LOCAL_SRC_FILES := libfmod.so
include $(PREBUILT_SHARED_LIBRARY)

//编译libfmodL.so
include $(CLEAR_VARS)
LOCAL_MODULE := fmodL
LOCAL_SRC_FILES := libfmodL.so
include $(PREBUILT_SHARED_LIBRARY)

//编译我们自己写的c代码为so文件,并添加上边编译的so支持
include $(CLEAR_VARS)
LOCAL_MODULE    := qq_voice
LOCAL_SRC_FILES := effect_fix.cpp
LOCAL_SHARED_LIBRARIES := fmod fmodL
//添加log支持
LOCAL_LDLIBS := -llog
//添加c++异常类支持
LOCAL_CPP_FEATURES := exceptions
include $(BUILD_SHARED_LIBRARY)

Application.mk

##支持C++异常处理,标准莫板块(针对string.h等头文件的处理,去掉了common.c之后,这个不再需要了,但是保留也没问题)
APP_STL := gnustl_static

10.不断的build project,直到所有异常解决编译成功

部分源码:
effect_fix.cpp

#include "org_fmod_example_EffectUtils.h"
#include "inc/fmod.hpp"
#include <stdlib.h>
#include <unistd.h>
#include <android/log.h>
#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"renzhenming",FORMAT,##__VA_ARGS__)
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"renzhenming",FORMAT,##__VA_ARGS__)

#define MODE_NORMAL 0
#define MODE_LUOLI 1
#define MODE_DASHU 2
#define MODE_JINGSONG 3
#define MODE_GAOGUAI 4
#define MODE_KONGLING 5

using namespace FMOD;

JNIEXPORT void JNICALL Java_org_fmod_example_EffectUtils_fix
  (JNIEnv *env, jclass jcls, jstring path_jstr, jint type){

    System            *system;
    FMOD_RESULT       result;
    Sound             *sound;
    Channel           *channel;
    DSP               *dsp;
    float             frequency = 0;
    bool isPlaying = true;
    const char *media_path = env->GetStringUTFChars(path_jstr,NULL);
    try {
            //初始化
            result = System_Create(&system);
            result = system->init(32, FMOD_INIT_NORMAL, NULL);
            //创建声音

            //这里进坑了,写作下边的样子是无法播放的,正确的方式是第二行 因为sound如果是null,那么,播放的时候的sound也就是null,怎么播放呢
            //result = system->createSound(media_path, FMOD_DEFAULT, 0, NULL);
            LOGI("%s",media_path);
            system->createSound(media_path, FMOD_DEFAULT, NULL, &sound);
            switch(type){
                case MODE_NORMAL:
                    //原生播放
                    result = system->playSound(sound, 0, false, &channel);
                    break;

                case MODE_LUOLI:
                    //dsp -- 音效
                    //FMOD_DSP_TYPE_PITCHSHIFT 提升或者降低音调用的一种音效
                    system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT,&dsp);
                    //设置音调的参数
                    dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH,2);
                    //播放(播放和添加channel的顺序必须是先播放,再添加,否则音效无法生效)
                    //猜测原因
                    //playSound之后并不是立即播放,而是在system->update();之后开始播放,
                    //playSound的作用是创造了一个sound载体一个channel载体,然后在这个载体基础上添加一系列的效果,所以,只能现有载体
                    //效果才有放置的位置,所以需要先play再添加
                    result = system->playSound(sound, 0, false, &channel);
                    //添加到channel
                    channel->addDSP(0,dsp);

                    break;
                case MODE_DASHU:
                    //dsp -- 音效
                    //FMOD_DSP_TYPE_PITCHSHIFT 提升或者降低音调用的一种音效
                    system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT,&dsp);
                    //设置音调的参数
                    dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH,0.6);
                    //播放(播放和添加channel的顺序必须是先播放,再添加,否则音效无法生效)
                    result = system->playSound(sound, 0, false, &channel);
                    //添加到channel
                    channel->addDSP(0,dsp);

                    break;
                case MODE_GAOGUAI:
                    //提高说话的速度
                    result = system->playSound(sound, 0, false, &channel);
                    channel->getFrequency(&frequency);\
                    frequency = frequency*1.5;
                    channel->setFrequency(frequency);
                    break;
                case MODE_KONGLING:
                    system->createDSPByType(FMOD_DSP_TYPE_ECHO,&dsp);
                    dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY,300);
                    dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK,2);
                    result = system->playSound(sound, 0, false, &channel);
                    channel->addDSP(0,dsp);
                    break;
                case MODE_JINGSONG:
                    //紧张
                    system->createDSPByType(FMOD_DSP_TYPE_ECHO,&dsp);
                    dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW,0.5);
                    result = system->playSound(sound, 0, false, &channel);
                    channel->addDSP(0,dsp);
                    break;
                default:
                    break;
            }
            while(isPlaying){
                channel->isPlaying(&isPlaying);
                //<unistd.h>
                //单位微秒,不断的睡眠保证声音播放完成之后再释放资源
                usleep(1000*1000);
            }
            LOGI("%s","播放完成");
            system->update();
    } catch(...){
        LOGE("%s","发生异常");
        goto end;
    }
    goto end;

    end:
    env->ReleaseStringUTFChars(path_jstr,media_path);
    result = sound->release();
    system->close();
    system->release();
}

QQActivity.java

package org.fmod.example;

import java.io.File;

import com.renzhenming.qq_voice.R;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;

public class QQActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         org.fmod.FMOD.init(this);
        setContentView(R.layout.activity_main);
    }
    
    public void mFix(View view){
        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "singing.wav";
        Log.d("renzhenming", path);
        
        switch (view.getId()) {
        case R.id.btn_record:
            EffectUtils.fix(path, EffectUtils.MODE_NORMAL);
            Log.d("renzhenming", "MODE_NORMAL");
            break;
        case R.id.btn_luoli:
            EffectUtils.fix(path, EffectUtils.MODE_LUOLI);
            Log.d("renzhenming", "MODE_LUOLI");
            break;
        case R.id.btn_dashu:
            EffectUtils.fix(path, EffectUtils.MODE_DASHU);
            Log.d("renzhenming", "MODE_DASHU");
            break;
        case R.id.btn_jingsong:
            EffectUtils.fix(path, EffectUtils.MODE_JINGSONG);
            break;  
            
        case R.id.btn_gaoguai:
            EffectUtils.fix(path, EffectUtils.MODE_GAOGUAI);
            break;  
            
        case R.id.btn_kongling:
            EffectUtils.fix(path, EffectUtils.MODE_KONGLING);
            break;  
        default:
            break;
        }
        
        
    }
    
    @Override
    protected void onDestroy(){    
        org.fmod.FMOD.close();      
        super.onDestroy();
    }
}

EffectUtils.java

package org.fmod.example;

public class EffectUtils {
    
    //音效的类型
    public static final int MODE_NORMAL = 0;
    public static final int MODE_LUOLI = 1;
    public static final int MODE_DASHU = 2;
    public static final int MODE_JINGSONG = 3;
    public static final int MODE_GAOGUAI = 4;
    public static final int MODE_KONGLING = 5;

    /**
     * 音效处理
     * @param path
     * @param type
     */
    public native static void fix(String path,int type);
    
    static{
        System.loadLibrary("fmodL");
        System.loadLibrary("fmod");
        System.loadLibrary("qq_voice");
    }
}

程序运行界面


img_164694655f48a5f4a37e75316cdad726.png
18404062.png
相关文章
|
Java 关系型数据库 MySQL
JSP在线小说系统用eclipse定制开发mysql数据库BS模式java编程jdbc
JSP 在线小说系统是一套完善的web设计系统,对理解JSP java SERLVET mvc编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0,使用java语言开发。
107 1
JSP在线小说系统用eclipse定制开发mysql数据库BS模式java编程jdbc
|
7月前
|
前端开发 Java Maven
Eclipse里使用Servlet实现简单的登录功能
Maven是一款非常方便的Java开发插件,它可以自动管理好开发过程中需要的jar包,提升开发者们的开发效率。在这里,我手把手教给大家如何新建一个Maven项目,并实现简单的用户登录功能。
197 0
|
Java 关系型数据库 MySQL
java 网上二手车销售系统用eclipse定制开发mysql数据库BS模式java编程jdbc
JSP 网上二手车销售系统是一套完善的web设计系统,对理解JSP java SERLVET mvc编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0,使用java语言开发。
85 0
|
22天前
|
NoSQL 编译器 C语言
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。高级技巧包括内存检查、性能分析和符号调试。通过实践案例学习如何有效定位和解决问题,同时注意保持耐心、合理利用工具、记录过程并避免过度调试,以提高编程能力和开发效率。
37 1
|
Java 关系型数据库 MySQL
SSM度假村管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目
SSM 度假村管理系统是一套完善的信息系统,结合SSM框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 前段主要技术html div js 后端主要技术 SSM框架 java jdbc 数据库 mysql 开发工具 eclipse JDK1.8 TOMCAT 8.5
60 0
|
5月前
|
存储 Oracle Java
Java面试题:描述如何使用Eclipse或IntelliJ IDEA进行Java开发?
Java面试题:描述如何使用Eclipse或IntelliJ IDEA进行Java开发?
58 0
|
6月前
|
开发工具 Android开发 git
合作开发(Eclipse+git +码云)
合作开发(Eclipse+git +码云)
83 0
|
Java 关系型数据库 数据库
JSP网上手机商城系统 用eclipse定制开发mysql数据库BS模式java编程jdbc
JSP 网上手机商城系统是一套完善的web设计系统,对理解JSP java SERLVET mvc编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0,使用java语言开发。
146 1
JSP网上手机商城系统 用eclipse定制开发mysql数据库BS模式java编程jdbc
|
Java 关系型数据库 MySQL
SSM校园设备管信息管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目
SSM 校园设备管信息理系统是一套完善的信息系统,结合SSM框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库,系 统主要采用B/S模式开发。 前段主要技术html div js 后端主要技术 SSM框架 java jdbc 数据库 mysql 开发工具 eclipse JDK1.8 TOMCAT 8.5
103 0
SSM校园设备管信息管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目
|
7月前
|
Java 关系型数据库 BI
基于Java Swing 开发的网吧管理系统【eclipse和idea两个版本运行源码】
基于Java Swing 开发的网吧管理系统【eclipse和idea两个版本运行源码】
139 0