

#include "inc/fmod.hpp"
#include "common.h"
#include <jni.h>
#include <android/log.h>
#include <unistd.h>
#include <stdlib.h>

#define LOGI(FORMAT, ...)  __android_log_print(ANDROID_LOG_INFO, "HSH_LOG", FORMAT, ##__VA_ARGS__);


#define VOICE_NORMAL  0
#define VOICE_LUOLI  1
#define  VOICE_DASHU  2
#define VOICE_JINGSONG  3
#define VOICE_GAOGUAI  4
#define  VOICE_KONGLING  5

using namespace FMOD;

extern "C"
JNIEXPORT void JNICALL
Java_org_fmod_example_VoiceUtil_playVoiceMode(JNIEnv *env, jclass cls_, jstring path_,
                                              jint type) {

    System *system;
    Sound *sound;
    Channel *channel;
    DSP *dsp;

    float frequency = 1;

    bool isPlaying = true;

    const char *path = env->GetStringUTFChars(path_, 0);
    try {
        System_Create(&system);

        system->init(32, FMOD_INIT_NORMAL, NULL);


        system->createSound(path, FMOD_DEFAULT, NULL, &sound);

        switch (type) {
            case VOICE_NORMAL:// 正常
                system->playSound(sound, 0, false, &channel);
                LOGI("path:%s", "VOICE_NORMAL");
                break;
            case VOICE_LUOLI: // 萝莉
                // DSP digital signal process (音效处理)
                // FMOD_DSP_TYPE_PITCHSHIFT 提升或降低音调
                system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                // 设置音调升降参数
                // Pitch value.  0.5 to 2.0.  Default = 1.0. 0.5 = one octave down, 2.0 = one octave up.  1.0 does not change the pitch
                dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 2);
                system->playSound(sound, 0, false, &channel);
                // 添加到不同音轨中
                // 只有一个音效，直接添加到第一个
                channel->addDSP(0, dsp);
                LOGI("path:%s", "VOICE_LUOLI");
                break;
            case VOICE_DASHU:// 大叔
                // DSP digital signal process (音效处理)
                // FMOD_DSP_TYPE_PITCHSHIFT 提升或降低音调
                system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                // 设置音调升降参数
                // Pitch value.  0.5 to 2.0.  Default = 1.0. 0.5 = one octave down, 2.0 = one octave up.  1.0 does not change the pitch
                dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.8);
                system->playSound(sound, 0, false, &channel);
                // 添加到不同音轨中
                // 只有一个音效，直接添加到第一个
                channel->addDSP(0, dsp);
                LOGI("path:%s", "VOICE_DASHU");
                break;
            case VOICE_JINGSONG:
                // 惊悚(颤抖)
                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 VOICE_GAOGUAI: {// 搞怪(提高语速)
                system->playSound(sound, 0, false, &channel);
                // 传参的目的是拿到frequency的值，如果我们定义一个float类型的指针传进来是没有意义的
                // 因为该指针没有初始化，是没有地址的，也就没办法存值，只能先指向一个有值的变量，完成初始化，
                // 或者直接传递一个基本数据类型变量的地址，用来重新赋值。
                // 传基本类型指针和类指针的区别：
                // 指针必须指向某个已经存在的变量，才能完成初始化，拥有了指向的内存的地址，否则其指向的地址是随意的(这也是为什么要赋为NULL)
                // 这里的类指针比如dsp、channel的初始化是作为函数的回参，通过二级指针进行初始化的(显然我们无法自己对其初始化)，传递一级指针参数的情况，只能在初始化之后

                // 提升播放速度
                channel->getFrequency(&frequency);
                float f = frequency * 1.6f;
                channel->setFrequency(f);
            }
                break;
            case VOICE_KONGLING:// 空灵
                system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);
                // 设置声音之间的间隔 Echo delay in ms.  10  to 5000.  Default = 500
                dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 300);
                // 每秒回音次数Echo decay per delay.  0 to 100.  100.0 = No decay, 0.0 = total decay (ie simple 1 line delay).  Default = 50.0
                dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 20);
                system->playSound(sound, 0, false, &channel);
                channel->addDSP(0, dsp);
                break;
        }
    } catch (...) {
        goto end;
    }

    //更新，没有更新是不会播放声音的
    system->update();
    //播放声音异步，如果没有播放完，
    //	等待播放完成
    while (isPlaying) {
        channel->isPlaying(&isPlaying);
        //休眠，单位：微秒
        usleep(1000 * 1000);    //1秒
    }
    goto end;

    end:
    sound->release();
    system->close();
    system->release();

    env->ReleaseStringUTFChars(path_, path);
}