PaddleSpeech的TTSAndroid编译armv7版本

2023-12-13 10:55:02

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.zip

https://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 tensor
  std::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.MessageDigest

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.baidu.paddle.lite.demo.tts"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        ndk {
            abiFilters 'armeabi-v7a'//, 'arm64-v8a'

        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles 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

文章来源:https://blog.csdn.net/q317379184/article/details/134950807
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。