(建立于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");
}
}
程式運作界面
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuYjM3QWYkNmNxMTN3U2NzEGNmVTY4QjZ1UjN0kjN0YTMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
18404062.png