All Projects → fsrmeng → VoiceChange

fsrmeng / VoiceChange

Licence: other
Android NDK开发

Programming Languages

java
68154 projects - #9 most used programming language
C++
36643 projects - #6 most used programming language
CMake
9771 projects
c
50402 projects - #5 most used programming language

Projects that are alternatives of or similar to VoiceChange

Adi
ADI(Android Debug Intensive) 是通过 JVMTI 实现的 Android 应用开发调试的增强工具集,目前主要提供性能相关的监控能力。
Stars: ✭ 194 (+397.44%)
Mutual labels:  jni
clojure-rust-graalvm
An example of Clojure program calling a Rust library, all combined into one executable using GraalVM.
Stars: ✭ 113 (+189.74%)
Mutual labels:  jni
sentencepiece-jni
Java JNI wrapper for SentencePiece: unsupervised text tokenizer for Neural Network-based text generation.
Stars: ✭ 26 (-33.33%)
Mutual labels:  jni
J4rs
Java for Rust
Stars: ✭ 210 (+438.46%)
Mutual labels:  jni
Jxnet
Jxnet is a Java library for capturing and sending custom network packet buffers with no copies. Jxnet wraps a native packet capture library (libpcap/winpcap/npcap) via JNI (Java Native Interface).
Stars: ✭ 26 (-33.33%)
Mutual labels:  jni
wgpu-mc
Rust-based replacement for the default Minecraft renderer
Stars: ✭ 254 (+551.28%)
Mutual labels:  jni
Xcrash
🔥 xCrash provides the Android app with the ability to capture java crash, native crash and ANR. No root permission or any system permissions are required.
Stars: ✭ 2,689 (+6794.87%)
Mutual labels:  jni
gdx-jnigen
jnigen is a small library that can be used with or without libGDX which allows C/C++ code to be written inline with Java source code.
Stars: ✭ 32 (-17.95%)
Mutual labels:  jni
JNI RSA Sign
通过JNI实现验证App签名获取公钥
Stars: ✭ 86 (+120.51%)
Mutual labels:  jni
ffmpeg4java
FFmpeg4Java provides a JNI wrapper of FFmpeg library
Stars: ✭ 21 (-46.15%)
Mutual labels:  jni
Relinker
A robust native library loader for Android.
Stars: ✭ 2,612 (+6597.44%)
Mutual labels:  jni
Android Disassembler
Disassemble ANY files including .so (NDK, JNI), Windows PE(EXE, DLL, SYS, etc), linux binaries, libraries, and any other files such as pictures, audios, etc(for fun)files on Android. Capstone-based disassembler application on android. 안드로이드 NDK 공유 라이브러리, Windows 바이너리, etc,... 리버싱 앱
Stars: ✭ 250 (+541.03%)
Mutual labels:  jni
monero-java
A Java library for using Monero
Stars: ✭ 76 (+94.87%)
Mutual labels:  jni
Inline Java
Haskell/Java interop via inline Java code in Haskell modules.
Stars: ✭ 197 (+405.13%)
Mutual labels:  jni
Libbulletjme
A JNI interface to Bullet Physics and V-HACD
Stars: ✭ 55 (+41.03%)
Mutual labels:  jni
Jfasttext
Java interface for fastText
Stars: ✭ 193 (+394.87%)
Mutual labels:  jni
Android
Swift library for Android
Stars: ✭ 48 (+23.08%)
Mutual labels:  jni
ChangeVoice
NDK语音消息的变声处理
Stars: ✭ 33 (-15.38%)
Mutual labels:  jni
terra-java
Lua/Terra + Java Native Interface
Stars: ✭ 20 (-48.72%)
Mutual labels:  jni
java-cpp-example
Example of using C++ classes from Java. Showcases SWIG, JNA and JNI
Stars: ✭ 135 (+246.15%)
Mutual labels:  jni

VoiceChange-mater

first commit ###前言

首先我们来介绍fmod,fmod声音系统是为游戏开发者准备的革命性音频引擎,如今采用了fmod作为音频引擎的游戏包括Far Cry(孤岛惊魂)、Tom Clancy's Ghost Recon(幽灵行动),甚至著名的World Of Warcraft(魔兽争霸)。而我们此次的变声特效也是使用了fmod这个库。**fmod官网:**https://www.fmod.com,点击Download,下载针对Android的api 1.png

变声特效最后的效果图:

2.png

###集成fmod,实现播放音频文件 废话不多说,直接上图:

3.png

  1. 创建一个支持C/C++的项目MyVoiceChange
  2. 将下载好的文件夹下的api / lowlevel / inc 下的头文件复制到项目中cpp下的inc文件夹(自己创建的)下。
  3. 将下载好的文件夹下的api / lowlevel / examples 下的play_sound.cpp复制到cpp下,play_sound.cpp中需要头文件common.h,故将common.hcommon.cpp复制到cpp下,common.h需要的头文件有common_platform.h,同理将common_platform.hcommon_platform.cpp复制到cpp下。
  4. 将下载好的文件夹下的api / lowlevel / lib 下的armeabi文件夹复制到项目中的libs目录下,将fmod.jar也复制到libs目录下,右键Add as library,在app的build.gradle中添加
externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters "armeabi"
            }
        }
  1. 在项目中的main文件夹下新建assets文件夹,将下载好的文件夹下的api / lowlevel / examples / media 文件夹下的drumloop.wav、jaguar.wav、swish.wav三个音频文件复制到assets中

  2. 将inc文件夹下的都加上inc/,如play_sound.cpp

#include "inc/fmod.hpp"
#include "common.h"
  1. MainActivity复制到项目中,然后将删除关于权限的,在清单文件中添加权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            String[] perms = { "android.permission.RECORD_AUDIO", "android.permission.WRITE_EXTERNAL_STORAGE" };
            if (checkSelfPermission(perms[0]) == PackageManager.PERMISSION_DENIED ||
                checkSelfPermission(perms[1]) == PackageManager.PERMISSION_DENIED)
            {
                requestPermissions(perms, 200);
            }
        }
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  1. MainActivity中的加载库改为
static {
        System.loadLibrary("voice_change");
    }

由于下面在CMakeLists中的target_link_libraries已经将fmod、fmodL与voice_change链接起来,故这里不需要重复添加加载fmod、fmodL。 9. 在common_platform.cpp中将Java_org_fmod_example_MainActivity_改为Java_com_zhangpan_myvoicechange_MainActivity_ 10. 配置CMakeLists

cmake_minimum_required(VERSION 3.4.1)

set(path_project E:/Demo/MyVoiceChange)

add_library(voice_change
            SHARED
            src/main/cpp/play_sound.cpp
            src/main/cpp/common_platform.cpp)

add_library(fmod
            SHARED
            IMPORTED)
set_target_properties(fmod
                      PROPERTIES IMPORTED_LOCATION
                      ${path_project}/app/libs/${ANDROID_ABI}/libfmod.so)
add_library(fmodL
            SHARED
            IMPORTED )
set_target_properties(fmodL
                      PROPERTIES IMPORTED_LOCATION
                      ${path_project}/app/libs/${ANDROID_ABI}/libfmodL.so)

include_directories(src/main/cpp/inc)

find_library(log-lib
             log)

target_link_libraries(voice_change
                      fmod
                      fmodL
                      ${log-lib})

编译运行报错

4.png

在app的build.gradle中的android中添加,指定预编译so库的路径

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

编译运行,成功播放音频文件。

5.png

关于配置相关信息,可以查看中文官网地址(需要翻墙):向您的项目添加 C 和 C++ 代码

###仿QQ变声特效 新建一个cpp文件voice_change.cpp,将CMakeLists中第一个addLibrary中的play_sound.cpp换成voice_change.cppsrc/main/cpp/play_sound.cppsrc/main/cpp/common_platform.cpp删除,其余不变

add_library(voice_change
            SHARED
            src/main/cpp/voice_change.cpp)

此时可以将之前复制进来的common.cpp、common.h、common_platform.cpp、common_platform.h、play_sound.cpp都可以删除掉,当然了不删除也是没有关系的。 新建一个Activity文件VoiceChangeActivity,创建布局文件activity_voice_change,添加图片,样式

public class VoiceChangeActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_voice_change);
    }
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical"
        android:background="#FFF"
        android:paddingBottom="20dp"
        android:gravity="center_horizontal">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="20dp">

            <LinearLayout 
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/iv_original"
	                style="@style/AudioImgStyle"
	                android:src="@mipmap/record"
	                android:onClick="mFix"/>
                <TextView 
                    style="@style/AudioTextStyle"
                    android:text="原声"/>
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/iv_girl"
	                style="@style/AudioImgStyle"
	                android:src="@mipmap/luoli"
	                android:onClick="mFix"/>
                <TextView 
                    style="@style/AudioTextStyle"
                    android:text="萝莉"/>
            </LinearLayout>
            

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/iv_uncle"
	                style="@style/AudioImgStyle"
	                android:src="@mipmap/dashu"
	                android:onClick="mFix"/>
                <TextView 
                    style="@style/AudioTextStyle"
                    android:text="大叔"/>
            </LinearLayout>
        </LinearLayout>
        
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="20dp">

            <LinearLayout 
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/iv_panic"
	                style="@style/AudioImgStyle"
	                android:src="@mipmap/jingsong"
	                android:onClick="mFix"/>
                <TextView 
                    style="@style/AudioTextStyle"
                    android:text="惊悚"/>
            </LinearLayout>

            <LinearLayout 
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/iv_funny"
	                style="@style/AudioImgStyle"
	                android:src="@mipmap/gaoguai"
	                android:onClick="mFix"/>
                <TextView 
                    style="@style/AudioTextStyle"
                    android:text="搞怪"/>
            </LinearLayout>

            <LinearLayout 
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/iv_intangible"
	                style="@style/AudioImgStyle"
	                android:src="@mipmap/kongling"
	                android:onClick="mFix"/>
                <TextView 
                    style="@style/AudioTextStyle"
                    android:text="空灵"/>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</RelativeLayout>
<resources>
    <style name="AppBaseTheme" parent="android:Theme.Light"/>
    <style name="AppTheme" parent="AppBaseTheme"/>
    <style name="AudioImgStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginLeft">25dp</item>
        <item name="android:layout_marginRight">25dp</item>
    </style>
    <style name="AudioTextStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginTop">5dp</item>
        <item name="android:layout_gravity">center_horizontal</item>
    </style>
</resources>

在清单文件中将MainActivity替换成VoiceChangeActivity 创建VoiceChangeUtils

public class VoiceChangeUtils {
    public static final int MODE_ORIGINAL = 0;       //原声
    public static final int MODE_LITTLE_GIRL = 1;    //萝莉
    public static final int MODE_UNCLE = 2;           //大叔
    public static final int MODE_PANIC = 3;           //惊悚
    public static final int MODE_FUNNY = 4;           //搞怪
    public static final int MODE_INTANGIBLE = 5;      //空灵

    public static native void fix(String path, int type);

    static {
        System.loadLibrary("voice_change");
    }
}

voice_change.cpp变声特效的核心实现:

//
// Created by zp on 2017/11/29.
//
#include <stdlib.h>
#include <jni.h>
#include <unistd.h>
#include <fmod.hpp>

#define MODE_ORIGINAL   0
#define MODE_GIRL       1
#define MODE_UNCLE      2
#define MODE_PANIC      3
#define MODE_FUNNY      4
#define MODE_INTANGIBLE 5
using namespace FMOD;
extern "C"
JNIEXPORT void JNICALL
Java_com_zhangpan_myvoicechange_VoiceChangeUtils_fix(JNIEnv *env, jclass type_, jstring path_,
jint type) {
    System* system;
    void* extradriverdata = 0;
    Sound* sound;
    Channel* channel;
    DSP* dsp;
    bool playing = true;
    float frequency = 0;
    const char *path = env->GetStringUTFChars(path_, 0);
    try {
        //初始化
        System_Create(&system);
        system->init(32, FMOD_INIT_NORMAL, extradriverdata);
        //创建声音
        system->createSound(path, FMOD_DEFAULT, 0, &sound);
        switch (type) {
            case MODE_ORIGINAL:
                //原生播放
                system->playSound(sound, 0, false, &channel);
                break;
            case MODE_GIRL:
                //萝莉
                //FMOD_DSP_TYPE_PITCHSHIFT 提高或者降低音调的一种音效
                system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                //设置音调的参数
                dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 2.0);
                //播放萝莉声音
                system->playSound(sound, 0, false, &channel);
                //添加到channel
                channel->addDSP(0, dsp);
                break;
            case MODE_UNCLE:
                system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.8);
                system->playSound(sound, 0, false, &channel);
                channel->addDSP(0, dsp);
                break;
            case MODE_PANIC:
                system->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);
                dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.5);
                system->playSound(sound, 0, false, &channel);
                channel->addDSP(0, dsp);
                break;
            case MODE_FUNNY:
                //先playSound才能拿到原音频的频率
                system->playSound(sound, 0, false, &channel);
                channel->getFrequency(&frequency);
                channel->setFrequency(frequency * 1.8);
                break;
            case MODE_INTANGIBLE:
                system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);
                dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 300);
                dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 20);
                system->playSound(sound, 0, false, &channel);
                channel->addDSP(0, dsp);
                break;
            default:
                break;
        }
        system->update();
        while (playing) {
            channel->isPlaying(&playing);
            usleep(1000 * 1000);
        }
    }catch (...) {
        goto end;
    }
    goto end;
end:
    sound->release();
    system->close();
    system->release();

    env->ReleaseStringUTFChars(path_, path);
}

VoiceChangeActivity的调用:

public class VoiceChangeActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_voice_change);

        FMOD.init(this);
    }

    public void mFix(View view) {
        String path = "file:///android_asset/zp.wav";
        switch(view.getId()) {
            case R.id.iv_original:
                VoiceChangeUtils.fix(path, VoiceChangeUtils.MODE_ORIGINAL);
                break;
            case R.id.iv_girl:
                VoiceChangeUtils.fix(path, VoiceChangeUtils.MODE_GIRL);
                break;
            case R.id.iv_uncle:
                VoiceChangeUtils.fix(path, VoiceChangeUtils.MODE_UNCLE);
                break;
            case R.id.iv_panic:
                VoiceChangeUtils.fix(path, VoiceChangeUtils.MODE_PANIC);
                break;
            case R.id.iv_funny:
                VoiceChangeUtils.fix(path, VoiceChangeUtils.MODE_FUNNY);
                break;
            case R.id.iv_intangible:
                VoiceChangeUtils.fix(path, VoiceChangeUtils.MODE_INTANGIBLE);
                break;
            default:
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        FMOD.close();
    }
}

编译运行,效果图如下:

6.png

###展望

喜欢本篇博客的简友们,就请来一波点赞,您的每一次关注,将成为我前进的动力,谢谢!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].