android 字节转wav,Android下使用SoundTouch实现变声并转为wav格式播放

关于pcm头部加44个字节转为wav格式的方法,请参照我前面写的博文。

关于soundtouc的下载,整理和修改方面的内容请参考iOS那篇博文,这里不再赘述了,其实只要将那个目录下的文件直接拷过来就可以用了。

下面重点介绍一下如何用NDK编译soundtouch。

1.  NDK的相关知识,请查看相关资料,如果有时间我会详细介绍。

2. 在你的工程根目录下,新建jni目录,然后将制作好的SoundTouch拷贝到jni下:

756c2b1edaf6a6142d5d1f405e806321.png

3.  找到STTypes.h头文件,将

#define ST_NO_EXCEPTION_HANDLING    1 原先的注释去掉,即启用这个宏定义,这样就不会使用c++的stdexcep相关的东西了,否则是编译不过去的,如下:

8b057c7cc0f1f663c9f9353d10e609c3.png

4. 编写Android.mk文件

e9416c084667edb451774535cd627c63.png

5.  我们看到上面的Android.mk文件中有一个soundtouch_wapper.cpp,这个是用来连接java和本地c++的一个桥梁,即需要在这个文件中对底层的soundtouch调用进行封装。我们先编写java文件JNISoundTouch.java:

package com.example.soundtouchdemo;

publicclass JNISoundTouch {

publicnativevoid setSampleRate(int sampleRate);

publicnativevoid setChannels(int channel);

publicnativevoid setTempoChange(float newTempo);

publicnativevoid setPitchSemiTones(int newPitch);

publicnativevoid setRateChange(float newRate);

publicnativevoid putSamples(short[] samples, int len);

publicnativeshort[] receiveSamples();

static{

System.loadLibrary("soundtouch");

}

}

这里声明了很多native方法,表示是本地实现的,然后加载了一个叫着“soundtouch”的动态库。

6.    用javah 生成JNISoundTouch.java对应的JNI头文件,先cd到你工程的bin/class目录下

hejinlai_iMac:classes hejinlai$ pwd

/Users/hejinlai/Workspace/Android/SoundTouchDemo/bin/classes

hejinlai_iMac:classes hejinlai$

执行javah com.example.soundtouchdemo.JNISoundTouch生成对应的JNI头文件

hejinlai_iMac:classes hejinlai$ javah com.example.soundtouchdemo.JNISoundTouch

hejinlai_iMac:classes hejinlai$ ls -l

total 8

drwxr-xr-x  3 hejinlai  staff   102  6 19 11:32 com

-rw-r--r--  1 hejinlai  staff  1904  6 19 18:45 com_example_soundtouchdemo_JNISoundTouch.h

hejinlai_iMac:classes hejinlai$

7.    将生成的头文件的内容全部复制到soundtouch_wapper.cpp中,然后这个文件中对头文件生成的方法进行实现:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class com_example_soundtouchdemo_JNISoundTouch */

#ifndef _Included_com_example_soundtouchdemo_JNISoundTouch

#define _Included_com_example_soundtouchdemo_JNISoundTouch

#ifdef __cplusplus

extern"C" {

#endif

#include"SoundTouch/SoundTouch.h"

#define BUFFER_SIZE 4096

soundtouch::SoundTouch mSoundTouch;

/*

* Class: com_example_soundtouchdemo_JNISoundTouch

* Method: setSampleRate

* Signature: (I)V

*/

JNIEXPORT void JNICALL Java_com_example_soundtouchdemo_JNISoundTouch_setSampleRate

(JNIEnv *env, jobject obj, jint sampleRate)

{

mSoundTouch.setSampleRate(sampleRate);

}

/*

* Class: com_example_soundtouchdemo_JNISoundTouch

* Method: setChannels

* Signature: (I)V

*/

JNIEXPORT void JNICALL Java_com_example_soundtouchdemo_JNISoundTouch_setChannels

(JNIEnv *env, jobject obj, jint channel)

{

mSoundTouch.setChannels(channel);

}

/*

* Class: com_example_soundtouchdemo_JNISoundTouch

* Method: setTempoChange

* Signature: (F)V

*/

JNIEXPORT void JNICALL Java_com_example_soundtouchdemo_JNISoundTouch_setTempoChange

(JNIEnv *env, jobject obj, jfloat newTempo)

{

mSoundTouch.setTempoChange(newTempo);

}

/*

* Class: com_example_soundtouchdemo_JNISoundTouch

* Method: setPitchSemiTones

* Signature: (I)V

*/

JNIEXPORT void JNICALL Java_com_example_soundtouchdemo_JNISoundTouch_setPitchSemiTones

(JNIEnv *env, jobject obj, jint pitch)

{

mSoundTouch.setPitchSemiTones(pitch);

}

/*

* Class: com_example_soundtouchdemo_JNISoundTouch

* Method: setRateChange

* Signature: (F)V

*/

JNIEXPORT void JNICALL Java_com_example_soundtouchdemo_JNISoundTouch_setRateChange

(JNIEnv *env, jobject obj, jfloat newRate)

{

mSoundTouch.setRateChange(newRate);

}

/*

* Class: com_example_soundtouchdemo_JNISoundTouch

* Method: putSamples

* Signature: ([SI)V

*/

JNIEXPORT void JNICALL Java_com_example_soundtouchdemo_JNISoundTouch_putSamples

(JNIEnv *env, jobject obj, jshortArray samples, jint len)

{

// 转换为本地数组

jshort *input_samples = env->GetShortArrayElements(samples, NULL);

mSoundTouch.putSamples(input_samples, len);

// 释放本地数组(避免内存泄露)

env->ReleaseShortArrayElements(samples, input_samples, 0);

}

/*

* Class: com_example_soundtouchdemo_JNISoundTouch

* Method: receiveSamples

* Signature: ([SI)I

*/

JNIEXPORT jshortArray JNICALL Java_com_example_soundtouchdemo_JNISoundTouch_receiveSamples

(JNIEnv *env, jobject obj)

{

short buffer[BUFFER_SIZE];

int nSamples = mSoundTouch.receiveSamples(buffer, BUFFER_SIZE);

// 局部引用,创建一个short数组

jshortArray receiveSamples = env->NewShortArray(nSamples);

// 给short数组设置值

env->SetShortArrayRegion(receiveSamples, 0, nSamples, buffer);

return receiveSamples;

}

#ifdef __cplusplus

}

#endif

#endif

这里设计到很多JNI的相关知识,如果读者不是很了解,可以查找相应的资料。

8.  在命令行中,cd到所在工程的jni目录下,调用ndk-build进行编译生成动态库so文件:

hejinlai_iMac:jni hejinlai$ pwd

/Users/hejinlai/Workspace/Android/SoundTouchDemo/jni

hejinlai_iMac:jni hejinlai$ ndk-build

/Users/hejinlai/Android/android-ndk-r8c/build/core/add-application.mk:128: Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in /Users/hejinlai/Workspace/Android/SoundTouchDemo/AndroidManifest.xml

Compile++ thumb  : soundtouch <= AAFilter.cpp

Compile++ thumb  : soundtouch <= BPMDetect.cpp

Compile++ thumb  : soundtouch <= cpu_detect_x86.cpp

Compile++ thumb  : soundtouch <= FIFOSampleBuffer.cpp

Compile++ thumb  : soundtouch <= FIRFilter.cpp

Compile++ thumb  : soundtouch <= mmx_optimized.cpp

Compile++ thumb  : soundtouch <= PeakFinder.cpp

Compile++ thumb  : soundtouch <= RateTransposer.cpp

SharedLibrary  : libsoundtouch.so

Install        : libsoundtouch.so => libs/armeabi/libsoundtouch.so

hejinlai_iMac:jni hejinlai$

9.  设置soundtouch的相关参数:

soundtouch.setSampleRate(16000);

soundtouch.setChannels(1);

soundtouch.setPitchSemiTones(10);

soundtouch.setRateChange(-0.7f);

soundtouch.setTempoChange(0.5f);

10.  调用soundtouch.putSamples方法将录音数据传递给soundtouch处理,然后在调用

soundtouch.receiveSamples方法得到处理后的数据

11. 给处理后的数据加上44个字节头部,转为wav格式,然后保存到sdcrad中:

WaveHeader header = new WaveHeader(fileLength);

byte[] headers = header.getHeader();

// 保存文件

FileOutputStream out = new FileOutputStream(Settings.recordingPath  + "soundtouch.wav");

out.write(headers);

for(byte[] bytes: wavDatas){

out.write(bytes);

}

out.close();

主要的步骤就是这些,这个运行的效果和iOS那个版本是差不多的,大家可以参考。

示例代码下载:http://www.it165.net/uploadfile/2013/0620/20130620085357766.zip

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值