音頻進階學習十九——逆系統(簡單進行回聲消除)

文章目錄

  • 前言
  • 一、可逆系統
    • 1.定義
    • 2.解卷積
    • 3.逆系統恢復原始信號過程
    • 4.逆系統與原系統的零極點關系
  • 二、使用逆系統去除回聲
    • 獲取原信號的頻譜
    • 原系統和逆系統幅頻響應和相頻響應
    • 使用逆系統恢復原始信號
    • 整體代碼如下
  • 總結


前言

在上一篇音頻進階學習十八——幅頻響應相同系統、全通系統、最小相位系統文章中,我們在最小相位系統中提到了逆系統:一個穩定因果的LTI系統,同時會有一個穩定因果的逆系統。

本文中將會介紹逆系統的含義,通過對于零極點的分析,來對比逆系統和原系統的關聯。最后,將會使用逆系統來對于給定的近端信號和參考信號來進行回聲消除。

|版本聲明:山河君,未經博主允許,禁止轉載


一、可逆系統

1.定義

如果一個系統的輸入是 x [ n ] x[n] x[n],經過系統 H ( z ) H(z) H(z)后系統的輸出是 y [ n ] y[n] y[n],那么將 y [ n ] y[n] y[n]通過系統 G ( z ) G(z) G(z)后輸出的是 x [ n ] x[n] x[n],此時系統 G ( z ) G(z) G(z)是系統 H ( z ) H(z) H(z)的逆系統。

G ( z ) G(z) G(z) H ( z ) H(z) H(z)的關系:

  • 頻域關系
    G ( z ) H ( z ) = 1 = > g [ n ] = h [ n ] G(z)H(z)=1=>g[n]=h[n] G(z)H(z)=1=>g[n]=h[n]
  • 時域關系
    對于系統 H H H的脈沖響應有: y [ n ] = x [ n ] ? h [ n ] y[n]=x[n]*h[n] y[n]=x[n]?h[n]
    對于系統 G G G的脈沖響應有: x ′ [ n ] = y [ n ] ? g [ n ] = ( x [ n ] ? h [ n ] ) ? g [ n ] = x [ n ] ? ( h [ n ] ? g [ n ] ) x'[n]=y[n]*g[n]=(x[n]*h[n])*g[n]=x[n] *(h[n]*g[n]) x[n]=y[n]?g[n]=(x[n]?h[n])?g[n]=x[n]?(h[n]?g[n])
    如果想要 x ′ [ n ] = x [ n ] x'[n]=x[n] x[n]=x[n],那么 h [ n ] ? g [ n ] = δ n h[n]*g[n]=\delta n h[n]?g[n]=δn

2.解卷積

對于給定的輸入信號 x [ n ] x[n] x[n]和輸出信號 y [ n ] y[n] y[n],我們知道通過系統有:
X ( f ) = F { x [ n ] } , Y ( f ) = F { x [ n ] } , H ( f ) = X ( f ) Y ( f ) X(f)=F\{x[n]\},Y(f)=F\{x[n]\},H(f)=\frac{X(f)}{Y(f)} X(f)=F{x[n]},Y(f)=F{x[n]},H(f)=Y(f)X(f)?
通過逆變換, h [ n ] = F ? 1 { H ( f ) } h[n]=F^{-1}\{H(f)\} h[n]=F?1{H(f)}得到沖激響應的這一過程,叫做解卷積

3.逆系統恢復原始信號過程

首先結合具體場景,假設發射了一個信號 x [ n ] x[n] x[n],通過多條途徑例如墻體、窗戶的反射,導致接收的信號是 y [ n ] y[n] y[n],我們想通過 y [ n ] y[n] y[n]恢復為原始的 x [ n ] x[n] x[n],如下圖:
在這里插入圖片描述

  • 發射約定好的信號 T [ n ] T[n] T[n]
  • 接收 T ′ [ n ] = T [ n ] ? h [ n ] T'[n]=T[n]*h[n] T[n]=T[n]?h[n]
  • 通過解卷積得到 h [ n ] h[n] h[n]
  • 構建逆系統 g [ n ] g[n] g[n]
  • 通過逆系統獲得原始信號 x [ n ] = y [ n ] ? G [ n ] x[n]=y[n]*G[n] x[n]=y[n]?G[n]

值得注意的是,在實際場景中,過程會比較復雜,例如不存在發射約定好的信號,或者場景變換導致沖激響應的變化等等,這就需要一個自適應濾波器不斷的估計回聲信號,當然這是以后的內容。

4.逆系統與原系統的零極點關系

對于Z變換的頻率響應,它的逆系統
H ( z ) = ∏ m = 1 M ( 1 ? c m z ? 1 ) ∏ n = 1 N ( 1 ? d n z ? 1 ) , G ( z ) = ∏ n = 1 N ( 1 ? d n z ? 1 ) ∏ m = 1 M ( 1 ? c m z ? 1 ) H(z)=\frac{\prod_{m=1}^M(1-c_mz^{-1})}{\prod_{n=1}^N(1-d_nz^{-1})},G(z)=\frac{\prod_{n=1}^N(1-d_nz^{-1})}{\prod_{m=1}^M(1-c_mz^{-1})} H(z)=n=1N?(1?dn?z?1)m=1M?(1?cm?z?1)?,G(z)=m=1M?(1?cm?z?1)n=1N?(1?dn?z?1)?
也就是原系統 H ( z ) H(z) H(z)和逆系統 G ( z ) G(z) G(z)的零極點是互換的,那么此時如果逆系統 G ( z ) G(z) G(z)是因果穩定的,那么逆系統 G ( z ) G(z) G(z)的零點和極點都在單位圓內,而此時原系統的 H ( z ) H(z) H(z)零點和極點同樣都在單位圓內,此時都為最小相位系統。

這也是上一篇文章中最小相位系統提到的特性。

二、使用逆系統去除回聲

現在使用matlab來設計一個逆系統,對于已知的輸入信號和輸出信號進行轉換。

獲取原信號的頻譜

需要注意的是,這里的輸入信號和輸出信號是筆者自己通過pcm疊加轉換的,所以頻域上可能看不出特別大的區別,但是實際可以明顯聽到回聲。

核心代碼

%輸入信號和輸出信號頻域圖
H_in=fft(input_signal);
H_out=fft(output_signal);
R_in = abs(H_in);
R_out = abs(H_out);
freq=linspace(0,fs/2, floor(min_len/2));figure;
subplot(2,1,1);
plot(freq, R_in(1:floor(min_len/2)));
title("輸入信號頻域圖");xlabel("頻率H(z)");ylabel("幅度");grid on;
subplot(2,1,2);
plot(freq, R_out(1:floor(min_len/2)));
title("輸出信號頻域圖");xlabel("頻率H(z)");ylabel("幅度");grid on;

得到結果:
在這里插入圖片描述

原系統和逆系統幅頻響應和相頻響應

通過圖像幅頻響應圖像和相頻響應的圖像,可以很清楚的看到原系統和逆系統的幅頻響應和相頻響應是倒過來的。

同時值得注意的是:

  • 某些頻率上幅值接近零(即原系統在這些頻率上有很強的衰減),那么其倒數 H i n v H_{inv} Hinv?可能會變得非常大,導致放大效應。
  • 在計算 H i n v H_{inv} Hinv?浮點數精度問題可能會導致不穩定。
  • 幅度部分可能被正常恢復,但相位的誤差會導致合成信號在時域上發生相干疊加,造成某些時刻的峰值更大,最終影響整體信號能量。

而這些問題需要結合窗口平滑來進行解決,這里是通過增加了一些閾值來減少極端值的出現。

代碼如下:

H_c = H_in ./ (H_out + eps);
%H_inv= 1 ./ (H_c + eps);
%H_inv(abs(H_c) < 1e-3) = 0;
H_inv = 1 ./ (H_c + 0.01);
H_inv(abs(H_c) < 1e-2) = 0;
R_c=abs(H_c);
R_inv=abs(H_inv);figure;
subplot(2,2,1);
plot(freq, 20*log10(R_c(1:floor(min_len/2))));
title('原系統幅頻響應');xlabel('頻率 (Hz)'); ylabel('幅度 (dB)'); grid on;
subplot(2,2,2);
plot(freq, rad2deg(angle(H_c(1:floor(min_len/2)))));
title('原系統相頻響應');xlabel('頻率 (Hz)'); ylabel('相位(度)'); grid on;
subplot(2,2,3);
plot(freq, 20*log10(R_inv(1:floor(min_len/2))));
title('逆系統幅頻響應');xlabel('頻率 (Hz)'); ylabel('幅度 (dB)'); grid on;
subplot(2,2,4);
plot(freq, rad2deg(angle(H_inv(1:floor(min_len/2)))));
title('逆系統相頻響應');xlabel('頻率 (Hz)'); ylabel('相位(度)'); grid on;

得到
在這里插入圖片描述

使用逆系統恢復原始信號

最后恢復的信號還是變大了,但是此時已經聽不見回聲了,這里在恢復時已經使用整體能量歸一化來盡量減少能量放大的影響。

代碼如下:

%還原后的信號頻譜
restored_signal = real(ifft(fft(output_signal) .* H_inv));
restored_signal = restored_signal / norm(restored_signal) * norm(input_signal);restored_signal = int16(restored_signal);
fwrite(turn_file, restored_signal, 'int16');
fclose(turn_file);
H_restored = fft(restored_signal);
R_res = abs(H_restored);
figure;
subplot(1,1,1);
plot(freq, R_res(1:floor(min_len/2)));
title('還原信號的頻域圖');
xlabel('頻率 (Hz)'); ylabel('幅度'); grid on;

得到
在這里插入圖片描述

整體代碼如下

fs=16000;
input_file=fopen("input.pcm",'rb');
output_file=fopen("output.pcm",'rb');
turn_file=fopen("turn.pcm",'wb+');input_signal=fread(input_file, inf, 'int16');
output_signal=fread(output_file, inf, 'int16');
fclose(input_file);
fclose(output_file);min_len=min(length(input_signal), length(output_signal));
input_signal=input_signal(1:min_len);
output_signal=output_signal(1:min_len);%輸入信號和輸出信號頻域圖
H_in=fft(input_signal);
H_out=fft(output_signal);
R_in = abs(H_in);
R_out = abs(H_out);
freq=linspace(0,fs/2, floor(min_len/2));figure;
subplot(2,1,1);
plot(freq, R_in(1:floor(min_len/2)));
title("輸入信號頻域圖");xlabel("頻率H(z)");ylabel("幅度");grid on;
subplot(2,1,2);
plot(freq, R_out(1:floor(min_len/2)));
title("輸入信號相頻響應");xlabel("頻率H(z)");ylabel("幅度");grid on;%原系統和逆系統幅頻響應和相頻響應
H_c = H_in ./ (H_out + eps);
%H_inv= 1 ./ (H_c + eps);
%H_inv(abs(H_c) < 1e-3) = 0;
H_inv = 1 ./ (H_c + 0.01);
H_inv(abs(H_c) < 1e-2) = 0;
R_c=abs(H_c);
R_inv=abs(H_inv);figure;
subplot(2,2,1);
plot(freq, 20*log10(R_c(1:floor(min_len/2))));
title('原系統幅頻響應');xlabel('頻率 (Hz)'); ylabel('幅度 (dB)'); grid on;
subplot(2,2,2);
plot(freq, rad2deg(angle(H_c(1:floor(min_len/2)))));
title('原系統相頻響應');xlabel('頻率 (Hz)'); ylabel('相位(度)'); grid on;
subplot(2,2,3);
plot(freq, 20*log10(R_inv(1:floor(min_len/2))));
title('逆系統幅頻響應');xlabel('頻率 (Hz)'); ylabel('幅度 (dB)'); grid on;
subplot(2,2,4);
plot(freq, rad2deg(angle(H_inv(1:floor(min_len/2)))));
title('逆系統相頻響應');xlabel('頻率 (Hz)'); ylabel('相位(度)'); grid on;%還原后的信號頻譜
restored_signal = real(ifft(fft(output_signal) .* H_inv));
restored_signal = restored_signal / norm(restored_signal) * norm(input_signal);restored_signal = int16(restored_signal);
fwrite(turn_file, restored_signal, 'int16');
fclose(turn_file);
H_restored = fft(restored_signal);
R_res = abs(H_restored);
figure;
subplot(1,1,1);
plot(freq, R_res(1:floor(min_len/2)));
title('還原信號的頻域圖');
xlabel('頻率 (Hz)'); ylabel('幅度'); grid on;

總結

本文中所使用的逆系統是基于原系統是一個最小相位系統來構建的。那如果原系統不是最小相位系統是存在一個不會發散的逆系統呢?其實答案已經在上一篇文章中給出了,那就是使用全通分解,去除零極點在單位圓外的影響。只使用全通分解中對于最小相位系統的部分。

其次,值得注意的是,本文中的例子是給定了參考信號來進行回聲消除,但在實際環境中,對于參考信號如何辨別是否是回聲,這需要使用自適應濾波器來進行回聲建模。

反正收藏也不會看,不如點個贊吧!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897450.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897450.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897450.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue3 使用sass變量

1. 在<style>中使用scss定義的變量和css變量 1. 在/style/variables.scss文件中定義scss變量 // scss變量 $menuText: #bfcbd9; $menuActiveText: #409eff; $menuBg: #304156; // css變量 :root {--el-menu-active-color: $menuActiveText; // 活動菜單項的文本顏色--el…

gbase8s rss集群通信流程

什么是rss RSS是一種將數據從主服務器復制到備服務器的方法 實例級別的復制 (所有啟用日志記錄功能的數據庫) 基于邏輯日志的復制技術&#xff0c;需要傳輸大量的邏輯日志,數據庫需啟用日志模式 通過網絡持續將數據復制到備節點 如果主服務器發生故障&#xff0c;那么備用服務…

熵與交叉熵詳解

前言 本文隸屬于專欄《機器學習數學通關指南》&#xff0c;該專欄為筆者原創&#xff0c;引用請注明來源&#xff0c;不足和錯誤之處請在評論區幫忙指出&#xff0c;謝謝&#xff01; 本專欄目錄結構和參考文獻請見《機器學習數學通關指南》 ima 知識庫 知識庫廣場搜索&#…

程序化廣告行業(3/89):深度剖析行業知識與數據處理實踐

程序化廣告行業&#xff08;3/89&#xff09;&#xff1a;深度剖析行業知識與數據處理實踐 大家好&#xff01;一直以來&#xff0c;我都希望能和各位技術愛好者一起在學習的道路上共同進步&#xff0c;分享知識、交流經驗。今天&#xff0c;咱們聚焦在程序化廣告這個充滿挑戰…

探索在生成擴散模型中基于RAG增強生成的實現與未來

概述 像 Stable Diffusion、Flux 這樣的生成擴散模型&#xff0c;以及 Hunyuan 等視頻模型&#xff0c;都依賴于在單一、資源密集型的訓練過程中通過固定數據集獲取的知識。任何在訓練之后引入的概念——被稱為 知識截止——除非通過 微調 或外部適應技術&#xff08;如 低秩適…

DeepSeek 助力 Vue3 開發:打造絲滑的表格(Table)之添加列寬調整功能,示例Table14基礎固定表頭示例

前言&#xff1a;哈嘍&#xff0c;大家好&#xff0c;今天給大家分享一篇文章&#xff01;并提供具體代碼幫助大家深入理解&#xff0c;徹底掌握&#xff01;創作不易&#xff0c;如果能幫助到大家或者給大家一些靈感和啟發&#xff0c;歡迎收藏關注哦 &#x1f495; 目錄 Deep…

取反符號~

取反符號 ~ 用于對整數進行按位取反操作。它會將二進制表示中的每一位取反&#xff0c;即 0 變 1&#xff0c;1 變 0。 示例 a 5 # 二進制表示為 0000 0101 b ~a # 按位取反&#xff0c;結果為 1111 1010&#xff08;補碼表示&#xff09; print(b) # 輸出 -6解釋 5 的二…

論文閱讀分享——UMDF(AAAI-24)

概述 題目&#xff1a;A Unified Self-Distillation Framework for Multimodal Sentiment Analysis with Uncertain Missing Modalities 發表&#xff1a;The Thirty-Eighth AAAI Conference on Artificial Intelligence (AAAI-24) 年份&#xff1a;2024 Github&#xff1a;暫…

WBC已形成“東亞-美洲雙中心”格局·棒球1號位

世界棒球經典賽&#xff08;WBC&#xff09;作為全球最高水平的國家隊棒球賽事&#xff0c;參賽隊伍按實力、地域和歷史表現可分為多個“陣營”。以下是基于歷屆賽事&#xff08;截至2023年&#xff09;的陣營劃分及代表性隊伍分析&#xff1a; 第一陣營&#xff1a;傳統豪強&a…

django中路由配置規則的詳細說明

在 Django 中,路由配置是將 URL 映射到視圖函數或類視圖的關鍵步驟,它決定了用戶請求的 URL 會觸發哪個視圖進行處理。以下將詳細介紹 Django 中路由配置的規則、高級使用方法以及多個應用配置的規則。 基本路由配置規則 1. 項目級路由配置 在 Django 項目中,根路由配置文…

【報錯】微信小程序預覽報錯”60001“

1.問題描述 我在微信開發者工具寫小程序時&#xff0c;使用http://localhost:8080是可以請求成功的&#xff0c;數據全都可以無報錯&#xff0c;但是點擊【預覽】&#xff0c;用手機掃描二維碼瀏覽時&#xff0c;發現前端圖片無返回且報錯60001&#xff08;打開開發者模式查看日…

柵格裁剪(Python)

在地理數據處理中&#xff0c;矢量裁剪柵格是一個非常重要的操作&#xff0c;它可以幫助我們提取感興趣的區域并獲得更精確的分析結果。其重要性包括&#xff1a; 區域限定&#xff1a;地球科學研究通常需要關注特定的地理區域。通過矢量裁剪柵格&#xff0c;我們可以將柵格數…

【無人機路徑規劃】基于麻雀搜索算法(SSA)的無人機路徑規劃(Matlab)

效果一覽 代碼獲取私信博主基于麻雀搜索算法&#xff08;SSA&#xff09;的無人機路徑規劃&#xff08;Matlab&#xff09; 一、算法背景與核心思想 麻雀搜索算法&#xff08;Sparrow Search Algorithm, SSA&#xff09;是一種受麻雀群體覓食行為啟發的元啟發式算法&#xff0…

MySQL數據庫安裝及基礎用法

安裝數據庫 第一步&#xff1a;下載并解壓mysql-8.4.3-winx64文件夾 鏈接: https://pan.baidu.com/s/1lD6XNNSMhPF29I2_HBAvXw?pwd8888 提取碼: 8888 第二步&#xff1a;打開文件中的my.ini文件 [mysqld]# 設置3306端口port3306# 自定義設置mysql的安裝目錄&#xff0c;即解…

軟件工程:軟件開發之需求分析

物有本末&#xff0c;事有終始。知所先后&#xff0c;則近道矣。對軟件開發而言&#xff0c;軟件需求乃重中之重。必先之事重千鈞&#xff0c;不可或缺如日辰。 汽車行業由于有方法論和各種標準約束&#xff0c;對軟件開發有嚴苛的要求。ASPICE指導如何審核軟件開發&#xff0…

正則表達式,idea,插件anyrule

????package lx;import java.util.regex.Pattern;public class lxx {public static void main(String[] args) {//正則表達式//寫一個電話號碼的正則表達式String regex "1[3-9]\\d{9}";//第一個數字是1&#xff0c;第二個數字是3-9&#xff0c;后面跟著9個數字…

RISC-V醫療芯片工程師復合型轉型的路徑與策略

從RISC-V到醫療芯片:工程師復合型轉型的路徑與策略 一、引言 1.1 研究背景 在科技快速發展的當下,芯片技術已然成為推動各行業進步的核心驅動力之一。其中,RISC-V 架構作為芯片領域的新興力量,正以其獨特的優勢迅速崛起,對整個芯片產業的格局產生著深遠影響。RISC-V 架…

【設計模式】掌握建造者模式:如何優雅地解決復雜對象創建難題?

概述 將一個復雜對象的構建與表示分離&#xff0c;使得同樣的構建過程可以創建不同的表示。 分離了部件的構造(由Builder來負責)和裝配(由Director負責)。 從而可以構造出復雜的對象。這個模式適用于&#xff1a;某個對象的構建過程復雜的情況。 由于實現了構建和裝配的解耦。…

量子計算對區塊鏈技術的影響:革新與挑戰

量子計算對區塊鏈技術的影響&#xff1a;革新與挑戰 大家好&#xff0c;我是你們的技術伙伴Echo_Wish。今天我們來探討一個頗具前沿性的話題——量子計算對區塊鏈技術的影響。量子計算作為新一代計算技術&#xff0c;其強大的計算能力為各個領域帶來了革新。然而&#xff0c;量…

【Java代碼審計 | 第八篇】文件操作漏洞成因及防范

未經許可&#xff0c;不得轉載。 文章目錄 文件操作漏洞文件讀取漏洞基于 InputStream 的讀取基于 FileReader 的讀取 文件下載漏洞文件刪除漏洞防范 文件操作漏洞 分為文件讀取漏洞、文件下載漏洞與文件刪除漏洞。 文件讀取漏洞 在Java中&#xff0c;文件讀取通常有兩種常見…