主要内容

树莓Pi噪声码生成中的关键字识别

这个例子演示了在Raspberry Pi™上使用双向长短期记忆(BiLSTM)网络和mel频率倒谱系数(MFCC)特征提取来识别关键字的代码生成。MATLAB®Coder™与深度学习支持,使生成一个独立的可执行文件金宝app(.elf)树莓派。MATLAB®(.mlx)文件与生成的可执行文件之间的通信通过异步用户数据报协议(UDP)进行。输入的语音信号使用timescope.一个掩码显示为一个围绕关键字YES的被标记实例的蓝色矩形。有关MFCC特征提取和深度学习网络训练的更多细节,请访问基于MFCC和LSTM网络的噪声关键字识别

例子要求

  • MATLAB®编码器接口的深度学习支持包金宝app

  • 支持NEON扩展的ARM处理器金宝app

  • ARM计算库版本20.02.1(在目标ARM硬件上)

  • 编译器和库的环境变量

有关库受金宝app支持的版本以及有关设置环境变量的信息,请参见深度学习与MATLAB编码器的先决条件(MATLAB编码器)

预先训练的网络关键字识别使用MATLAB®和从麦克风流音频

预训练网络的采样率为16kHz。设置窗口长度为512样本,重叠长度为384样本,跳跃长度定义为窗口和重叠长度之间的差值。定义估计掩码的速率。掩码为每一个生成一次numHopsPerUpdate音频帧。

fs = 16 e3;windowLength = 512;overlapLength = 384;hopLength = windowLength - overlapLength;numHopsPerUpdate = 16;maskLength = hopLength * numHopsPerUpdate;

创建一个audioFeatureExtractor对象执行MFCC特征提取。

afe = audioFeatureExtractor (“SampleRate”fs,...“窗口”损害(windowLength“周期”),...“OverlapLength”overlapLength,...“mfcc”,真的,...“mfccDelta”,真的,...“mfccDeltaDelta”,真正的);

下载和加载预先训练的网络,以及平均值()及标准差(年代)用于特征标准化的向量。

url =“http://ssd.mathworks.com/金宝appsupportfiles/audio/KeywordSpotting.zip”;downloadNetFolder =“。/”;netFolder = fullfile (downloadNetFolder,“KeywordSpotting”);如果~存在(netFolder“dir”) disp (“下载预先训练的网络和音频文件(4个文件- 7 MB)……”解压缩(url, downloadNetFolder)结束负载(fullfile (netFolder“KWSNet.mat”),“KWSNet”“M”“S”);

调用generateMATLABFunctionaudioFeatureExtractor对象创建特征提取函数。

generateMATLABFunction (afe“generateKeywordFeatures”“IsStreaming”,真正的);

定义一个音频设备的读者系统对象™从您的麦克风读取音频。设置帧长度等于跳数长度。这使得从麦克风接收到的每一个新的音频帧都可以计算一组新的特性。

frameLength = hopLength;adr = audioDeviceReader (“SampleRate”fs,...“SamplesPerFrame”frameLength,“OutputDataType”“单一”);

创建一个时间范围可视化语音信号和估计掩模。

范围= timescope (“SampleRate”fs,...“TimeSpanSource”“属性”...“时间间隔”5,...“TimeSpanOverrunAction”“滚动”...“BufferLength”fs * 5 * 2,...“ShowLegend”,真的,...“ChannelNames”, {“演讲”“关键词面具”},...“YLimits”(-1.2 - 1.2),...“标题”关键字定位的);

初始化音频数据的缓冲区、计算特征的缓冲区以及用于绘制输入音频和输出语音掩码的缓冲区。

dataBuff = dsp.AsyncBuffer (windowLength);featureBuff = dsp.AsyncBuffer (numHopsPerUpdate);plotBuff = dsp.AsyncBuffer (numHopsPerUpdate * windowLength);

对从麦克风接收到的语音执行关键字识别。要无限期地运行循环,请设置期限.要停止模拟,请关闭范围

显示(范围);期限= 20;抽搐toc < timeLimit && isVisible(scope) data = adr();写(dataBuff、数据);写(plotBuff、数据);帧=阅读(dataBuff windowLength overlapLength);特点= generateKeywordFeatures(框架、fs);写(featureBuff特性。');如果featureBuff。NumUnreadSamples == numHopsPerUpdate featureMatrix = read(featureBuff);featureMatrix (~ isfinite (featureMatrix)) = 0;featureMatrix = (featureMatrix - M)./S;[keywordNet v] = classifyAndUpdateState (KWSNet featureMatrix。');V = double(V) - 1;v = repmat (v hopLength 1);v = (,);v =模式(v);v = repmat(v,numHopsPerUpdate * hopLength,1); data = read(plotBuff); scope([data,v]); drawnowlimitrate结束结束隐藏(范围)

helperKeywordSpottingRaspi金宝app支持函数封装了前面演示的特征提取和网络预测过程。为了使特征提取与代码生成兼容,特征提取由生成的代码处理generateKeywordFeatures函数。为了使网络与代码生成兼容,支持函数使用金宝appcoder.loadDeepLearningNetwork(MATLAB编码器)命令功能,加载网络。

支持函数金宝app使用adsp。UDPReceiver系统对象接收从MATLAB®捕获的音频,并使用dsp。UDPSender系统对象将输入的语音信号连同网络预测的估计掩码一起发送到MATLAB®。同样,MATLAB®的活动脚本使用dsp。UDPSender对象将捕获的语音信号发送给运行在树莓派上的可执行文件dsp。UDPReceiver系统对象接收来自树莓派的语音信号和估计掩码。

生成可执行文件在树莓派

取代hostIPAddress你的机器地址。您的树莓派发送输入语音信号和估计掩码到指定的IP地址。

hostIPAddress =编码器。常数(“172.18.230.30”);

创建代码生成配置对象以生成可执行程序。指定目标语言为c++。

cfg = coder.config (exe”);cfg。TargetLang =“c++”

使用Raspberry Pi上的ARM计算库创建一个用于深度学习代码生成的配置对象。指定树莓派的架构,并将深度学习配置对象附加到代码生成配置对象。

dlcfg =编码器。DeepLearningConfig (“arm-compute”);dlcfg。ArmArchitecture =v7的;dlcfg。ArmComputeVersion =“20.02.1”;cfg。DeepLearningConfig = dlcfg;

使用树莓派支持包功能,金宝appraspi,创建连接到你的树莓派。在以下代码中,替换:

  • raspiname你的树莓派的名字

  • π用你的用户名

  • 密码用你的密码

r = raspi (“raspiname”“π”“密码”);

创建一个coder.hardware(MATLAB编码器)对象,并将其附加到代码生成配置对象。

hw = coder.hardware (“树莓π”);cfg。硬件= hw;

在树莓派上指定构建文件夹。

buildDir =“~ / remoteBuildDir”;cfg.Hardware.BuildDir = buildDir;

生成生成独立可执行文件所需的c++主文件。

cfg。GenerateExampleMain =“GenerateCodeAndCompile”

生成c++代码helperKeywordSpottingRaspi你的树莓派。

codegen配置cfghelperKeywordSpottingRaspiarg游戏{hostIPAddress}报告
部署代码。这可能需要几分钟。警告:函数'helperKeywordSpottingRaspi'不会因为无限循环而终止。Warning in ==> helperkeywordspotingraspi Line: 78 Column: 1代码生成成功(带有警告):查看报告

使用部署的代码执行关键字识别

创建一个命令来打开helperKeywordSpottingRaspi覆盆子派的应用。使用系统发送命令给你的树莓派

applicationName =“helperKeywordSpottingRaspi”;applicationDirPaths = raspi.utils.getRemoteBuildDirectory (“applicationName”applicationName);targetDirPath = applicationDirPaths {1} .directory;exeName = strcat (applicationName,“.elf”);命令= [“cd”targetDirPath,”;。/”exeName,' &> 1 &'];系统(r,命令);

创建一个dsp。UDPSender系统对象发送音频捕获在MATLAB®到您的树莓派。更新targetIPAddress你的树莓派。树莓派接收捕获的音频从同一端口使用dsp。UDPReceiver系统对象。

targetIPAddress =“172.18.240.234”;UDPSend = dsp。UDPSender (“RemoteIPPort”, 26000,“RemoteIPAddress”, targetIPAddress);

创建一个dsp。UDPReceiver从树莓派接收语音数据和预测语音掩码的系统对象。从树莓派接收到的UDP报文由以下几部分组成maskLength面具和语音样本。的最大消息长度dsp。UDPReceiver对象是65507字节。计算缓冲区大小以容纳UDP报文的最大数目。

sizeOfFloatInBytes = 4;speechDataLength = maskLength;numElementsPerUDPPacket = maskLength + speech datallength;maxUDPMessageLength =地板(65507 / sizeOfFloatInBytes);numPackets =地板(maxUDPMessageLength / numElementsPerUDPPacket);bufferSize = numPackets * numElementsPerUDPPacket * sizeOfFloatInBytes;UDPReceive = dsp。UDPReceiver (“LocalIPPort”, 21000,...“MessageDataType”“单身”...“MaximumMessageLength”1 + numElementsPerUDPPacket,...“下面的”bufferSize);

只要时间范围打开或达到时间限制,就锁定关键字。要在达到时间限制之前停止活检测,请关闭时间范围。

抽搐;显示(范围);期限= 20;toc < timelimit && isVisible(scope) x = adr();UDPSend (x);data = UDPReceive ();如果~isempty(data) mask = data(1:maskLength);dataForPlot = data(maskLength + 1: numElementsPerUDPPacket);范围([dataForPlot、面具]);结束drawnowlimitrate结束

释放系统对象并终止独立的可执行文件。

hide(scope) release(UDPSend) release(udreceive) release(scope) release(adr) stopExecutable(codertarget.raspi.raspberrypi,exeName)

使用PIL功能工作流评估执行时间

要评估树莓派上独立可执行文件的执行时间,使用PIL(处理器在循环)工作流。执行PIL profiling,生成PIL function for support function金宝appprofileKeywordSpotting.的profileKeywordSpotting相当于helperKeywordSpottingRaspi,只是前者返回语音和预测语音掩码,而后者使用UDP发送相同的参数。UDP调用所花费的时间小于1毫秒,与总体执行时间相比相对较小。

创建代码生成配置对象来生成PIL函数。

cfg = coder.config (“自由”“是”,真正的);cfg。VerificationMode =“公益诉讼”

设置ARM计算库和架构。

dlcfg =编码器。DeepLearningConfig (“arm-compute”);cfg。DeepLearningConfig = dlcfg;cfg.DeepLearningConfig.ArmArchitecture =v7的;cfg.DeepLearningConfig.ArmComputeVersion =“20.02.1”

建立与目标硬件的连接。

如果(~ (“r”“var”) r =“raspiname”“π”“密码”);结束hw = coder.hardware (“树莓π”);cfg。硬件= hw;

设置构建目录和目标语言。

buildDir =“~ / remoteBuildDir”;cfg.Hardware.BuildDir = buildDir;cfg。TargetLang =“c++”

启用分析并生成PIL代码。一个名为profileKeywordSpotting_pil在当前文件夹中生成。

cfg。CodeExecutionProfiling = true;codegen配置cfgprofileKeywordSpottingarg游戏{pinknoise (hopLength 1 '单')}报告
部署代码。这可能需要几分钟。生成的精灵位置:/home/ Pi / remotebuilddir /MATLAB_ws/R2021a/E/sandbox/sporwal/Examples/ExampleManager/ sporwall . bdoc21a。j1572571/deeplearning_shared-ex18742368/codegen/lib/profileKeywordSpotting/pil代码生成成功:查看报告

评估树莓派的执行时间

多次调用生成的PIL函数以获得平均执行时间。

numPredictCalls = 10;totalCalls = numHopsPerUpdate * numPredictCalls;x = pinknoise (hopLength 1“单一”);k = 1:totalCalls [maskReceived,inputSignal,plotFlag] = profileKeywordSpotting_pil(x); / / / / / / / / / / /结束
###启动应用程序:'codegen\lib\profileKeywordSpotting\pil\profileKeywordSpotting。###启动应用程序profileKeywordSpotting_pil…可以查看执行分析数据。打开仿真数据检查器。终止后可用的执行分析报告。

终止公益诉讼执行。

清晰的profileKeywordSpotting_pil
###主机应用程序产生以下标准输出(stdout)和标准错误(stderr)消息:

生成执行概要报告以评估执行时间。

executionProfile = getCoderExecutionProfile (“profileKeywordSpotting”);报告(executionProfile,...“单位”“秒”...“ScaleFactor”“1 e 03”...“NumericFormat”' % 0.4 f '
ans = ' E: \沙箱\ sporwal \ \ ExampleManager \ sporwal.Bdoc21a.j1572571例子\ deeplearning_shared-ex18742368 \ codegen \ lib \ profileKeywordSpotting \ html \ \ ExecutionProfiling_303d853869fa4b88.html孤儿”

从生成的报告中绘制每个帧的执行时间。

由于初始化开销,第一帧的处理花费了大约20毫秒。时间图中每16帧的峰值(numHopsPerUpdate)对应于每16帧调用一次的计算密集预测函数。最大执行时间约为30毫秒,低于实时流的128毫秒预算。性能是在树莓Pi 4模型B Rev 1.1上测量的。