<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>语音降噪 on BeYoung</title>
    <link>https://lyapple2008.github.io/tags/%E8%AF%AD%E9%9F%B3%E9%99%8D%E5%99%AA/</link>
    <description>Recent content in 语音降噪 on BeYoung</description>
    <image>
      <title>BeYoung</title>
      <url>https://lyapple2008.github.io/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</url>
      <link>https://lyapple2008.github.io/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</link>
    </image>
    <generator>Hugo -- 0.152.2</generator>
    <language>zh</language>
    <copyright>See this site&amp;rsquo;s source code here, licensed under GPLv3 ·</copyright>
    <lastBuildDate>Mon, 03 Nov 2025 19:39:53 +0800</lastBuildDate>
    <atom:link href="https://lyapple2008.github.io/tags/%E8%AF%AD%E9%9F%B3%E9%99%8D%E5%99%AA/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>使用ORT进行语音降噪模型推理</title>
      <link>https://lyapple2008.github.io/posts/202511/2025-11-03-%E4%BD%BF%E7%94%A8ort%E8%BF%9B%E8%A1%8C%E8%AF%AD%E9%9F%B3%E9%99%8D%E5%99%AA%E6%8E%A8%E7%90%86/</link>
      <pubDate>Mon, 03 Nov 2025 19:39:53 +0800</pubDate>
      <guid>https://lyapple2008.github.io/posts/202511/2025-11-03-%E4%BD%BF%E7%94%A8ort%E8%BF%9B%E8%A1%8C%E8%AF%AD%E9%9F%B3%E9%99%8D%E5%99%AA%E6%8E%A8%E7%90%86/</guid>
      <description>&lt;p&gt;在深度学习语音降噪模型的部署过程中，选择合适的推理引擎至关重要。ONNX Runtime（ORT）作为微软开源的跨平台推理引擎，在性能、兼容性和易用性方面表现出色，已成为许多生产环境的首选。本文将介绍为什么选择ORT，ORT的核心概念和使用流程，以及在使用ORT进行语音降噪推理时需要注意的关键事项，特别是针对时序模型（如GRU/LSTM）的隐状态管理。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>在深度学习语音降噪模型的部署过程中，选择合适的推理引擎至关重要。ONNX Runtime（ORT）作为微软开源的跨平台推理引擎，在性能、兼容性和易用性方面表现出色，已成为许多生产环境的首选。本文将介绍为什么选择ORT，ORT的核心概念和使用流程，以及在使用ORT进行语音降噪推理时需要注意的关键事项，特别是针对时序模型（如GRU/LSTM）的隐状态管理。</p>
<h2 id="一为什么选择ort">一、为什么选择ORT？</h2>
<h3 id="11-跨平台支持">1.1 跨平台支持</h3>
<p>ORT提供了广泛的平台支持，包括：</p>
<ul>
<li><strong>CPU推理</strong>：支持x86、ARM等架构，可在Windows、Linux、macOS、Android、iOS等系统运行</li>
<li><strong>GPU加速</strong>：支持CUDA（NVIDIA GPU）、DirectML（Windows）、TensorRT等</li>
<li><strong>专用硬件</strong>：支持CoreML（Apple Silicon）、OpenVINO（Intel）、QNN（Qualcomm）等</li>
</ul>
<p>这种跨平台特性使得同一套代码可以在不同设备上运行，大大降低了部署成本。</p>
<h3 id="12-性能优化">1.2 性能优化</h3>
<p>ORT在性能方面做了大量优化：</p>
<ul>
<li><strong>图优化</strong>：自动进行算子融合、常量折叠、死代码消除等优化</li>
<li><strong>执行提供者（Execution Provider）</strong>：针对不同硬件提供专门的优化实现</li>
<li><strong>动态形状支持</strong>：支持动态batch size和序列长度，适合实时推理场景</li>
</ul>
<h3 id="13-模型格式标准化">1.3 模型格式标准化</h3>
<p>ORT基于ONNX（Open Neural Network Exchange）格式，这是业界标准的模型交换格式：</p>
<ul>
<li><strong>框架无关</strong>：可以从PyTorch、TensorFlow、Keras等框架导出ONNX模型</li>
<li><strong>版本兼容</strong>：ONNX规范持续演进，ORT保持向后兼容</li>
<li><strong>工具生态</strong>：丰富的模型转换和优化工具</li>
</ul>
<h3 id="14-易于集成">1.4 易于集成</h3>
<p>ORT提供了多种语言绑定：</p>
<ul>
<li><strong>C++ API</strong>：适合高性能场景和嵌入式设备</li>
<li><strong>Python API</strong>：便于快速原型开发和调试</li>
<li><strong>C#、Java、JavaScript</strong>：支持多种应用场景</li>
</ul>
<h3 id="15-活跃的社区支持">1.5 活跃的社区支持</h3>
<p>作为微软开源项目，ORT拥有活跃的社区和持续的更新，bug修复和新功能迭代速度快。</p>
<h2 id="二ort基本概念与推理流程">二、ORT基本概念与推理流程</h2>
<h3 id="21-核心概念">2.1 核心概念</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">   ┌───────────────────────────────┐
</span></span><span class="line"><span class="cl">   │ OrtEnv （运行时环境）         │
</span></span><span class="line"><span class="cl">   │ └─ 管理全局资源、线程池等     │
</span></span><span class="line"><span class="cl">   └──────────────┬────────────────┘
</span></span><span class="line"><span class="cl">                  │
</span></span><span class="line"><span class="cl">   ┌──────────────┴────────────────┐
</span></span><span class="line"><span class="cl">   │ OrtSession （推理会话）        │
</span></span><span class="line"><span class="cl">   │ └─ 持有已加载的 ONNX 模型      │
</span></span><span class="line"><span class="cl">   └──────────────┬────────────────┘
</span></span><span class="line"><span class="cl">                  │
</span></span><span class="line"><span class="cl">   ┌──────────────┴────────────────────────┐
</span></span><span class="line"><span class="cl">   │ OrtRun（一次推理调用）                │
</span></span><span class="line"><span class="cl">   │ ├─ 输入 OrtValue (Tensor 等)           │
</span></span><span class="line"><span class="cl">   │ ├─ 输出 OrtValue                      │
</span></span><span class="line"><span class="cl">   │ └─ 在 Env/Session 的线程池中执行      │
</span></span><span class="line"><span class="cl">   └────────────────────────────────────────┘</span></span></code></pre></td></tr></table>
</div>
</div>
<h4 id="ortenv运行时环境">OrtEnv（运行时环境）</h4>
<p><code>OrtEnv</code>是ORT的全局运行时环境，负责管理线程池、日志等全局资源。通常一个进程只需要创建一个<code>OrtEnv</code>实例：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;onnxruntime_c_api.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 创建运行时环境
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">OrtEnv</span><span class="o">*</span> <span class="n">env</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">OrtStatus</span><span class="o">*</span> <span class="n">status</span> <span class="o">=</span> <span class="nf">OrtCreateEnv</span><span class="p">(</span><span class="n">ORT_LOGGING_LEVEL_WARNING</span><span class="p">,</span> <span class="s">&#34;ORT&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">env</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 错误处理
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">msg</span> <span class="o">=</span> <span class="nf">OrtGetErrorMessage</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">OrtReleaseStatus</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h4 id="ortsession推理会话">OrtSession（推理会话）</h4>
<p><code>OrtSession</code>负责加载ONNX模型并执行推理。创建会话需要先创建会话选项：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;onnxruntime_c_api.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 1. 创建会话选项
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">OrtSessionOptions</span><span class="o">*</span> <span class="n">session_options</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtCreateSessionOptions</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_options</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 2. 创建推理会话
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">OrtSession</span><span class="o">*</span> <span class="n">session</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">model_path</span> <span class="o">=</span> <span class="s">&#34;denoise_model.onnx&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">status</span> <span class="o">=</span> <span class="nf">OrtCreateSession</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">model_path</span><span class="p">,</span> <span class="n">session_options</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">session</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 错误处理
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">msg</span> <span class="o">=</span> <span class="nf">OrtGetErrorMessage</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">OrtReleaseStatus</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 3. 释放资源（使用完毕后）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtReleaseSessionOptions</span><span class="p">(</span><span class="n">session_options</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtReleaseSession</span><span class="p">(</span><span class="n">session</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtReleaseEnv</span><span class="p">(</span><span class="n">env</span><span class="p">);</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h4 id="execution-provider-ep">Execution Provider (EP)</h4>
<p>执行提供者决定了模型在哪个硬件上运行。在C API中，通过<code>OrtSessionOptionsAppendExecutionProvider</code>添加EP：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// CPU执行（默认，无需显式添加）
</span></span></span><span class="line"><span class="cl"><span class="c1">// 直接创建会话即可使用CPU
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// CUDA执行（需要NVIDIA GPU）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtSessionOptionsAppendExecutionProvider_CUDA</span><span class="p">(</span><span class="n">session_options</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// TensorRT执行（需要NVIDIA GPU和TensorRT）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">OrtTensorRTProviderOptions</span> <span class="n">trt_options</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtSessionOptionsAppendExecutionProvider_TensorRT</span><span class="p">(</span><span class="n">session_options</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">trt_options</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// CoreML执行（macOS/iOS）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtSessionOptionsAppendExecutionProvider_CoreML</span><span class="p">(</span><span class="n">session_options</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 创建会话（会按顺序尝试EP，失败则回退到下一个）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtCreateSession</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">model_path</span><span class="p">,</span> <span class="n">session_options</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">session</span><span class="p">);</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h4 id="inputoutput">Input/Output</h4>
<p>模型的输入输出通过<code>OrtValue</code>传递，需要手动创建和管理：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 1. 获取输入输出信息
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">size_t</span> <span class="n">num_input_nodes</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">OrtStatus</span><span class="o">*</span> <span class="n">status</span> <span class="o">=</span> <span class="nf">OrtSessionGetInputCount</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">num_input_nodes</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">input_name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">OrtTypeInfo</span><span class="o">*</span> <span class="n">input_type_info</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtSessionGetInputName</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">input_name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtSessionGetInputTypeInfo</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">input_type_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 2. 准备输入数据
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">float</span> <span class="n">input_data</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="cm">/* audio_features数据 */</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="kt">int64_t</span> <span class="n">input_shape</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">480</span><span class="p">};</span>  <span class="c1">// batch_size, feature_dim
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">size_t</span> <span class="n">input_tensor_size</span> <span class="o">=</span> <span class="mi">480</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">OrtValue</span><span class="o">*</span> <span class="n">input_tensor</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">OrtMemoryInfo</span><span class="o">*</span> <span class="n">memory_info</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtCreateCpuMemoryInfo</span><span class="p">(</span><span class="n">OrtArenaAllocator</span><span class="p">,</span> <span class="n">OrtMemTypeDefault</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">memory_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtCreateTensorWithDataAsOrtValue</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">memory_info</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">input_data</span><span class="p">,</span> <span class="n">input_tensor_size</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="n">input_shape</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">&amp;</span><span class="n">input_tensor</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 3. 执行推理
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">input_names</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="n">input_name</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">output_names</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#34;output&#34;</span><span class="p">};</span>  <span class="c1">// 根据模型实际输出名称
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">OrtValue</span><span class="o">*</span> <span class="n">output_tensor</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">status</span> <span class="o">=</span> <span class="nf">OrtRun</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">input_names</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">input_tensor</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">output_names</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">output_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 4. 获取输出数据
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">float</span><span class="o">*</span> <span class="n">output_data</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtGetTensorMutableData</span><span class="p">(</span><span class="n">output_tensor</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">output_data</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 使用output_data...
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 5. 释放资源
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtReleaseValue</span><span class="p">(</span><span class="n">output_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtReleaseValue</span><span class="p">(</span><span class="n">input_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtReleaseMemoryInfo</span><span class="p">(</span><span class="n">memory_info</span><span class="p">);</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h3 id="22-性能优化选项">2.2 性能优化选项</h3>
<p>ORT提供了多种性能优化选项，在C API中通过<code>OrtSessionOptions</code>进行配置：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">OrtSessionOptions</span><span class="o">*</span> <span class="n">session_options</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">OrtCreateSessionOptions</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_options</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 图优化级别
</span></span></span><span class="line"><span class="cl"><span class="c1">// ORT_DISABLE_ALL, ORT_ENABLE_BASIC, ORT_ENABLE_EXTENDED, ORT_ENABLE_ALL
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtSetSessionGraphOptimizationLevel</span><span class="p">(</span><span class="n">session_options</span><span class="p">,</span> <span class="n">ORT_ENABLE_ALL</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 线程数设置
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtSetIntraOpNumThreads</span><span class="p">(</span><span class="n">session_options</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>  <span class="c1">// 算子内部并行线程数
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtSetInterOpNumThreads</span><span class="p">(</span><span class="n">session_options</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">// 算子间并行线程数
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 内存模式
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtEnableMemPattern</span><span class="p">(</span><span class="n">session_options</span><span class="p">);</span>  <span class="c1">// 启用内存模式优化
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtEnableCpuMemArena</span><span class="p">(</span><span class="n">session_options</span><span class="p">);</span> <span class="c1">// 启用CPU内存池
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 执行模式
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtSetSessionExecutionMode</span><span class="p">(</span><span class="n">session_options</span><span class="p">,</span> <span class="n">ORT_SEQUENTIAL</span><span class="p">);</span>  <span class="c1">// 顺序执行
</span></span></span><span class="line"><span class="cl"><span class="c1">// OrtSetSessionExecutionMode(session_options, ORT_PARALLEL);  // 并行执行
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 优化配置文件（可选，用于更精细的控制）
</span></span></span><span class="line"><span class="cl"><span class="c1">// OrtSetOptimizedModelFilePath(session_options, &#34;optimized_model.onnx&#34;);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// 创建会话时应用这些选项
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtCreateSession</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">model_path</span><span class="p">,</span> <span class="n">session_options</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">session</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 使用完毕后释放
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">OrtReleaseSessionOptions</span><span class="p">(</span><span class="n">session_options</span><span class="p">);</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h2 id="三语音降噪推理的特殊注意事项">三、语音降噪推理的特殊注意事项</h2>
<p>语音降噪模型通常使用时序建模网络（如GRU、LSTM），这些网络具有隐状态（hidden state），在实时推理时需要特别注意状态管理。</p>
<h3 id="31-为什么ort不保存隐状态">3.1 为什么ORT不保存隐状态？</h3>
<p>ORT（ONNX Runtime）采用**无状态（stateless）**的设计理念，即每次推理调用都是独立的，ORT不会在内部保存任何状态信息。这种设计有以下几个重要原因：</p>
<h4 id="311-设计理念无状态推理">3.1.1 设计理念：无状态推理</h4>
<p>ORT的核心设计原则是每次<code>OrtRun</code>调用都是完全独立的，不依赖之前的调用结果。这种设计带来以下优势：</p>
<ol>
<li><strong>线程安全</strong>：多个线程可以同时使用同一个<code>OrtSession</code>进行推理，而不会因为共享状态导致竞争条件</li>
<li><strong>可重现性</strong>：相同的输入总是产生相同的输出，不受历史状态影响</li>
<li><strong>灵活性</strong>：可以灵活控制何时重置状态、何时复用状态，适应不同的应用场景</li>
</ol>
<h4 id="312-状态管理的责任归属">3.1.2 状态管理的责任归属</h4>
<p>在ORT的设计中，<strong>状态管理是应用层的责任</strong>，而不是推理引擎的责任。这样做的好处是：</p>
<ul>
<li><strong>应用层控制</strong>：应用可以根据业务需求决定何时重置状态、如何管理多个流的状态</li>
<li><strong>内存管理</strong>：应用可以精确控制状态的内存分配和释放时机</li>
<li><strong>多实例支持</strong>：同一个模型可以同时处理多个独立的音频流，每个流维护自己的状态</li>
</ul>
<h4 id="313-与训练框架的差异">3.1.3 与训练框架的差异</h4>
<p>在训练框架（如PyTorch、TensorFlow）中，RNN/LSTM层通常会维护隐状态：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># PyTorch训练时的行为</span>
</span></span><span class="line"><span class="cl"><span class="n">lstm</span> <span class="o">=</span> <span class="n">nn</span><span class="o">.</span><span class="n">LSTM</span><span class="p">(</span><span class="n">input_size</span><span class="p">,</span> <span class="n">hidden_size</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">output</span><span class="p">,</span> <span class="p">(</span><span class="n">hidden</span><span class="p">,</span> <span class="n">cell</span><span class="p">)</span> <span class="o">=</span> <span class="n">lstm</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="p">(</span><span class="n">hidden</span><span class="p">,</span> <span class="n">cell</span><span class="p">))</span>  <span class="c1"># 状态在层内部管理</span></span></span></code></pre></td></tr></table>
</div>
</div>
<p>但在ONNX导出和ORT推理时，隐状态被<strong>显式化</strong>为模型的输入和输出：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// ONNX模型结构
</span></span></span><span class="line"><span class="cl"><span class="c1">// 输入: [audio_features, hidden_state, cell_state]  // 显式输入
</span></span></span><span class="line"><span class="cl"><span class="c1">// 输出: [denoised_features, new_hidden_state, new_cell_state]  // 显式输出
</span></span></span></code></pre></td></tr></table>
</div>
</div>
<p>这种显式化的设计使得：</p>
<ul>
<li>状态在模型外部可见和可控</li>
<li>可以跨框架、跨平台保持一致的行为</li>
<li>便于调试和优化</li>
</ul>
<h4 id="314-实际影响">3.1.4 实际影响</h4>
<p>对于语音降噪等时序应用，ORT不保存隐状态意味着：</p>
<ol>
<li><strong>必须手动传递状态</strong>：每次推理时，需要将上一次的输出状态作为下一次的输入</li>
<li><strong>状态持久化由应用负责</strong>：如果需要保存状态（如断点续传），需要应用层实现</li>
<li><strong>多流处理需要独立状态</strong>：处理多个音频流时，需要为每个流维护独立的状态变量</li>
</ol>
<p>这种设计虽然增加了应用层的复杂度，但提供了更大的灵活性和控制力，特别适合生产环境中的复杂场景。</p>
<h3 id="32-实战使用ort进行rnnoise降噪推理">3.2 实战使用ORT进行Rnnoise降噪推理</h3>
<p>RNNoise是一个基于深度学习的实时语音降噪模型，使用了三个GRU层（VAD GRU、Noise GRU、Denoise GRU）进行时序建模。在使用ORT进行推理时，需要特别注意这三个GRU层的隐状态管理。</p>
<h4 id="321-转换成onnx模型时导出gru隐状态输入输出端口">3.2.1 转换成ONNX模型时导出GRU隐状态输入输出端口</h4>
<p>RNNoise的Keras训练模型通常只接受特征输入，GRU的隐状态在内部管理。但在导出ONNX模型用于ORT推理时，需要将隐状态显式化为模型的输入和输出端口，这样才能在应用层控制状态传递。</p>
<p><strong>关键步骤：</strong></p>
<ol>
<li><strong>重建模型结构</strong>：创建一个新的推理模型，为每个GRU层添加<code>initial_state</code>输入和<code>return_state=True</code>输出</li>
<li><strong>复制权重</strong>：从训练模型复制所有层的权重到新模型</li>
<li><strong>定义输入输出</strong>：新模型有4个输入（features + 3个GRU状态）和5个输出（denoise_output + vad_output + 3个GRU状态）</li>
</ol>
<p>下图中，左侧为没有导出隐状态的onnx模型可视化图，可以看到gru的隐状态每次都是被重置的；右侧为导出了隐状态的onnx模型可视化图，可以看到gru节点对应了一个gru state输入端口和一个gru state的输出端口。</p>
<p><img alt="rnnoise-onnx-导出隐状态" loading="lazy" src="/images/2025-11-03/rnnoise-onnx-%E5%AF%BC%E5%87%BA%E9%9A%90%E7%8A%B6%E6%80%81.jpg"></p>
<p>以下是完整的转换代码：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span><span class="lnt">150
</span><span class="lnt">151
</span><span class="lnt">152
</span><span class="lnt">153
</span><span class="lnt">154
</span><span class="lnt">155
</span><span class="lnt">156
</span><span class="lnt">157
</span><span class="lnt">158
</span><span class="lnt">159
</span><span class="lnt">160
</span><span class="lnt">161
</span><span class="lnt">162
</span><span class="lnt">163
</span><span class="lnt">164
</span><span class="lnt">165
</span><span class="lnt">166
</span><span class="lnt">167
</span><span class="lnt">168
</span><span class="lnt">169
</span><span class="lnt">170
</span><span class="lnt">171
</span><span class="lnt">172
</span><span class="lnt">173
</span><span class="lnt">174
</span><span class="lnt">175
</span><span class="lnt">176
</span><span class="lnt">177
</span><span class="lnt">178
</span><span class="lnt">179
</span><span class="lnt">180
</span><span class="lnt">181
</span><span class="lnt">182
</span><span class="lnt">183
</span><span class="lnt">184
</span><span class="lnt">185
</span><span class="lnt">186
</span><span class="lnt">187
</span><span class="lnt">188
</span><span class="lnt">189
</span><span class="lnt">190
</span><span class="lnt">191
</span><span class="lnt">192
</span><span class="lnt">193
</span><span class="lnt">194
</span><span class="lnt">195
</span><span class="lnt">196
</span><span class="lnt">197
</span><span class="lnt">198
</span><span class="lnt">199
</span><span class="lnt">200
</span><span class="lnt">201
</span><span class="lnt">202
</span><span class="lnt">203
</span><span class="lnt">204
</span><span class="lnt">205
</span><span class="lnt">206
</span><span class="lnt">207
</span><span class="lnt">208
</span><span class="lnt">209
</span><span class="lnt">210
</span><span class="lnt">211
</span><span class="lnt">212
</span><span class="lnt">213
</span><span class="lnt">214
</span><span class="lnt">215
</span><span class="lnt">216
</span><span class="lnt">217
</span><span class="lnt">218
</span><span class="lnt">219
</span><span class="lnt">220
</span><span class="lnt">221
</span><span class="lnt">222
</span><span class="lnt">223
</span><span class="lnt">224
</span><span class="lnt">225
</span><span class="lnt">226
</span><span class="lnt">227
</span><span class="lnt">228
</span><span class="lnt">229
</span><span class="lnt">230
</span><span class="lnt">231
</span><span class="lnt">232
</span><span class="lnt">233
</span><span class="lnt">234
</span><span class="lnt">235
</span><span class="lnt">236
</span><span class="lnt">237
</span><span class="lnt">238
</span><span class="lnt">239
</span><span class="lnt">240
</span><span class="lnt">241
</span><span class="lnt">242
</span><span class="lnt">243
</span><span class="lnt">244
</span><span class="lnt">245
</span><span class="lnt">246
</span><span class="lnt">247
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">keras.backend</span> <span class="k">as</span> <span class="nn">K</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">keras.constraints</span> <span class="kn">import</span> <span class="n">Constraint</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">keras.layers</span> <span class="kn">import</span> <span class="n">Input</span><span class="p">,</span> <span class="n">Dense</span><span class="p">,</span> <span class="n">GRU</span><span class="p">,</span> <span class="n">concatenate</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">keras.models</span> <span class="kn">import</span> <span class="n">Model</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">my_crossentropy</span><span class="p">(</span><span class="n">y_true</span><span class="p">,</span> <span class="n">y_pred</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">K</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">K</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">y_true</span> <span class="o">-</span> <span class="mf">0.5</span><span class="p">)</span> <span class="o">*</span> <span class="n">K</span><span class="o">.</span><span class="n">binary_crossentropy</span><span class="p">(</span><span class="n">y_pred</span><span class="p">,</span> <span class="n">y_true</span><span class="p">),</span> <span class="n">axis</span><span class="o">=-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">mymask</span><span class="p">(</span><span class="n">y_true</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">K</span><span class="o">.</span><span class="n">minimum</span><span class="p">(</span><span class="n">y_true</span> <span class="o">+</span> <span class="mf">1.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">msse</span><span class="p">(</span><span class="n">y_true</span><span class="p">,</span> <span class="n">y_pred</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">K</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">mymask</span><span class="p">(</span><span class="n">y_true</span><span class="p">)</span> <span class="o">*</span> <span class="n">K</span><span class="o">.</span><span class="n">square</span><span class="p">(</span><span class="n">K</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">y_pred</span><span class="p">)</span> <span class="o">-</span> <span class="n">K</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">y_true</span><span class="p">)),</span> <span class="n">axis</span><span class="o">=-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">mycost</span><span class="p">(</span><span class="n">y_true</span><span class="p">,</span> <span class="n">y_pred</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">K</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">mymask</span><span class="p">(</span><span class="n">y_true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="o">*</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="mi">10</span> <span class="o">*</span> <span class="n">K</span><span class="o">.</span><span class="n">square</span><span class="p">(</span><span class="n">K</span><span class="o">.</span><span class="n">square</span><span class="p">(</span><span class="n">K</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">y_pred</span><span class="p">)</span> <span class="o">-</span> <span class="n">K</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">y_true</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">            <span class="o">+</span> <span class="n">K</span><span class="o">.</span><span class="n">square</span><span class="p">(</span><span class="n">K</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">y_pred</span><span class="p">)</span> <span class="o">-</span> <span class="n">K</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">y_true</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">            <span class="o">+</span> <span class="mf">0.01</span> <span class="o">*</span> <span class="n">K</span><span class="o">.</span><span class="n">binary_crossentropy</span><span class="p">(</span><span class="n">y_pred</span><span class="p">,</span> <span class="n">y_true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">axis</span><span class="o">=-</span><span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">my_accuracy</span><span class="p">(</span><span class="n">y_true</span><span class="p">,</span> <span class="n">y_pred</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">K</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">K</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">y_true</span> <span class="o">-</span> <span class="mf">0.5</span><span class="p">)</span> <span class="o">*</span> <span class="n">K</span><span class="o">.</span><span class="n">equal</span><span class="p">(</span><span class="n">y_true</span><span class="p">,</span> <span class="n">K</span><span class="o">.</span><span class="n">round</span><span class="p">(</span><span class="n">y_pred</span><span class="p">)),</span> <span class="n">axis</span><span class="o">=-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">WeightClip</span><span class="p">(</span><span class="n">Constraint</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Accept **kwargs to be compatible with Keras deserialization that may pass &#39;name&#39; etc.</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>  <span class="c1"># kwargs may include &#39;name&#39;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">c</span> <span class="o">=</span> <span class="n">c</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">K</span><span class="o">.</span><span class="n">clip</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="o">-</span><span class="bp">self</span><span class="o">.</span><span class="n">c</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">c</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">get_config</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">{</span><span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="s1">&#39;c&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">c</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">CUSTOM_OBJECTS</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;my_crossentropy&#39;</span><span class="p">:</span> <span class="n">my_crossentropy</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;mymask&#39;</span><span class="p">:</span> <span class="n">mymask</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;msse&#39;</span><span class="p">:</span> <span class="n">msse</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;mycost&#39;</span><span class="p">:</span> <span class="n">mycost</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;my_accuracy&#39;</span><span class="p">:</span> <span class="n">my_accuracy</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;WeightClip&#39;</span><span class="p">:</span> <span class="n">WeightClip</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">rebuild_model_with_states</span><span class="p">(</span><span class="n">training_model</span><span class="p">:</span> <span class="n">Model</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Model</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">    自动重建模型，添加GRU隐状态输入/输出端口。
</span></span></span><span class="line"><span class="cl"><span class="s2">    如果模型已经有GRU状态端口，直接返回原模型。
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># 检查是否已有GRU状态端口</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">training_model</span><span class="o">.</span><span class="n">inputs</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">training_model</span><span class="o">.</span><span class="n">outputs</span><span class="p">)</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;  Model already has GRU state ports, skipping rebuild&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">training_model</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;  Rebuilding model with GRU state inputs/outputs...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 新的推理输入（带状态）</span>
</span></span><span class="line"><span class="cl">    <span class="n">features_in</span> <span class="o">=</span> <span class="n">Input</span><span class="p">(</span><span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">42</span><span class="p">),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;features&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_state_in</span> <span class="o">=</span> <span class="n">Input</span><span class="p">(</span><span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">24</span><span class="p">,),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;vad_gru_state&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">noise_state_in</span> <span class="o">=</span> <span class="n">Input</span><span class="p">(</span><span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">48</span><span class="p">,),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;noise_gru_state&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_state_in</span> <span class="o">=</span> <span class="n">Input</span><span class="p">(</span><span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">96</span><span class="p">,),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;denoise_gru_state&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 复制训练模型的层配置并加载权重</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># 1) input_dense</span>
</span></span><span class="line"><span class="cl">    <span class="n">input_dense_src</span> <span class="o">=</span> <span class="n">training_model</span><span class="o">.</span><span class="n">get_layer</span><span class="p">(</span><span class="s1">&#39;input_dense&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">input_dense</span> <span class="o">=</span> <span class="n">Dense</span><span class="p">(</span><span class="mi">24</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;tanh&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;input_dense_export&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">kernel_constraint</span><span class="o">=</span><span class="n">input_dense_src</span><span class="o">.</span><span class="n">kernel_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">bias_constraint</span><span class="o">=</span><span class="n">input_dense_src</span><span class="o">.</span><span class="n">bias_constraint</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">tmp_export</span> <span class="o">=</span> <span class="n">input_dense</span><span class="p">(</span><span class="n">features_in</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">input_dense</span><span class="o">.</span><span class="n">set_weights</span><span class="p">(</span><span class="n">input_dense_src</span><span class="o">.</span><span class="n">get_weights</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 2) vad_gru (return_sequences+return_state)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_gru_src</span> <span class="o">=</span> <span class="n">training_model</span><span class="o">.</span><span class="n">get_layer</span><span class="p">(</span><span class="s1">&#39;vad_gru&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_gru_exp</span> <span class="o">=</span> <span class="n">GRU</span><span class="p">(</span><span class="mi">24</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;tanh&#39;</span><span class="p">,</span> <span class="n">recurrent_activation</span><span class="o">=</span><span class="s1">&#39;sigmoid&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="n">return_sequences</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">return_state</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;vad_gru_export&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="n">kernel_regularizer</span><span class="o">=</span><span class="n">vad_gru_src</span><span class="o">.</span><span class="n">kernel_regularizer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="n">recurrent_regularizer</span><span class="o">=</span><span class="n">vad_gru_src</span><span class="o">.</span><span class="n">recurrent_regularizer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="n">kernel_constraint</span><span class="o">=</span><span class="n">vad_gru_src</span><span class="o">.</span><span class="n">kernel_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="n">recurrent_constraint</span><span class="o">=</span><span class="n">vad_gru_src</span><span class="o">.</span><span class="n">recurrent_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="n">bias_constraint</span><span class="o">=</span><span class="n">vad_gru_src</span><span class="o">.</span><span class="n">bias_constraint</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_seq</span><span class="p">,</span> <span class="n">vad_state_out</span> <span class="o">=</span> <span class="n">vad_gru_exp</span><span class="p">(</span><span class="n">tmp_export</span><span class="p">,</span> <span class="n">initial_state</span><span class="o">=</span><span class="n">vad_state_in</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_gru_exp</span><span class="o">.</span><span class="n">set_weights</span><span class="p">(</span><span class="n">vad_gru_src</span><span class="o">.</span><span class="n">get_weights</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 3) vad_output</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_output_src</span> <span class="o">=</span> <span class="n">training_model</span><span class="o">.</span><span class="n">get_layer</span><span class="p">(</span><span class="s1">&#39;vad_output&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_output_exp_layer</span> <span class="o">=</span> <span class="n">Dense</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;sigmoid&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;vad_output_export&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                 <span class="n">kernel_constraint</span><span class="o">=</span><span class="n">vad_output_src</span><span class="o">.</span><span class="n">kernel_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                 <span class="n">bias_constraint</span><span class="o">=</span><span class="n">vad_output_src</span><span class="o">.</span><span class="n">bias_constraint</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_output_exp</span> <span class="o">=</span> <span class="n">vad_output_exp_layer</span><span class="p">(</span><span class="n">vad_seq</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">vad_output_exp_layer</span><span class="o">.</span><span class="n">set_weights</span><span class="p">(</span><span class="n">vad_output_src</span><span class="o">.</span><span class="n">get_weights</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 4) noise_gru 输入：concat([tmp_export, vad_seq, features_in])</span>
</span></span><span class="line"><span class="cl">    <span class="n">noise_in</span> <span class="o">=</span> <span class="n">concatenate</span><span class="p">([</span><span class="n">tmp_export</span><span class="p">,</span> <span class="n">vad_seq</span><span class="p">,</span> <span class="n">features_in</span><span class="p">],</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;noise_concat_export&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">noise_gru_src</span> <span class="o">=</span> <span class="n">training_model</span><span class="o">.</span><span class="n">get_layer</span><span class="p">(</span><span class="s1">&#39;noise_gru&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">noise_gru_exp</span> <span class="o">=</span> <span class="n">GRU</span><span class="p">(</span><span class="mi">48</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;relu&#39;</span><span class="p">,</span> <span class="n">recurrent_activation</span><span class="o">=</span><span class="s1">&#39;sigmoid&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">return_sequences</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">return_state</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;noise_gru_export&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">kernel_regularizer</span><span class="o">=</span><span class="n">noise_gru_src</span><span class="o">.</span><span class="n">kernel_regularizer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">recurrent_regularizer</span><span class="o">=</span><span class="n">noise_gru_src</span><span class="o">.</span><span class="n">recurrent_regularizer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">kernel_constraint</span><span class="o">=</span><span class="n">noise_gru_src</span><span class="o">.</span><span class="n">kernel_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">recurrent_constraint</span><span class="o">=</span><span class="n">noise_gru_src</span><span class="o">.</span><span class="n">recurrent_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">bias_constraint</span><span class="o">=</span><span class="n">noise_gru_src</span><span class="o">.</span><span class="n">bias_constraint</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">noise_seq</span><span class="p">,</span> <span class="n">noise_state_out</span> <span class="o">=</span> <span class="n">noise_gru_exp</span><span class="p">(</span><span class="n">noise_in</span><span class="p">,</span> <span class="n">initial_state</span><span class="o">=</span><span class="n">noise_state_in</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">noise_gru_exp</span><span class="o">.</span><span class="n">set_weights</span><span class="p">(</span><span class="n">noise_gru_src</span><span class="o">.</span><span class="n">get_weights</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 5) denoise_gru 输入：concat([vad_seq, noise_seq, features_in])</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_in</span> <span class="o">=</span> <span class="n">concatenate</span><span class="p">([</span><span class="n">vad_seq</span><span class="p">,</span> <span class="n">noise_seq</span><span class="p">,</span> <span class="n">features_in</span><span class="p">],</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;denoise_concat_export&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_gru_src</span> <span class="o">=</span> <span class="n">training_model</span><span class="o">.</span><span class="n">get_layer</span><span class="p">(</span><span class="s1">&#39;denoise_gru&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_gru_exp</span> <span class="o">=</span> <span class="n">GRU</span><span class="p">(</span><span class="mi">96</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;tanh&#39;</span><span class="p">,</span> <span class="n">recurrent_activation</span><span class="o">=</span><span class="s1">&#39;sigmoid&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="n">return_sequences</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">return_state</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;denoise_gru_export&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="n">kernel_regularizer</span><span class="o">=</span><span class="n">denoise_gru_src</span><span class="o">.</span><span class="n">kernel_regularizer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="n">recurrent_regularizer</span><span class="o">=</span><span class="n">denoise_gru_src</span><span class="o">.</span><span class="n">recurrent_regularizer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="n">kernel_constraint</span><span class="o">=</span><span class="n">denoise_gru_src</span><span class="o">.</span><span class="n">kernel_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="n">recurrent_constraint</span><span class="o">=</span><span class="n">denoise_gru_src</span><span class="o">.</span><span class="n">recurrent_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="n">bias_constraint</span><span class="o">=</span><span class="n">denoise_gru_src</span><span class="o">.</span><span class="n">bias_constraint</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_seq</span><span class="p">,</span> <span class="n">denoise_state_out</span> <span class="o">=</span> <span class="n">denoise_gru_exp</span><span class="p">(</span><span class="n">denoise_in</span><span class="p">,</span> <span class="n">initial_state</span><span class="o">=</span><span class="n">denoise_state_in</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_gru_exp</span><span class="o">.</span><span class="n">set_weights</span><span class="p">(</span><span class="n">denoise_gru_src</span><span class="o">.</span><span class="n">get_weights</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 6) denoise_output</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_output_src</span> <span class="o">=</span> <span class="n">training_model</span><span class="o">.</span><span class="n">get_layer</span><span class="p">(</span><span class="s1">&#39;denoise_output&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_output_exp_layer</span> <span class="o">=</span> <span class="n">Dense</span><span class="p">(</span><span class="mi">22</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;sigmoid&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;denoise_output_export&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                     <span class="n">kernel_constraint</span><span class="o">=</span><span class="n">denoise_output_src</span><span class="o">.</span><span class="n">kernel_constraint</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                     <span class="n">bias_constraint</span><span class="o">=</span><span class="n">denoise_output_src</span><span class="o">.</span><span class="n">bias_constraint</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_output_exp</span> <span class="o">=</span> <span class="n">denoise_output_exp_layer</span><span class="p">(</span><span class="n">denoise_seq</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">denoise_output_exp_layer</span><span class="o">.</span><span class="n">set_weights</span><span class="p">(</span><span class="n">denoise_output_src</span><span class="o">.</span><span class="n">get_weights</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">export_model</span> <span class="o">=</span> <span class="n">Model</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">inputs</span><span class="o">=</span><span class="p">[</span><span class="n">features_in</span><span class="p">,</span> <span class="n">vad_state_in</span><span class="p">,</span> <span class="n">noise_state_in</span><span class="p">,</span> <span class="n">denoise_state_in</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">outputs</span><span class="o">=</span><span class="p">[</span><span class="n">denoise_output_exp</span><span class="p">,</span> <span class="n">vad_output_exp</span><span class="p">,</span> <span class="n">vad_state_out</span><span class="p">,</span> <span class="n">noise_state_out</span><span class="p">,</span> <span class="n">denoise_state_out</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">name</span><span class="o">=</span><span class="s1">&#39;rnnoise_export_with_states&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;  ✓ Model rebuilt successfully with GRU state ports&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">export_model</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">convert</span><span class="p">(</span><span class="n">hdf5_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">onnx_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">opset</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">13</span><span class="p">,</span> <span class="n">auto_rebuild</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">hdf5_path</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">raise</span> <span class="ne">FileNotFoundError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;HDF5 model not found: </span><span class="si">{</span><span class="n">hdf5_path</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Loading Keras model from: </span><span class="si">{</span><span class="n">hdf5_path</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Load with custom objects registered for deserialization</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span> <span class="o">=</span> <span class="n">keras</span><span class="o">.</span><span class="n">models</span><span class="o">.</span><span class="n">load_model</span><span class="p">(</span><span class="n">hdf5_path</span><span class="p">,</span> <span class="n">custom_objects</span><span class="o">=</span><span class="n">CUSTOM_OBJECTS</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># Auto-rebuild model with GRU states if needed</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">auto_rebuild</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">=== Auto-Rebuild Mode ===&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;  Checking if model needs GRU state ports...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">model</span> <span class="o">=</span> <span class="n">rebuild_model_with_states</span><span class="p">(</span><span class="n">model</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;  Model ready for conversion with GRU state ports</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Check if the model has GRU state inputs/outputs</span>
</span></span><span class="line"><span class="cl">    <span class="n">num_inputs</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">inputs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">num_outputs</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">outputs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Model has </span><span class="si">{</span><span class="n">num_inputs</span><span class="si">}</span><span class="s2"> input(s) and </span><span class="si">{</span><span class="n">num_outputs</span><span class="si">}</span><span class="s2"> output(s)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># Print input information</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">inp</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">inputs</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  Input </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">inp</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, shape: </span><span class="si">{</span><span class="n">inp</span><span class="o">.</span><span class="n">shape</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># Print output information</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">out</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">outputs</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  Output </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">out</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, shape: </span><span class="si">{</span><span class="n">out</span><span class="o">.</span><span class="n">shape</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># Check if this is a model with GRU states (4 inputs and 5 outputs)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">num_inputs</span> <span class="o">==</span> <span class="mi">4</span> <span class="ow">and</span> <span class="n">num_outputs</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Detected model with GRU state inputs/outputs&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Build input signature for model with efficient state management</span>
</span></span><span class="line"><span class="cl">        <span class="n">input_specs</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">inp</span> <span class="ow">in</span> <span class="n">model</span><span class="o">.</span><span class="n">inputs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">inp_name</span> <span class="o">=</span> <span class="n">inp</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="n">inp_shape</span> <span class="o">=</span> <span class="n">inp</span><span class="o">.</span><span class="n">shape</span><span class="o">.</span><span class="n">as_list</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="c1"># Handle different input shapes</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">inp_shape</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>  <span class="c1"># features: (None, None, 42)</span>
</span></span><span class="line"><span class="cl">                <span class="n">spec</span> <span class="o">=</span> <span class="n">tf</span><span class="o">.</span><span class="n">TensorSpec</span><span class="p">([</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="n">inp_shape</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="n">tf</span><span class="o">.</span><span class="n">float32</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">inp_name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">inp_shape</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>  <span class="c1"># GRU states: (None, hidden_size)</span>
</span></span><span class="line"><span class="cl">                <span class="n">spec</span> <span class="o">=</span> <span class="n">tf</span><span class="o">.</span><span class="n">TensorSpec</span><span class="p">([</span><span class="kc">None</span><span class="p">,</span> <span class="n">inp_shape</span><span class="p">[</span><span class="mi">1</span><span class="p">]],</span> <span class="n">tf</span><span class="o">.</span><span class="n">float32</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">inp_name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="c1"># Fallback: use dynamic shape</span>
</span></span><span class="line"><span class="cl">                <span class="n">spec</span> <span class="o">=</span> <span class="n">tf</span><span class="o">.</span><span class="n">TensorSpec</span><span class="p">([</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">inp_shape</span><span class="p">),</span> <span class="n">tf</span><span class="o">.</span><span class="n">float32</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">inp_name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="n">input_specs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">spec</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Converting to ONNX (opset </span><span class="si">{</span><span class="n">opset</span><span class="si">}</span><span class="s2">) with GRU state inputs/outputs...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Convert with all input signatures</span>
</span></span><span class="line"><span class="cl">        <span class="n">tf2onnx</span><span class="o">.</span><span class="n">convert</span><span class="o">.</span><span class="n">from_keras</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">input_signature</span><span class="o">=</span><span class="n">input_specs</span><span class="p">,</span> <span class="n">output_path</span><span class="o">=</span><span class="n">onnx_path</span><span class="p">,</span> <span class="n">opset</span><span class="o">=</span><span class="n">opset</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">elif</span> <span class="n">num_inputs</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Detected standard model without GRU state ports&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Use a dynamic input signature (None, None, 42) to preserve time dimension flexibility</span>
</span></span><span class="line"><span class="cl">        <span class="n">input_name</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">inputs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="n">spec</span> <span class="o">=</span> <span class="p">(</span><span class="n">tf</span><span class="o">.</span><span class="n">TensorSpec</span><span class="p">([</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="mi">42</span><span class="p">],</span> <span class="n">tf</span><span class="o">.</span><span class="n">float32</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">input_name</span><span class="p">),)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Converting to ONNX (opset </span><span class="si">{</span><span class="n">opset</span><span class="si">}</span><span class="s2">)...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Convert directly from the Keras model</span>
</span></span><span class="line"><span class="cl">        <span class="n">tf2onnx</span><span class="o">.</span><span class="n">convert</span><span class="o">.</span><span class="n">from_keras</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">input_signature</span><span class="o">=</span><span class="n">spec</span><span class="p">,</span> <span class="n">output_path</span><span class="o">=</span><span class="n">onnx_path</span><span class="p">,</span> <span class="n">opset</span><span class="o">=</span><span class="n">opset</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Generic conversion for models with multiple inputs but unknown structure</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Converting to ONNX (opset </span><span class="si">{</span><span class="n">opset</span><span class="si">}</span><span class="s2">) with </span><span class="si">{</span><span class="n">num_inputs</span><span class="si">}</span><span class="s2"> inputs...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">input_specs</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">inp</span> <span class="ow">in</span> <span class="n">model</span><span class="o">.</span><span class="n">inputs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">inp_name</span> <span class="o">=</span> <span class="n">inp</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="n">inp_shape</span> <span class="o">=</span> <span class="n">inp</span><span class="o">.</span><span class="n">shape</span><span class="o">.</span><span class="n">as_list</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># Use dynamic shapes for flexibility</span>
</span></span><span class="line"><span class="cl">            <span class="n">spec</span> <span class="o">=</span> <span class="n">tf</span><span class="o">.</span><span class="n">TensorSpec</span><span class="p">([</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">inp_shape</span><span class="p">),</span> <span class="n">tf</span><span class="o">.</span><span class="n">float32</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">inp_name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">input_specs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">spec</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">tf2onnx</span><span class="o">.</span><span class="n">convert</span><span class="o">.</span><span class="n">from_keras</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">input_signature</span><span class="o">=</span><span class="n">input_specs</span><span class="p">,</span> <span class="n">output_path</span><span class="o">=</span><span class="n">onnx_path</span><span class="p">,</span> <span class="n">opset</span><span class="o">=</span><span class="n">opset</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Saved ONNX model to: </span><span class="si">{</span><span class="n">onnx_path</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s1">&#39;Convert Keras HDF5 model to ONNX for RNNoise.&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--input&#39;</span><span class="p">,</span> <span class="s1">&#39;-i&#39;</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">&#39;Path to Keras HDF5 model file&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--output&#39;</span><span class="p">,</span> <span class="s1">&#39;-o&#39;</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">&#39;Path to output ONNX file&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--opset&#39;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mi">13</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">&#39;ONNX opset version (default: 13)&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--auto-rebuild&#39;</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s1">&#39;store_true&#39;</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                        <span class="n">help</span><span class="o">=</span><span class="s1">&#39;Automatically rebuild model with GRU state ports if missing&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">input_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">input</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">output_path</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">output</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">output_path</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">base</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">input_path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">output_path</span> <span class="o">=</span> <span class="n">base</span> <span class="o">+</span> <span class="s1">&#39;.onnx&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">output_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">output_path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">output_path</span><span class="p">),</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">convert</span><span class="p">(</span><span class="n">input_path</span><span class="p">,</span> <span class="n">output_path</span><span class="p">,</span> <span class="n">opset</span><span class="o">=</span><span class="n">args</span><span class="o">.</span><span class="n">opset</span><span class="p">,</span> <span class="n">auto_rebuild</span><span class="o">=</span><span class="n">args</span><span class="o">.</span><span class="n">auto_rebuild</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h4 id="322-推理时对隐状态进行管理">3.2.2 推理时对隐状态进行管理</h4>
<p>前面导出onnx模型时，已经为每个GRU节点导出了隐状态的输入和输出端口，因此在每一次帧的时候，只需要将上一次推理保存的隐状态信息输入到对应的隐状态输入端口，同时在推理后对GRU节点的隐状态输出端口进行保存，就可以实现流式推理GRU保留历史信息了。</p>
<p>以下是部分核心函数实现，只需要将其嵌入到原rnnoise降噪代码中就可以实现ort推理了。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span><span class="lnt">150
</span><span class="lnt">151
</span><span class="lnt">152
</span><span class="lnt">153
</span><span class="lnt">154
</span><span class="lnt">155
</span><span class="lnt">156
</span><span class="lnt">157
</span><span class="lnt">158
</span><span class="lnt">159
</span><span class="lnt">160
</span><span class="lnt">161
</span><span class="lnt">162
</span><span class="lnt">163
</span><span class="lnt">164
</span><span class="lnt">165
</span><span class="lnt">166
</span><span class="lnt">167
</span><span class="lnt">168
</span><span class="lnt">169
</span><span class="lnt">170
</span><span class="lnt">171
</span><span class="lnt">172
</span><span class="lnt">173
</span><span class="lnt">174
</span><span class="lnt">175
</span><span class="lnt">176
</span><span class="lnt">177
</span><span class="lnt">178
</span><span class="lnt">179
</span><span class="lnt">180
</span><span class="lnt">181
</span><span class="lnt">182
</span><span class="lnt">183
</span><span class="lnt">184
</span><span class="lnt">185
</span><span class="lnt">186
</span><span class="lnt">187
</span><span class="lnt">188
</span><span class="lnt">189
</span><span class="lnt">190
</span><span class="lnt">191
</span><span class="lnt">192
</span><span class="lnt">193
</span><span class="lnt">194
</span><span class="lnt">195
</span><span class="lnt">196
</span><span class="lnt">197
</span><span class="lnt">198
</span><span class="lnt">199
</span><span class="lnt">200
</span><span class="lnt">201
</span><span class="lnt">202
</span><span class="lnt">203
</span><span class="lnt">204
</span><span class="lnt">205
</span><span class="lnt">206
</span><span class="lnt">207
</span><span class="lnt">208
</span><span class="lnt">209
</span><span class="lnt">210
</span><span class="lnt">211
</span><span class="lnt">212
</span><span class="lnt">213
</span><span class="lnt">214
</span><span class="lnt">215
</span><span class="lnt">216
</span><span class="lnt">217
</span><span class="lnt">218
</span><span class="lnt">219
</span><span class="lnt">220
</span><span class="lnt">221
</span><span class="lnt">222
</span><span class="lnt">223
</span><span class="lnt">224
</span><span class="lnt">225
</span><span class="lnt">226
</span><span class="lnt">227
</span><span class="lnt">228
</span><span class="lnt">229
</span><span class="lnt">230
</span><span class="lnt">231
</span><span class="lnt">232
</span><span class="lnt">233
</span><span class="lnt">234
</span><span class="lnt">235
</span><span class="lnt">236
</span><span class="lnt">237
</span><span class="lnt">238
</span><span class="lnt">239
</span><span class="lnt">240
</span><span class="lnt">241
</span><span class="lnt">242
</span><span class="lnt">243
</span><span class="lnt">244
</span><span class="lnt">245
</span><span class="lnt">246
</span><span class="lnt">247
</span><span class="lnt">248
</span><span class="lnt">249
</span><span class="lnt">250
</span><span class="lnt">251
</span><span class="lnt">252
</span><span class="lnt">253
</span><span class="lnt">254
</span><span class="lnt">255
</span><span class="lnt">256
</span><span class="lnt">257
</span><span class="lnt">258
</span><span class="lnt">259
</span><span class="lnt">260
</span><span class="lnt">261
</span><span class="lnt">262
</span><span class="lnt">263
</span><span class="lnt">264
</span><span class="lnt">265
</span><span class="lnt">266
</span><span class="lnt">267
</span><span class="lnt">268
</span><span class="lnt">269
</span><span class="lnt">270
</span><span class="lnt">271
</span><span class="lnt">272
</span><span class="lnt">273
</span><span class="lnt">274
</span><span class="lnt">275
</span><span class="lnt">276
</span><span class="lnt">277
</span><span class="lnt">278
</span><span class="lnt">279
</span><span class="lnt">280
</span><span class="lnt">281
</span><span class="lnt">282
</span><span class="lnt">283
</span><span class="lnt">284
</span><span class="lnt">285
</span><span class="lnt">286
</span><span class="lnt">287
</span><span class="lnt">288
</span><span class="lnt">289
</span><span class="lnt">290
</span><span class="lnt">291
</span><span class="lnt">292
</span><span class="lnt">293
</span><span class="lnt">294
</span><span class="lnt">295
</span><span class="lnt">296
</span><span class="lnt">297
</span><span class="lnt">298
</span><span class="lnt">299
</span><span class="lnt">300
</span><span class="lnt">301
</span><span class="lnt">302
</span><span class="lnt">303
</span><span class="lnt">304
</span><span class="lnt">305
</span><span class="lnt">306
</span><span class="lnt">307
</span><span class="lnt">308
</span><span class="lnt">309
</span><span class="lnt">310
</span><span class="lnt">311
</span><span class="lnt">312
</span><span class="lnt">313
</span><span class="lnt">314
</span><span class="lnt">315
</span><span class="lnt">316
</span><span class="lnt">317
</span><span class="lnt">318
</span><span class="lnt">319
</span><span class="lnt">320
</span><span class="lnt">321
</span><span class="lnt">322
</span><span class="lnt">323
</span><span class="lnt">324
</span><span class="lnt">325
</span><span class="lnt">326
</span><span class="lnt">327
</span><span class="lnt">328
</span><span class="lnt">329
</span><span class="lnt">330
</span><span class="lnt">331
</span><span class="lnt">332
</span><span class="lnt">333
</span><span class="lnt">334
</span><span class="lnt">335
</span><span class="lnt">336
</span><span class="lnt">337
</span><span class="lnt">338
</span><span class="lnt">339
</span><span class="lnt">340
</span><span class="lnt">341
</span><span class="lnt">342
</span><span class="lnt">343
</span><span class="lnt">344
</span><span class="lnt">345
</span><span class="lnt">346
</span><span class="lnt">347
</span><span class="lnt">348
</span><span class="lnt">349
</span><span class="lnt">350
</span><span class="lnt">351
</span><span class="lnt">352
</span><span class="lnt">353
</span><span class="lnt">354
</span><span class="lnt">355
</span><span class="lnt">356
</span><span class="lnt">357
</span><span class="lnt">358
</span><span class="lnt">359
</span><span class="lnt">360
</span><span class="lnt">361
</span><span class="lnt">362
</span><span class="lnt">363
</span><span class="lnt">364
</span><span class="lnt">365
</span><span class="lnt">366
</span><span class="lnt">367
</span><span class="lnt">368
</span><span class="lnt">369
</span><span class="lnt">370
</span><span class="lnt">371
</span><span class="lnt">372
</span><span class="lnt">373
</span><span class="lnt">374
</span><span class="lnt">375
</span><span class="lnt">376
</span><span class="lnt">377
</span><span class="lnt">378
</span><span class="lnt">379
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// Initialize ONNX model
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">initialize_onnx_model</span><span class="p">(</span><span class="n">RNNoiseContext</span><span class="o">*</span> <span class="n">ctx</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">model_path</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Get ONNX Runtime API
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="n">OrtApiBase</span><span class="o">*</span> <span class="n">api_base</span> <span class="o">=</span> <span class="nf">OrtGetApiBase</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">api_base</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting ONNX Runtime API base</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span> <span class="o">=</span> <span class="n">api_base</span><span class="o">-&gt;</span><span class="nf">GetApi</span><span class="p">(</span><span class="n">ORT_API_VERSION</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting ONNX Runtime API</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Initialize ONNX Runtime environment
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">OrtStatus</span><span class="o">*</span> <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">CreateEnv</span><span class="p">(</span><span class="n">ORT_LOGGING_LEVEL_WARNING</span><span class="p">,</span> <span class="s">&#34;RNNoiseONNX&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">env</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error creating ONNX Runtime environment</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Create session options
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">CreateSessionOptions</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session_options</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error creating session options</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Set session options
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SetIntraOpNumThreads</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session_options</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error setting intra-op threads</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SetSessionGraphOptimizationLevel</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session_options</span><span class="p">,</span> <span class="n">ORT_ENABLE_EXTENDED</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error setting optimization level</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Create session
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">CreateSession</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">env</span><span class="p">,</span> <span class="n">model_path</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session_options</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error creating ONNX session</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Get allocator
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">GetAllocatorWithDefaultOptions</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting allocator</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Get input/output names
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">size_t</span> <span class="n">num_input_nodes</span><span class="p">,</span> <span class="n">num_output_nodes</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetInputCount</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">num_input_nodes</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting input count</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetOutputCount</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">num_output_nodes</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting output count</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;ONNX Model Info:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Input nodes: %zu</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">num_input_nodes</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Output nodes: %zu</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">num_output_nodes</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Detect model type: 4 inputs + 5 outputs = model with GRU states
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">has_gru_states</span> <span class="o">=</span> <span class="p">(</span><span class="n">num_input_nodes</span> <span class="o">==</span> <span class="mi">4</span> <span class="o">&amp;&amp;</span> <span class="n">num_output_nodes</span> <span class="o">==</span> <span class="mi">5</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">has_gru_states</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Model type: WITH GRU state inputs/outputs</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1">// Get all input names
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetInputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting features input name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetInputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_vad_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting VAD state input name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetInputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_noise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting noise state input name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetInputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_denoise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting denoise state input name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1">// Get all output names
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetOutputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_denoise</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting denoise output name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetOutputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_vad</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting VAD output name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetOutputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_vad_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting VAD state output name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetOutputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_noise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting noise state output name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetOutputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_denoise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting denoise state output name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Inputs:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [0] %s (features)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [1] %s (VAD GRU state)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_vad_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [2] %s (noise GRU state)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_noise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [3] %s (denoise GRU state)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_denoise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Outputs:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [0] %s (denoise)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_denoise</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [1] %s (VAD)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_vad</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [2] %s (VAD GRU state)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_vad_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [3] %s (noise GRU state)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_noise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;    [4] %s (denoise GRU state)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_denoise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Model type: Standard (without GRU state ports)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1">// Get input name (standard model)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetInputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting input name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1">// Get output names (standard model)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetOutputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_denoise</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting denoise output name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">SessionGetOutputName</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">allocator</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_vad</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting VAD output name</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Input: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Output denoise: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_denoise</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;  Output VAD: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_vad</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Allocate buffers
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_buffer</span> <span class="o">=</span> <span class="p">(</span><span class="kt">float</span><span class="o">*</span><span class="p">)</span><span class="nf">malloc</span><span class="p">(</span><span class="n">FRAME_SIZE</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_buffer</span> <span class="o">=</span> <span class="p">(</span><span class="kt">float</span><span class="o">*</span><span class="p">)</span><span class="nf">malloc</span><span class="p">(</span><span class="n">FRAME_SIZE</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_buffer</span> <span class="o">||</span> <span class="o">!</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_buffer</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error: Memory allocation failed</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Initialize RNNoise state for feature extraction
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">denoise_state</span> <span class="o">=</span> <span class="nf">rnnoise_create</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">denoise_state</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error: Failed to create RNNoise state</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="nf">rnnoise_init</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">denoise_state</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Initialize biquad filter memory
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">mem_hp_x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mf">0.0f</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">mem_hp_x</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mf">0.0f</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Initialize processing buffers
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">X</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">X</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">P</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">P</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">Ex</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">Ex</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">Ep</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">Ep</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">Exp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">Exp</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">lastg</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">lastg</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">synthesis_mem</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">synthesis_mem</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Initialize frame count
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">frame_count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Initialize GRU states if model supports it
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nf">initialize_gru_states</span><span class="p">(</span><span class="n">ctx</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;ONNX model loaded successfully: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">model_path</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Initialize GRU states
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">initialize_gru_states</span><span class="p">(</span><span class="n">RNNoiseContext</span><span class="o">*</span> <span class="n">ctx</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">vad_gru_state</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">vad_gru_state</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">noise_gru_state</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">noise_gru_state</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memset</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">denoise_gru_state</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">denoise_gru_state</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">gru_states_initialized</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// ONNX inference with external state management
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">onnx_inference_with_states</span><span class="p">(</span><span class="n">RNNoiseContext</span><span class="o">*</span> <span class="n">ctx</span><span class="p">,</span> <span class="k">const</span> <span class="kt">float</span><span class="o">*</span> <span class="n">features</span><span class="p">,</span> <span class="kt">float</span><span class="o">*</span> <span class="n">gains</span><span class="p">,</span> <span class="kt">float</span><span class="o">*</span> <span class="n">vad</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Prepare separate input tensors for features and GRU states
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">float</span> <span class="n">features_data</span><span class="p">[</span><span class="mi">42</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span> <span class="n">vad_state_data</span><span class="p">[</span><span class="mi">24</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span> <span class="n">noise_state_data</span><span class="p">[</span><span class="mi">48</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span> <span class="n">denoise_state_data</span><span class="p">[</span><span class="mi">96</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Copy features
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nf">memcpy</span><span class="p">(</span><span class="n">features_data</span><span class="p">,</span> <span class="n">features</span><span class="p">,</span> <span class="mi">42</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Copy GRU states (use saved states for next frame)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nf">memcpy</span><span class="p">(</span><span class="n">vad_state_data</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">vad_gru_state</span><span class="p">,</span> <span class="mi">24</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memcpy</span><span class="p">(</span><span class="n">noise_state_data</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">noise_gru_state</span><span class="p">,</span> <span class="mi">48</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memcpy</span><span class="p">(</span><span class="n">denoise_state_data</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">denoise_gru_state</span><span class="p">,</span> <span class="mi">96</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Create input tensors
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="kt">int64_t</span> <span class="n">features_shape</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">42</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">int64_t</span> <span class="n">vad_state_shape</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">24</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">int64_t</span> <span class="n">noise_state_shape</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">48</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">int64_t</span> <span class="n">denoise_state_shape</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">96</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">OrtMemoryInfo</span><span class="o">*</span> <span class="n">memory_info</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">OrtStatus</span><span class="o">*</span> <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">CreateCpuMemoryInfo</span><span class="p">(</span><span class="n">OrtArenaAllocator</span><span class="p">,</span> <span class="n">OrtMemTypeDefault</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">memory_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error creating memory info</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Create input tensors
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">OrtValue</span><span class="o">*</span> <span class="n">features_tensor</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">OrtValue</span><span class="o">*</span> <span class="n">vad_state_tensor</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">OrtValue</span><span class="o">*</span> <span class="n">noise_state_tensor</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">OrtValue</span><span class="o">*</span> <span class="n">denoise_state_tensor</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">CreateTensorWithDataAsOrtValue</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">memory_info</span><span class="p">,</span> <span class="n">features_data</span><span class="p">,</span> <span class="mi">42</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">features_shape</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">features_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error creating features tensor</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseMemoryInfo</span><span class="p">(</span><span class="n">memory_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">CreateTensorWithDataAsOrtValue</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">memory_info</span><span class="p">,</span> <span class="n">vad_state_data</span><span class="p">,</span> <span class="mi">24</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">vad_state_shape</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">vad_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error creating VAD state tensor</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">features_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseMemoryInfo</span><span class="p">(</span><span class="n">memory_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">CreateTensorWithDataAsOrtValue</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">memory_info</span><span class="p">,</span> <span class="n">noise_state_data</span><span class="p">,</span> <span class="mi">48</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">noise_state_shape</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">noise_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error creating noise state tensor</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">features_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">vad_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseMemoryInfo</span><span class="p">(</span><span class="n">memory_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">CreateTensorWithDataAsOrtValue</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">memory_info</span><span class="p">,</span> <span class="n">denoise_state_data</span><span class="p">,</span> <span class="mi">96</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">denoise_state_shape</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">denoise_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error creating denoise state tensor</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">features_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">vad_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">noise_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseMemoryInfo</span><span class="p">(</span><span class="n">memory_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Prepare input names and tensors
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">input_names</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_vad_state</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                                 <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_noise_state</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">input_name_denoise_state</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">OrtValue</span><span class="o">*</span> <span class="n">input_tensors</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="n">features_tensor</span><span class="p">,</span> <span class="n">vad_state_tensor</span><span class="p">,</span> <span class="n">noise_state_tensor</span><span class="p">,</span> <span class="n">denoise_state_tensor</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Prepare output names
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">output_names</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_denoise</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_vad</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                                  <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_vad_state</span><span class="p">,</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_noise_state</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                                  <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">output_name_denoise_state</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">OrtValue</span><span class="o">*</span> <span class="n">output_tensors</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Run inference
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">Run</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">input_names</span><span class="p">,</span> <span class="p">(</span><span class="k">const</span> <span class="n">OrtValue</span><span class="o">*</span> <span class="k">const</span><span class="o">*</span><span class="p">)</span><span class="n">input_tensors</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                   <span class="n">output_names</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">output_tensors</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error running inference</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">features_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">vad_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">noise_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">denoise_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseMemoryInfo</span><span class="p">(</span><span class="n">memory_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Get output data
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">float</span><span class="o">*</span> <span class="n">denoise_output</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span><span class="o">*</span> <span class="n">vad_output</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span><span class="o">*</span> <span class="n">updated_vad_state</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span><span class="o">*</span> <span class="n">updated_noise_state</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">float</span><span class="o">*</span> <span class="n">updated_denoise_state</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">GetTensorMutableData</span><span class="p">(</span><span class="n">output_tensors</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">(</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">denoise_output</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting denoise output data</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">goto</span> <span class="n">cleanup</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">GetTensorMutableData</span><span class="p">(</span><span class="n">output_tensors</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">vad_output</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting VAD output data</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">goto</span> <span class="n">cleanup</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">GetTensorMutableData</span><span class="p">(</span><span class="n">output_tensors</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="p">(</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">updated_vad_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting updated VAD state data</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">goto</span> <span class="n">cleanup</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">GetTensorMutableData</span><span class="p">(</span><span class="n">output_tensors</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="p">(</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">updated_noise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting updated noise state data</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">goto</span> <span class="n">cleanup</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">GetTensorMutableData</span><span class="p">(</span><span class="n">output_tensors</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="p">(</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">updated_denoise_state</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;Error getting updated denoise state data</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">goto</span> <span class="n">cleanup</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Store results
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nf">memcpy</span><span class="p">(</span><span class="n">gains</span><span class="p">,</span> <span class="n">denoise_output</span><span class="p">,</span> <span class="n">NB_BANDS</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="o">*</span><span class="n">vad</span> <span class="o">=</span> <span class="n">vad_output</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1">// Update GRU states with the outputs from the model (for next frame)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nf">memcpy</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">vad_gru_state</span><span class="p">,</span> <span class="n">updated_vad_state</span><span class="p">,</span> <span class="mi">24</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memcpy</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">noise_gru_state</span><span class="p">,</span> <span class="n">updated_noise_state</span><span class="p">,</span> <span class="mi">48</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">memcpy</span><span class="p">(</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">denoise_gru_state</span><span class="p">,</span> <span class="n">updated_denoise_state</span><span class="p">,</span> <span class="mi">96</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">gru_states_initialized</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="nl">cleanup</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Cleanup
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">features_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">vad_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">noise_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">denoise_state_tensor</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">output_tensors</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseValue</span><span class="p">(</span><span class="n">output_tensors</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">api</span><span class="o">-&gt;</span><span class="nf">ReleaseMemoryInfo</span><span class="p">(</span><span class="n">memory_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h3 id="33-推理性能对比">3.3 推理性能对比</h3>
<p>可以看到在不需要自己手搓各个算子的C实现，借助ORT就可以实现接近5倍的性能提升，这投入回报比可是不要太高了。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">=== Overall Inference Time Statistics ===
</span></span><span class="line"><span class="cl">Total frames processed: 2048
</span></span><span class="line"><span class="cl">Frames with inference: 2047
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ONNX Inference:
</span></span><span class="line"><span class="cl">  Total time: 73.568 ms
</span></span><span class="line"><span class="cl">  Average per frame: 0.036 ms
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">C Inference:
</span></span><span class="line"><span class="cl">  Total time: 349.820 ms
</span></span><span class="line"><span class="cl">  Average per frame: 0.171 ms
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Comparison:
</span></span><span class="line"><span class="cl">  ONNX / C ratio: 0.21x
</span></span><span class="line"><span class="cl">  Speedup: 4.76x (ONNX faster)
</span></span><span class="line"><span class="cl">==========================================</span></span></code></pre></td></tr></table>
</div>
</div>
<h2 id="四总结">四、总结</h2>
<p>ORT作为跨平台的推理引擎，在语音降噪模型部署中具有显著优势。正确使用ORT需要：</p>
<ol>
<li><strong>理解基本概念</strong>：掌握InferenceSession、Execution Provider等核心概念</li>
<li><strong>遵循推理流程</strong>：按照标准的加载、准备、执行、获取结果流程</li>
<li><strong>管理隐状态</strong>：对于时序模型，必须正确管理隐状态的传递和更新</li>
<li><strong>性能优化</strong>：根据场景选择合适的优化选项和执行提供者</li>
</ol>
<p>对于实时语音降噪场景，隐状态管理是关键，需要仔细设计状态传递逻辑，确保模型能够正确利用历史信息。</p>
<p>通过合理使用ORT，可以充分发挥深度学习语音降噪模型的性能，实现高效、稳定的实时推理。</p>
<p>另外，ORT还有很多高级特性，大家可以自己摸索尝试下。</p>
<img src="/images/To-Be-Continued.jpeg"/>]]></content:encoded>
    </item>
    <item>
      <title>语音增强算法评估指南</title>
      <link>https://lyapple2008.github.io/posts/202508/2025-08-11-%E9%9F%B3%E9%A2%91%E7%AE%97%E6%B3%95%E8%AF%84%E4%BC%B0/</link>
      <pubDate>Mon, 11 Aug 2025 22:27:28 +0800</pubDate>
      <guid>https://lyapple2008.github.io/posts/202508/2025-08-11-%E9%9F%B3%E9%A2%91%E7%AE%97%E6%B3%95%E8%AF%84%E4%BC%B0/</guid>
      <description>&lt;h1 id=&#34;语音增强算法评估指南&#34;&gt;语音增强算法评估指南&lt;/h1&gt;
&lt;p&gt;如今语音增强算法已成为智能设备、视频会议和助听器等应用的核心，它能从嘈杂环境中“拯救”清晰的语音信号，但如何判断一个算法的好坏？这就是评估的意义所在。今天，我们来聊聊语音增强算法的评估体系，通过一个国际挑战赛作为切入点，带你一步步了解关键指标和计算方法。无论你是初学者还是从业者，这篇文章都能帮你理清思路。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="语音增强算法评估指南">语音增强算法评估指南</h1>
<p>如今语音增强算法已成为智能设备、视频会议和助听器等应用的核心，它能从嘈杂环境中“拯救”清晰的语音信号，但如何判断一个算法的好坏？这就是评估的意义所在。今天，我们来聊聊语音增强算法的评估体系，通过一个国际挑战赛作为切入点，带你一步步了解关键指标和计算方法。无论你是初学者还是从业者，这篇文章都能帮你理清思路。</p>
<h2 id="前言为什么需要评估语音增强算法">前言：为什么需要评估语音增强算法？</h2>
<p>想象一下，你开发了一个语音增强模型，自认为它能完美去除背景噪音。但在实际应用中，用户反馈“声音听起来怪怪的”或“某些噪音下完全失效”。这就是为什么评估至关重要：它提供了一个客观、量化的标准，帮助开发者识别算法的优缺点、优化性能，并与其他方法进行公平比较。</p>
<p>评估的作用主要体现在三个方面：</p>
<ul>
<li><strong>指导开发</strong>：通过指标反馈，迭代模型设计，避免主观偏见。</li>
<li><strong>基准比较</strong>：在竞赛或论文中，用统一标准衡量不同算法的进步。</li>
<li><strong>实际部署</strong>：确保算法在真实场景（如移动端或低信噪比环境）下的鲁棒性和通用性。</li>
</ul>
<p>没有评估，算法开发就像盲人摸象；有了评估，它就成了科学工程。接下来，我们以NeurIPS 2024竞赛轨道下的URGENT 2024挑战为例，深入探讨评估体系。这个挑战聚焦于构建通用语音增强模型，强调在不同噪声、采样率和麦克风配置下的表现。</p>
<h2 id="urgent-2024挑战评估体系的典范">URGENT 2024挑战：评估体系的典范</h2>
<p><a href="https://urgent-challenge.github.io/urgent2024/">URGENT 2024（Universality, Robustness, and Generalizability for EnhancemeNT）</a>挑战旨在解决传统语音增强研究的痛点：许多算法只针对特定条件优化，缺乏跨场景泛化能力。挑战要求参赛者使用统一的公共数据集训练单一模型，处理各种失真（如噪声、混响），并支持不同输入格式（如单/多通道、不同采样率）。</p>
<p>这个挑战的亮点在于其全面评估框架，包括非侵入式（无参考信号）和侵入式（需参考信号）指标，以及下游任务相关指标（如词错误率WER）。它还引入主观MOS（Mean Opinion Score）评分作为最终盲测环节的补充。挑战提供ESPnet工具包的基线模型，鼓励数据增强，但严格限制训练数据来源，确保公平性。</p>
<p>通过这个挑战，我们可以看到评估不仅是“打分”，而是推动行业向真实场景迈进的基准。接下来，重点介绍挑战中使用的核心客观指标：PESQ、ESTOI、SDR、MCD、LSD、DNSMOS和NISQA。</p>
<h2 id="评估指标详解每个指标都在测什么">评估指标详解：每个指标都在测什么？</h2>
<p>语音增强评估指标大致分为侵入式（需要干净参考信号）和非侵入式（无需参考，模拟真实场景）。URGENT 2024挑战选用这些指标来全面考察算法的语音质量、可懂度和保真度。下面逐一解释：</p>
<ul>
<li>
<p><strong>PESQ (Perceptual Evaluation of Speech Quality)</strong>：这是一个侵入式指标，通过比较增强后的语音与参考干净信号，评估感知质量。它关注失真和噪声对人类听觉的影响，得分范围通常为-0.5到4.5（越高越好）。在语音增强中，PESQ常用于客观测试算法的整体质量，尤其适合电话或VoIP场景。</p>
</li>
<li>
<p><strong>ESTOI (Extended Short-Time Objective Intelligibility)</strong>：侵入式指标，专注于评估增强语音的可懂度。它分析短时段信号，预测听者在噪声下的理解能力，得分从0到1（越高表示更易懂）。这个指标特别适用于低信噪比环境，帮助算法优化对人类认知的友好度。</p>
</li>
<li>
<p><strong>SDR (Signal-to-Distortion Ratio)</strong>：侵入式指标，计算期望信号能量与失真（包括噪声和伪影）能量的比率，通常以dB为单位（越高越好）。它评估增强信号的整体保真度，在多通道或复杂噪声场景中非常实用。</p>
</li>
<li>
<p><strong>MCD (Mel-Cepstral Distortion)</strong>：侵入式指标，量化增强信号与参考信号在梅尔倒谱系数上的差异（越低越好）。它聚焦谱失真，提供对感知质量的洞察，常用于评估算法对语音频谱的保留能力。</p>
</li>
<li>
<p><strong>LSD (Log-Spectral Distance)</strong>：侵入式指标，测量增强和参考信号功率谱的对数差异（越低越好）。它评估谱准确性，帮助理解算法如何保留原始语音特征，适用于频域分析。</p>
</li>
<li>
<p><strong>DNSMOS (Deep Noise Suppression Mean Opinion Score)</strong>：非侵入式指标，无需参考信号，使用深度学习模型预测语音质量（模拟人类评分，范围1-5）。它基于人类评级训练，适用于真实场景评估，尤其当干净参考不可用时。</p>
</li>
<li>
<p><strong>NISQA (Non-Intrusive Speech Quality Assessment)</strong>：同样是非侵入式指标，使用机器学习预测感知质量，无需参考。它评估整体语音质量，在参考信号缺失的实际部署中大放异彩。</p>
</li>
</ul>
<p>这些指标组合使用，能从质量、可懂度和失真等多维度评估算法。URGENT挑战强调，非侵入式指标如DNSMOS和NISQA更贴近现实，因为真实环境中往往没有干净参考。</p>
<h2 id="评测数据集从哪里获取如何使用">评测数据集：从哪里获取，如何使用？</h2>
<p>要实际计算这些指标，需要可靠的数据集。URGENT 2024挑战通过其GitHub仓库提供官方评测数据集，托管在Hugging Face上，便于下载和使用。</p>
<ul>
<li><strong>官方评测数据集</strong>：包括验证集、非盲测集和盲测集，地址：https://huggingface.co/datasets/urgent-challenge/urgent2024_official。这些数据集包含各种失真条件下的语音样本，适合测试算法的通用性。</li>
<li><strong>MOS数据集</strong>：额外提供带人类标注MOS分数的语音质量评估数据集，地址：https://huggingface.co/datasets/urgent-challenge/urgent2024_mos。用于主观指标验证。</li>
</ul>
<p>访问方式简单：在Hugging Face平台搜索并下载，或使用Python的datasets库加载。数据集设计覆盖不同噪声、混响和麦克风配置，确保评估的全面性。</p>
<blockquote>
<p>可以参考下面的代码将hugging face中的validataion数据集以wav形式保存在本地，方便后续不同算法进行处理后，对处理结果进行评估。</p>
</blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datasets</span> <span class="kn">import</span> <span class="n">load_dataset</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">soundfile</span> <span class="k">as</span> <span class="nn">sf</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 参数 =====</span>
</span></span><span class="line"><span class="cl"><span class="n">DATASET_NAME</span> <span class="o">=</span> <span class="s2">&#34;urgent-challenge/urgent2024_official&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">SPLIT</span> <span class="o">=</span> <span class="s2">&#34;validation&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">SAVE_DIR</span> <span class="o">=</span> <span class="s2">&#34;../data/validation&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">NUM_PROC</span> <span class="o">=</span> <span class="mi">8</span>  <span class="c1"># 并行进程数，可以改成你的 CPU 核心数</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 目录准备 =====</span>
</span></span><span class="line"><span class="cl"><span class="n">clean_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">SAVE_DIR</span><span class="p">,</span> <span class="s2">&#34;clean&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">noisy_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">SAVE_DIR</span><span class="p">,</span> <span class="s2">&#34;noisy&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">clean_dir</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">noisy_dir</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 加载数据 =====</span>
</span></span><span class="line"><span class="cl"><span class="n">dataset</span> <span class="o">=</span> <span class="n">load_dataset</span><span class="p">(</span><span class="n">DATASET_NAME</span><span class="p">,</span> <span class="n">SPLIT</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 保存函数 =====</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">save_audio</span><span class="p">(</span><span class="n">example</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">uid</span> <span class="o">=</span> <span class="n">example</span><span class="p">[</span><span class="s2">&#34;id&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># noisy</span>
</span></span><span class="line"><span class="cl">    <span class="n">noisy</span> <span class="o">=</span> <span class="n">example</span><span class="p">[</span><span class="s2">&#34;noisy_audio&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">noisy_samples</span><span class="p">,</span> <span class="n">noisy_sr</span> <span class="o">=</span> <span class="n">noisy</span><span class="p">[</span><span class="s2">&#34;array&#34;</span><span class="p">],</span> <span class="n">noisy</span><span class="p">[</span><span class="s2">&#34;sampling_rate&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># clean</span>
</span></span><span class="line"><span class="cl">    <span class="n">clean</span> <span class="o">=</span> <span class="n">example</span><span class="p">[</span><span class="s2">&#34;clean_audio&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">clean_samples</span><span class="p">,</span> <span class="n">clean_sr</span> <span class="o">=</span> <span class="n">clean</span><span class="p">[</span><span class="s2">&#34;array&#34;</span><span class="p">],</span> <span class="n">clean</span><span class="p">[</span><span class="s2">&#34;sampling_rate&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 确保采样率一致</span>
</span></span><span class="line"><span class="cl">    <span class="k">assert</span> <span class="n">noisy_sr</span> <span class="o">==</span> <span class="n">clean_sr</span><span class="p">,</span> <span class="sa">f</span><span class="s2">&#34;Sample rate mismatch: noisy=</span><span class="si">{</span><span class="n">noisy_sr</span><span class="si">}</span><span class="s2">, clean=</span><span class="si">{</span><span class="n">clean_sr</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 保存文件路径</span>
</span></span><span class="line"><span class="cl">    <span class="n">noisy_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">noisy_dir</span><span class="p">,</span> <span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">uid</span><span class="si">}</span><span class="s2">.wav&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">clean_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">clean_dir</span><span class="p">,</span> <span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">uid</span><span class="si">}</span><span class="s2">.wav&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># 写文件</span>
</span></span><span class="line"><span class="cl">    <span class="n">sf</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">noisy_path</span><span class="p">,</span> <span class="n">noisy_samples</span><span class="p">,</span> <span class="n">noisy_sr</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">sf</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">clean_path</span><span class="p">,</span> <span class="n">clean_samples</span><span class="p">,</span> <span class="n">clean_sr</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">{</span><span class="s2">&#34;noisy_path&#34;</span><span class="p">:</span> <span class="n">noisy_path</span><span class="p">,</span> <span class="s2">&#34;clean_path&#34;</span><span class="p">:</span> <span class="n">clean_path</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 多进程导出 =====</span>
</span></span><span class="line"><span class="cl"><span class="n">dataset</span><span class="o">.</span><span class="n">map</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">save_audio</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">num_proc</span><span class="o">=</span><span class="n">NUM_PROC</span><span class="p">,</span>      <span class="c1"># 开启多进程</span>
</span></span><span class="line"><span class="cl">    <span class="n">desc</span><span class="o">=</span><span class="s2">&#34;Exporting audio&#34;</span><span class="p">,</span> <span class="c1"># tqdm 进度条描述</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h2 id="指标计算实践一步步上手">指标计算实践：一步步上手</h2>
<p>计算这些指标需要工具和脚本。URGENT挑战的GitHub仓库（https://github.com/urgent-challenge/urgent2024_challenge）提供了evaluation_metrics文件夹下的实用脚本，如calculate_intrusive_se_metrics.py（处理PESQ、ESTOI、SDR、MCD、LSD等侵入式指标，支持无限SDR值处理），calculate_nonintrusive_dnsmos.py和calculate_nonintrusive_nisqa.py分别计算DNSMOS和NISQA。</p>
<p><strong>计算步骤示例</strong>：</p>
<blockquote>
<p>参考evaluation_metrics/README.md</p>
</blockquote>
<ol>
<li><strong>数据准备</strong>对validation数据集中的noisy数据进行处理，得到enhanced的数据，按下面的目录结构进行组织
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">📁 /path/to/your/data/
</span></span><span class="line"><span class="cl">├── 📁 enhanced/
</span></span><span class="line"><span class="cl">│   ├── 🔈 fileid_1.wav
</span></span><span class="line"><span class="cl">│   ├── 🔈 fileid_2.wav
</span></span><span class="line"><span class="cl">│   └── ...
</span></span><span class="line"><span class="cl">└── 📁 clean/
</span></span><span class="line"><span class="cl">    ├── 🔈 fileid_1.wav
</span></span><span class="line"><span class="cl">    ├── 🔈 fileid_2.wav
</span></span><span class="line"><span class="cl">    └── ...</span></span></code></pre></td></tr></table>
</div>
</div>
</li>
<li><strong>生成scp文件</strong> 为clean数据和enhance数据生成对应的scp文件，在scp文件中包含两列信息，一列是一个唯一的文件id，一列是文件路径，如下
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># enhanced.scp
</span></span><span class="line"><span class="cl">fileid_1 /path/to/your/data/enhanced/fileid_1.flac
</span></span><span class="line"><span class="cl">fileid_2 /path/to/your/data/enhanced/fileid_2.flac
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># reference.scp
</span></span><span class="line"><span class="cl">fileid_1 /path/to/your/data/clean/fileid_1.flac
</span></span><span class="line"><span class="cl">fileid_2 /path/to/your/data/clean/fileid_2.flac
</span></span><span class="line"><span class="cl">...</span></span></code></pre></td></tr></table>
</div>
</div>
</li>
<li><strong>运行脚本</strong>：例如，对于侵入式指标，运行<code>calculate_intrusive_se_metrics.py</code>输入增强文件和参考文件，输出PESQ等分数。非侵入式如DNSMOS可直接输入增强语音。</li>
<li><strong>示例代码片段</strong>：
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nv">nj</span><span class="o">=</span><span class="m">8</span>  <span class="c1"># Number of parallel CPU jobs for speedup</span>
</span></span><span class="line"><span class="cl"><span class="nv">python</span><span class="o">=</span>python3
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">output_prefix</span><span class="o">=</span>metrics_score
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># PESQ, ESTOI, SDR, MCD, LSD</span>
</span></span><span class="line"><span class="cl"><span class="si">${</span><span class="nv">python</span><span class="si">}</span> calculate_intrusive_se_metrics.py <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>   --ref_scp reference.scp <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>   --inf_scp enhanced_webrtc.scp <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>   --output_dir <span class="s2">&#34;</span><span class="si">${</span><span class="nv">output_prefix</span><span class="si">}</span><span class="s2">&#34;</span>/scoring_webrtc <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>   --nj <span class="si">${</span><span class="nv">nj</span><span class="si">}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>   --chunksize <span class="m">60</span></span></span></code></pre></td></tr></table>
</div>
</div>
对于批量计算，仓库脚本支持文件夹输入。</li>
</ol>
<p>在实践中，建议结合主观听测（如MOS）验证客观指标，避免“高分低体验”的情况。</p>
<h2 id="结语评估驱动创新">结语：评估驱动创新</h2>
<p>语音增强算法评估不是终点，而是起点。通过URGENT 2024这样的挑战，我们看到评估体系在推动算法向通用、鲁棒方向演进。未来，随着更多非侵入式指标和多模态数据的融入，评估将更贴近真实世界。</p>
<p>最后我们来看下之前介绍的WebRTC NS是什么水平吧，最终的指标如下所示。</p>
<p><img alt="webrtc ns算法评估指标" loading="lazy" src="/images/2025-08-11/validation_webrtc_ns.png"></p>
<p><img alt="noisy" loading="lazy" src="/images/2025-08-11/validation_noisy.png"></p>
<p>可以看到WebRTC NS的评估指标分数只比noisy的分数好一点点，可见还有很大的上升空间。传统算法或多或少都会基于一些假设，而这些假设不只小范围内是生效的，这造成了传统算法的局限性。近年深度学习基于数据驱动的方法，进一步突破这些局限性，极大提高了音频算法的效果上线。下期预告，让我们迈上深度学习时代吧。</p>
<img src="/images/To-Be-Continued.jpeg"/>]]></content:encoded>
    </item>
  </channel>
</rss>
