1.下载docker镜像
docker pull paddlepaddle/paddle-lite:2.0.0_beta
2.克隆代码
git clone https://github.com/PaddlePaddle/Paddle-Lite.git
3.运行容器
docker run -it --name paddlelite_docker -v $PWD/Paddle-Lite:/Paddle-Lite --net=host paddlepaddle/paddle-lite /bin/bash
4.编译opt工具
cd Paddle-Lite
./lite/tools/build.sh build_optimize_tool --with_extra=ON
5.下载模型
https://paddlespeech.bj.bcebos.com/Parakeet/released_models/fastspeech2/fastspeech2_cnndecoder_csmsc_static_1.0.0.ziphttps://paddlespeech.bj.bcebos.com/Parakeet/released_models/mb_melgan/mb_melgan_csmsc_static_0.1.1.zip
mb_melgan_csmsc_static_0.1.1.zip
fastspeech2_cnndecoder_csmsc_static_1.0.0.zip
6.模型转换
cd /Paddle-Lite/build.opt/lite/api
./opt --model_file=/Paddle-Lite/models/fastspeech2_cnndecoder_csmsc_static_1.0.0/fastspeech2_csmsc.pdmodel --param_file=/Paddle-Lite/models/fastspeech2_cnndecoder_csmsc_static_1.0.0/fastspeech2_csmsc.pdiparams --valid_targets=arm --optimize_out_type=naive_buffer --optimize_out=/Paddle-Lite/models/fastspeech2_csmsc_arm --quant_model=true --quant_type=QUANT_INT8 ./opt --model_file=/Paddle-Lite/models/mb_melgan_csmsc_static_0.1.1/mb_melgan_csmsc.pdmodel --param_file=/Paddle-Lite/models/mb_melgan_csmsc_static_0.1.1/mb_melgan_csmsc.pdiparams --valid_targets=arm --optimize_out_type=naive_buffer --optimize_out=/Paddle-Lite/models/mb_melgan_csmsc_arm --quant_model=true --quant_type=QUANT_INT8
mb_melgan_csmsc_arm.nb
fastspeech2_csmsc_arm.nb
7.编译预测动态库
a.修改代码Paddle-Lite/lite/kernels/arm/slice_compute.cc
inline std::vector<int64_t> get_new_data_from_tensorlist(const std::vector<lite::Tensor*>& list_new_data_tensor) {// get tensorstd::vector<int64_t> vec_new_data;for (size_t i = 0; i < list_new_data_tensor.size(); ++i) {auto tensor = list_new_data_tensor[i];LOG(WARNING) <<" tensor dims is :"<<tensor->dims();// CHECK_EQ(tensor->dims(), DDim({1})) << "shape of dim tensor should be [1]";if (tensor->precision() == PrecisionType::kInt32) {vec_new_data.push_back(static_cast<int64_t>(*tensor->data<int32_t>()));} else if (tensor->precision() == PrecisionType::kInt64) {vec_new_data.push_back(static_cast<int64_t>(*tensor->data<int64_t>()));} else {vec_new_data.push_back(static_cast<int64_t>(*tensor->data<int32_t>()));LOG(WARNING) << "slice StartsTensor or EndsTensor :The dtype of Tensor ""must be int32 ""or int64";}}return vec_new_data;
}
b.修改Paddle-Lite/lite/api/android/jni/native/tensor_jni.h,新增声明
/** Class: com_baidu_paddle_lite_Tensor* Method: nativeSetData* Signature: ([J)Z*/
JNIEXPORT jboolean JNICALL Java_com_baidu_paddle_lite_Tensor_nativeSetData___3J(JNIEnv *, jobject, jlongArray);
c.修改Paddle-Lite/lite/api/android/jni/native/tensor_jni.cc,新增实现
JNIEXPORT jboolean JNICALL Java_com_baidu_paddle_lite_Tensor_nativeSetData___3J(JNIEnv *env, jobject jtensor, jlongArray buf) {std::unique_ptr<Tensor> *tensor = get_writable_tensor_pointer(env, jtensor);if (tensor == nullptr || (*tensor == nullptr)) {return JNI_FALSE;}int64_t buf_size = (int64_t)env->GetArrayLength(buf);if (buf_size != product((*tensor)->shape())) {return JNI_FALSE;}int64_t *input = (*tensor)->mutable_data<int64_t>();env->GetLongArrayRegion(buf, 0, buf_size, input);return JNI_TRUE;
}
d.编译脚本
./lite/tools/build_android.sh --arch=armv7 --toolchain=gcc --android_stl=c++_static --with_java=ON --with_extra=ON
e.编译产物
libpaddle_lite_jni.so
8.调整Android工程代码
a.修改D:\02Code\code\PaddleSpeech-r1.4.1\demos\TTSAndroid\app\build.gradle
import java.security.MessageDigestapply plugin: 'com.android.application'android {compileSdkVersion 28defaultConfig {applicationId "com.baidu.paddle.lite.demo.tts"minSdkVersion 15targetSdkVersion 28versionCode 1versionName "1.0"testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"ndk {abiFilters 'armeabi-v7a'//, 'arm64-v8a'}}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}
}dependencies {implementation fileTree(include: ['*.jar'], dir: 'libs')implementation 'com.android.support:appcompat-v7:28.0.0'implementation 'com.android.support.constraint:constraint-layout:1.1.3'implementation 'com.android.support:design:28.0.0'testImplementation 'junit:junit:4.12'androidTestImplementation 'com.android.support.test:runner:1.0.2'androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'implementation files('libs/PaddlePredictor.jar')
}
b.修改com/baidu/paddle/lite/demo/tts/Predictor.java及对应的调用地方,主要是数据类型由float改为long
public boolean runModel(long[] phones) {if (!isLoaded()) {return false;}Date start = new Date();Tensor am_output_handle = getAMOutput(phones, AMPredictor);wav = getVOCOutput(am_output_handle, VOCPredictor);Date end = new Date();inferenceTime = (end.getTime() - start.getTime());Log.d(TAG, "runModel: "+inferenceTime+"ms");return true;
}public Tensor getAMOutput(long[] phones, PaddlePredictor am_predictor) {Tensor phones_handle = am_predictor.getInput(0);long[] dims = {phones.length};phones_handle.resize(dims);phones_handle.setData(phones);am_predictor.run();Tensor am_output_handle = am_predictor.getOutput(0);// [?, 80]// long outputShape[] = am_output_handle.shape();float[] am_output_data = am_output_handle.getFloatData();return am_output_handle;}
c.工程结构
ndk需要于docker镜像一致,采用17.2
d.编译产出
TTSAndroid.apk