语音增强TFLite模型的安卓部署
语音增强TFLite模型的安卓java部署
TF官网对于关于图像的深度学习模型部署提供了较多的demo,但是对于语音特别是语音增强的示例较少。本文对使用java在安卓部署语音增强模型进行详细记录。
语音增强模型(降噪)使用的是DTLN模型,DTLN是两个模型串联在一起的模型,一个频域的LSTM,一个时域的LSTM。
1. 官网关于模型加载的函数
private MappedByteBuffer loadModelFile(String model) throws IOException {AssetFileDescriptor fileDescriptor = getApplicationContext().getAssets().openFd(model + ".tflite");FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());FileChannel fileChannel = inputStream.getChannel();long startOffset = fileDescriptor.getStartOffset();long declaredLength = fileDescriptor.getDeclaredLength();return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);}
2. 调用模型infer函数
private void loadModule1() {String model1 = "model_1";try {Interpreter.Options options = new Interpreter.Options();options.setNumThreads(4);options.setUseNNAPI(true);// 加载模型文件tflite1 = new Interpreter(loadModelFile(model1), options);Toast.makeText(MainActivity.this, model1 + " model load success", Toast.LENGTH_SHORT).show();} catch (IOException e) {e.printStackTrace();}}
3.模型infer函数
public float[][][] model1_infer(double [] spec){float [] spec_f = new float[spec.length];for (int i=0; i<spec.length; i++){spec_f[i] = (float) spec[i];}float[][][] input1 =new float[1][1][257];//input1赋初值//System.out.println(input1[0][0][i]);System.arraycopy(spec_f, 0, input1[0][0], 0, 257);
// for (int i = 0; i < 257; i++) {
// System.out.println(input1[0][0][i]);
// }float[][][] output1 = new float[1][1][257];//System.out.println(output1[0][0][0]); //自动给定初值0.0float[][][][] output2 = new float[1][2][128][2];float[][][][] input2 = new float[1][2][128][2];Object [] inputs = {input1, input2};Map<Integer, Object> outputs = new HashMap<>();outputs.put(0,output1);outputs.put(1,output2);// 运行模型的predict功能tflite1.runForMultipleInputsOutputs(inputs,outputs);// 测试用,已经有数据了
// for (int u =0; u<10; u++) {
// System.out.println(output1[0][0][u]);
// }
// 注意复数的表示方法
// for (int u =0; u<257; u++) {
// spec_f[u]*output1[0][0][u]*(Math.cos(phase[u]));
// }return output1;}
整体的流程代码如下所示
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//int frame_len = 512;int frame_shift =128;int m_start;int m_end;double [] wav_data_tmp;//wav_data_tmp = new double[frame_len];specY = new double[frame_len/2+1];//timeY = new double[frame_len];phaseY = new double[frame_len/2+1];specX = new double[frame_len];//freqX = new Complex[frame_len];/*****************************************************///加载模型1loadModule1();//模型2推理loadModule2();//读音频及前处理copyAssetAndWrite(filepath);File dataFile=new File(getCacheDir(),filepath);Log.d("1","filePath:" + dataFile.getAbsolutePath());try {wav_data = wav_read(dataFile.getAbsolutePath());} catch (IOException e) {e.printStackTrace();}//测试读入数据,正确
// for (int i=10000; i<10030; i++) {
// System.out.println(wav_data[i]);
// }out_file = new float[wav_data.length];out_file_short = new short[wav_data.length];out_file_int = new int[wav_data.length];in_buffer = new double[frame_len];out_buffer = new float[frame_len];out_block = new float[frame_len];wav_data_tmp = new double[wav_data.length];int numFrames = (wav_data.length-frame_len)/frame_shift;for (int i=0; i<numFrames; i++){m_start = i*frame_shift;m_end = m_start + frame_len;
// for (int j = m_start; j<m_end;j++){
// wav_data_tmp[j-m_start] = wav_data[j]/32768.0;
// }// for (int j = 0; j<wav_data.length; j++){wav_data_tmp[j] = wav_data[j]/32768.0;}for(int e=0;e<512-128;e++) {in_buffer[e] = in_buffer[e+128];}for(int e=512-128;e<512;e++) {in_buffer[e] = wav_data_tmp[i*128+e-(512-128)];}// todo 2021/3/24新加//测试读入数据,正确
// for (int ii=0; ii<10; ii++){
// System.out.println(wav_data_tmp[ii]);
// }//窗函数,python里面没用窗函数
// double[] hamming = HammingWindow();
// wav_data_tmp = applyHammingWindow(wav_data_tmp, hamming);FFT1D = new DoubleFFT_1D(frame_len);double[] fft = new double[frame_len*2];// TODO: 2021/3/24//System.arraycopy(wav_data_tmp,0,fft,0,wav_data_tmp.length);System.arraycopy(in_buffer,0,fft,0,in_buffer.length);// 傅里叶变换FFT1D.realForwardFull(fft);// 测试读入数据,正确
// for (int ii=0; ii<50; ii++){
// System.out.println(fft[ii]);
// }//System.out.println(fft.length);// 频谱幅值及相位for(int h=0; h<frame_len/2+1; h++){specY[h] = Math.hypot(fft[h * 2], fft[h * 2 + 1]);phaseY[h] = Math.atan2(fft[h*2+1], fft[h*2]);}//幅值相位测试正确
// for (int ii=0; ii<20; ii++){
// System.out.println(specY[ii]);
// }
// for (int ii=0; ii<20; ii++){
// System.out.println(phaseY[ii]);
// }//模型1推理float[][][] specR = new float[0][0][257];specR = model1_infer(specY);
// for(int h=250; h<257; h++){
// System.out.println(specR[0][0][h]);
// }//傅里叶逆变换FFT1D = new DoubleFFT_1D(frame_len);double[] ifft = new double[frame_len*2];for(int c=0;c<257;c++){ifft[c*2] = specY[c]*specR[0][0][c]*(Math.cos(phaseY[c]));ifft[c*2+1]=specY[c]*specR[0][0][c]*(Math.sin(phaseY[c]));}for(int c=0;c<255;c++) {ifft[(c+257) * 2] = ifft[(255-c)*2];ifft[(c+257) * 2 + 1] = -ifft[(255-c)*2+1];}
// for(int h=500; h<514; h++){
// System.out.println(ifft[h]);
// }FFT1D.complexInverse(ifft, true);//测试
// for(int h=0; h<10; h++){
// System.out.println(ifft[h]);
// }for(int d=0;d<frame_len;d++){specX[d] = ifft[d*2];}//specX = removeHammingWindow(specX,hamming); //没有窗函数,不需要这个// for (int ii=510; ii<512; ii++){
// System.out.println(specX[ii]);
// }//System.out.println(specX.length);float [][][] signal_sec;signal_sec = model2_infer(specX); //相当于out_block// for (int ii=0; ii<10; ii++){
// System.out.println(signal_sec[0][0][ii]);
// }//变换回整数for( int e=0;e<512; e++){//在后面乘以32768//float temp = (float) (signal_sec[0][0][e]*32768.0);float temp = signal_sec[0][0][e];//System.out.println(temp);//out_block[e+m_start] = (short)temp;out_block[e] = temp;}// for( int e=0;e<512; e++){
// //在后面乘以32768
// float temp = (float) (signal_sec[0][0][e]*32768.0);
// //float temp = signal_sec[0][0][e];
// //System.out.println(temp);
// out_file_short[e+m_start] = (short)temp;
// //out_block[e] = temp;
// }//
// for (int ii=0; ii<10; ii++){
// System.out.println(out_block[ii]);
// }for(int e=0;e<512-128;e++) {out_buffer[e] = out_buffer[e+128];}for(int e=512-128;e<512;e++) {out_buffer[e] = (float) 0.0;}for(int e=0;e<512;e++) {out_buffer[e] = out_buffer[e]+out_block[e];}for(int e=0;e<128;e++) {out_file[i*128+e] = (float) (out_buffer[e]);}
// for (int ii=0; ii<129; ii++){
// System.out.println(out_file[ii]);
// }}for (int ii=0; ii<wav_data.length; ii++) {out_file_short[ii] = (short) (out_file[ii]*32768.0/4.0);}// for (int ii=0; ii<wav_data.length; ii++) {
// out_file_int[ii] = out_file_short[ii];
// }
//
// for (int ii=0; ii<wav_data.length; ii++) {
// out_file_short[ii] = (short) (out_file_short[ii]/(short)max);
// }// 写出音频文件
// copyAssetAndWrite(outfilepath);
// File outdataFile=new File(getCacheDir(),outfilepath);
// Log.d("1","filePath:" + outdataFile.getAbsolutePath());try {wavwrite(out_file_short);} catch (FileNotFoundException e) {e.printStackTrace();}}
参考资料
https://github.com/breizhn/DTLN
https://github.com/tensorflow/examples/tree/master/lite/examples/sound_classification/android
语音增强TFLite模型的安卓部署相关推荐
- Android部署TFLite模型并启用GPU加速
项目准备 训练并量化好的TFLite模型: model.tflite 需要使用TFLite的安卓工程 开发用手机 部署流程 在Gradle中配置TFLite相关库,在build.gradle中补充依赖 ...
- 功率谱 魏凤英统计程序_单通道语音增强之统计信号模型
[欢迎访问我的博客原文](单通道语音增强之统计信号模型) 1. 信号估计理论简述 信号估计理论是现代统计处理的基础课题[@ZhangXianDa2002ModernSP],在通信.语音.图像领域均有广 ...
- 语音顶会 ICASSP 2022 成果分享:基于时频感知域模型的单通道语音增强算法
近日,阿里云视频云音频技术团队与新加坡国立大学李海洲教授团队合作论文 <基于时频感知域模型的单通道语音增强算法 >(Time-Frequency Attention for Monaura ...
- AliCloudDenoise 语音增强算法:助力实时会议系统进入超清音质时代
简介:近些年,随着实时通信技术的发展,在线会议逐渐成为人们工作中不可或缺的重要办公工具,据不完全统计,线上会议中约有 75% 为纯语音会议,即无需开启摄像头和屏幕共享功能,此时会议中的语音质量和清晰度 ...
- 语音增强相关技术综述
1 非监督语音增强技术 2 监督语音增强技术 3 github上提供的源代码及分析 3.1 Dual-signal Transformation LSTM Network 简介 https://git ...
- 冯仕堃:预训练模型哪家强?百度知识增强大模型探索实践!
作者 | 冯仕堃 百度 主任架构师 来源 | DataFunTalk 导读:近年来,预训练语言模型在自然语言处理领域发展迅速,并获得广泛应用.本文将介绍百度基于知识增强的语义理解ERNIE的实践探索, ...
- 训练好的深度学习模型是怎么部署的?
训练好的深度学习模型是怎么部署的? 来源:https://www.zhihu.com/question/329372124 作者:田子宸 先说结论:部署的方式取决于需求 需求一:简单的demo演示,只 ...
- yolov5 6.0版本->onnx->ncnn +安卓部署 附加ncnn环境配置 保姆级详细教程
目标检测:yolov5 6.0版本 ncnn环境安装 至 +安卓部署 一条龙教程 文章目录 背景 一.准备阶段 1.参考文章 #2.流程 二.pt模型->onnx 三.Windows下ncnn环 ...
- 【项目实战课】微信小程序图像识别模型前后端部署实战
欢迎大家来到我们的项目实战课,本期内容是<微信小程序图像识别模型前后端部署实战>.所谓项目实战课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的实战讲解. ...
最新文章
- Linux kernel分析前的准备
- DRF的序列化——Serializers 序列化组件
- Java 8 Friday Goodies:Lambda和XML
- 快速傅里叶变换(FFT)——按时间抽取DIT的基
- [Unity][FlowCanvas][NodeCanvas] ForEach 不适合连接 Wait,FSM 的 SubFlowScript 接受不到事件
- golang 返回值问题
- socket编程,简单查看
- Azure PowerShell (10) 使用PowerShell导出订阅下所有的Azure VM和Cloud Service的高可用情况...
- python求最大回文数_python最长回文串算法
- 高等数学(第七版)同济大学 习题2-4 个人解答
- 【MapGIS必备】常见问题处理(第十四期)
- java guice_java – Guice Inject类中的字段不是由Guice创建的
- EWSA1.50.0.298栈溢出错误
- 前端使用(久派)高拍仪进行拍照上传
- 网站 内容更新 监控 php,网站状态监控方法,使用PHP轻松监控你的网站运行状态...
- spring使用之旅(二) ---- AOP的使用
- 微信生成二维码报invalid action name hint错误的解决方法
- Laravel 生成QRCODE
- がいねんとれいさいのにちじょう
- 实时头发-面部皮肤分割与人脸肤色分类