Language

Saturday, February 2, 2013

如何在 GNU Emacs 減少按鍵次數並提升工作效率


GNU Emacs 是一個非常 powerful 的編輯器, 這個就不需要我多作介紹, 但是與 vim 相比, GNU Emacs 有一個比較大的缺點就是按鍵多。只要是採用 modeless 的方式編輯, 又要功能多, 按鍵數很難減少, 但是還是有一些方法, 可以讓我們整體的按鍵數量變少的, 可以減少手的傷害。至於那些買了青軸機械式鍵盤之後, 想辦法多打字讓別人聽按鍵聲音的, 就不在本文的討論範圍內。

GNU Emacs 有兩種方式減少打字數目, 筆者認為值得推薦, 一種是用巨集(macro), 另一種是用 skeleton 套件。當然還有第三種是編寫 Emacs Lisp, 寫點函數, 這個難度比較高, 不太適合初學者。今天筆者介紹的這兩個方式都很適合初學者使用。

Table of Contents


巨集

首先, 我們來看看巨集。要知道 EMACS 這個名字是由 Editing MACroS 來的, 巨集可是 Emacs 的核心價值啊!只要你發現你在做重複性的工作, 就可以把那些一連串的按鍵動作變成巨集。
定義巨集很簡單, 在你的一連串按鍵動作開始之前, 先輸入 C-x (, 然後就開始按照平常的動作按按鍵, 按完所有按鍵之後, 鍵入 C-x ) 就完成巨集的定義了。
要執行剛剛定義完的巨集, 就按 C-x e, 也可以配合 Emacs 的數字前置指令來執行多次的巨集。比如說你想要執行這個巨集四次, 就鍵入 M-4 C-x e 就會執行這個巨集四次。
The quick brown fox jumps over the lazy dog

比方說, 你想要把上面這個檔案改成一個英文單字一行, 可以用巨集來做, 方法如下:
按鍵動作
C-x (開始錄製巨集
M-f把游標往前移一個單字
C-d刪除一個字元
[ENTER]插入換行字元
C-x )結束巨集的錄製

上述的巨集可以讓一個單字單獨存在於一行, 把剩下的文字換到下一行去, 如果要把所有英文單字都單獨存在於一行, 就需要重複作這個巨集。可以先用 M-x count-words-region 來計算這一行的單字數, 九個。所以要處理完所有的單字, 就輸入按鍵 M-9 C-x e, 不過通常我們錄製巨集的時候已經先做完一遍了, 那這時候你只需要執行 8 次就好。執行完結果就會如下所示:
The
quick
brown
fox
jumps
over
the
lazy
dog



Skeleton




如果你的重複性工作, 是經常性的使用到, 比方說寫函數時的註解, 常常需要寫函數名稱、作者、建立的時間等等資訊, 有些是每次都寫一樣的資訊(如作者), 有些則可以由函數執行結果得來(如日期), 有些需要打兩次一樣的字串(如函數名稱), 那麼 skeleton 就是一個不錯的工具, 讓你減少打字數目。


使用 skeleton 的方法如下:

(define-skeleton your-skeleton-name
  "String to describe this skeleton."
  "String that will be inserted when you call your-skeleton")



然後你就可以用 Emacs Lisp 函數一樣的呼叫方式來呼叫:
M-x your-skeleton-name 這函數就會自動從游標位置插入預先定義好的字串。
高階一點的用法就會牽扯到

  • 使用者輸入字串

    • 使用 (skeleton-read)

  • 重複使用者輸入的字串

    • 使用 v1, v2 變數

  • 游標最後所處位置

    • 使用 "_" 來標示

  • 呼叫 Emacs Lisp 函數來插入字串

    • 直接呼叫


筆者就用我自己用的一個例子來說明 skeleton:
; Skeleton for assembly subroutine header
(define-skeleton insert-asm-header
  "Prompt for subroutine name and insert assembly subroutine header"
  "" ?\n
  ";******************************************************************************" ?\n
  "; Name:\t\t" (setq v1 (skeleton-read "Subroutine name: "))?\n
  "; Purpose:" ?\n
  ";   " (skeleton-read "Purpose: ") ?\n
  "; Method:\t" ?\n
  ";   " ?\n
  "; Parameters:\t\t" (skeleton-read "Parameters: ") ?\n
  "; Affected regs:\t" ?\n
  "; Author:\tAlbert Chun-Chieh Huang, " (insert-current-date) ?\n
  ";******************************************************************************" ?\n
  v1 \n
  "" _ \n
  "rts" \n
  )



定義完之後, 我們就可以用 M-x insert-asm-header 來呼叫這個 skeleton, 呼叫之後, 在 mode line 會出現
Subroutine name: 



要求使用者輸入副程式名稱, 除了馬上把這名稱字串放到 "Name:" 之後, 並且存在 v1 這個變數裡。 接下來會要求使用者輸入 Purpose: 說明這個副程式的用途, 並把副程式用途就插入 (skeleton-read "Purpose: ") 的位置上。接下來的 Parameters: 也一樣。到了 Author 的地方就呼叫 Emacs Lisp 函數 (insert-current-date) 把日期填上。
在倒數第四行的 v1 就是把剛剛存在 v1 這個變數的副程式名稱取代 v1 填上去。
倒數第三行的 "_" 就是指示 skeleton 插入完這些字串之後, 游標要回到這個位置來。
所有被雙引號包起來的都是字串, 不會有特殊意義。在雙引號以外的, 就是 Emacs Lisp 函數、變數、或是特殊字元。=\n= 是換行並且依照所處的 mode 縮排, 而 ?\n 則只有單純的換行字元而已。


下面的例子就是執行完後的結果, 游標會停在倒數第二行, 與 rts 同樣的縮排位置上, 方便我打第一個 instruction.
;******************************************************************************
; Name:         Test
; Purpose:
;   Test
; Method:       
;   
; Parameters:           a1
; Affected regs:        
; Author:       Albert Chun-Chieh Huang, 02 February 2013
;******************************************************************************
Test
        
        rts


如果對於 skeleton 想要有更深入的了解, 可以按 C-h f skeleton-insert, 裡面有關於 define-skeleton 的字串該怎麼寫的詳盡說明。






結語




要提升工作效率, 第一要件就是先找出重複的工作, 並且用快速有效率的方法執行這個工作。當你找出重複性的部份之後, 可以把重複不變的部份抽出來變成巨集, 如果有經常性的重複編輯工作, 就可以考慮用 skeleton 來定義, 如果有每一次呼叫變動的部份, 就考慮把這些變動用呼叫函數或是輸入參數的方式來引入, 如此就可以有效的減少按鍵次數, 並且提升工作效率。



--
Albert Huang
Chun-Chieh Huang(黃俊傑)

Tuesday, December 18, 2012

GNU Radio Talk: A Glimpse into Developing Software-Defined Radio by Python

這是我十二月十七日在 PyHUG(一個新竹的 Python 社群, 由陳永昱(Yung-Yu Chen) 博士與我在 2011 年所組織發起的)講的講題, 內容簡介了軟體無線電的概念, 軟體無線電的硬體以及開源的專案 GNU Radio, 以及使用 GNU Radio 來開發軟體無線電的三種不同路徑的簡介。這是 GNU Radio 系列講題的第一個, 接下來的講題目前未定, 可能會從數位訊號處理的概念以及如何使用 GNU Radio 來作濾波器先切入, 然後再看聽眾反應決定接下來的主題。有任何建議都歡迎提出來!

PyHUG 目前的聚會模式是每個月的第一與第三個星期一晚上, 通常都會有一個或一個以上的二十分鐘短講, 地點在交大計中一樓訓練教室, 所有訊息都是透過 meetup 這個網頁來公告, 你可以到這裡看相關訊息。

The slides were given to PyHUG in December 17, 2012 in PyHUG, which is Python Hsinchu User Group initiated by Dr. Yung-Yu Chen and I in 2011. In this talk, I introduced the concept of software-defined radio, the free & open source software-defined radio project - GNU Radio, RF front-end hardware that can be used with GNU Radio provided by Ettus Research and Realtek, and illustrated three ways to develop software-defined radio by GNU Radio. This is the first of GNU Radio series talk, the topics for the subsequent talks are to be done, and I'll probably start from using filters in GNU Radio as well as concepts of digital signal processing. And then I'll try to decide topics depending upon feedback of attendees. Any idea or suggestions are welcome!

Currently we have regular meetings on the first and the third Monday nights every month at the training classroom in the building of computer center in National Chaio-Tung University. Normally there will be one or two 20-minute talks. All messages related to PyHUG meetings or events are distributed via meetup website, and you can find information here.

Download/view slides of "A Glimpse into Developing Software-Defined Radio by Python"

Saturday, December 15, 2012

工程訓練與人文素養


工程訓練與人文素養, 一個是左腦, 一個是右腦, 一個需要理性, 一個需要感性, 看似非常衝突的兩個面向, 但我覺得是一個工程師必須同時要具備的兩個面向。


工程師, 尤其是電子電機工程師, 在現代的社會及媒體上, 有著許多不同的稱號, 比如說: 科技宅男、竹科新貴,中國大陸還有張江男之類的稱號, 其實都帶有些許戲謔的成分在。但回首過往, 被譽為中國鐵路之父的詹天佑(1861-1919), 不就是一名工程師嗎?他幼年就留學美國, 後來回近代中國修築了中國第一條鐵路, 並且修築了難度頗高的京張鐵路, 不僅帶給當代中國交通上的便利, 更因修築了外國人認為中國人不可能辦到的鐵路而激勵了當時的華人世界。更現代一些, 我們都在國中小學課本裡面讀過的作者, 陳之藩先生(1925-2012), 寫了不少膾炙人口的文章, 被收錄在「旅美小簡」、「在春風裡」、「劍河倒影」、「一星如月」等等, 我想在台灣應該是幾乎每一個人都讀過陳之藩先生的文章, 而他是學電機的, 也是工程師出身。


工程訓練的目的是訓練一個人, 在既有的流程或基礎上, 運用自己所學的知識與理論, 事先籌劃改善的方法, 並預測改善後的成效, 然後著手實踐這個改善方法。因此, 大學的工程相關科系有著非常多的理論與實驗課程, 這些都在養成工程師基礎的知識, 與動手做的能力, 兩者缺一不可, 卻也相輔相成。沒有基礎知識, 不知道實驗結果的真正原因為何; 沒有動手做, 就不知道自己缺乏哪些知識與理論, 也不知道為什麼要學那些理論。


人文素養對一名工程師來說, 乍看之下似乎沒有必要, 畢竟工程師不需要人文素養就能夠成為一名工程師。但是若從工程的本質來看的話, 人文素養又變成不可或缺的一部分。我來給工程下個定義, 把上一段的工程訓練目的稍微擴展一下, 「工程是為了改善人類的生活, 而在既有的基礎上, 運用自己所學的知識, 事先規劃改善方法, 預測改善後的成效, 並且著手實踐它。」既然是為了改善人類的生活, 人文素養能說不重要嗎?工程師做成的產品大部分時候是要給人使用的, 如果工程師在設計的時候, 脫離了「人」來思考, 設計出來的東西不是難以使用, 就是曲高和寡。工程師如果對於人性有所了解, 懂得人, 那麼就能夠很輕易的從日常生活中, 找到改善生活的方法, 讓人類的生活更便利。市面上有一種拖把, 有個桶子, 上面有個轉盤, 在洗好拖把之後可以用腳踩使轉盤轉動, 利用離心力的原理可以輕易的把水甩乾, 就不需要用手擰乾拖把而把手弄髒, 這個產品的問世帶給所有需要打掃的人, 包括家庭主婦與幫理家務的好男人, 非常便利的生活。這個就是因為發明人, 在幫忙老婆打掃家務的時候, 對於整個流程有敏銳與細膩的觀察, 從中找到改善的方法, 並且實踐這個改善的方法。我認為這就是帶有人文素養的工程思維表現。


如果科學家的熱情是來自於研究宇宙的真理, 哲學家的熱情是來自於思考人類的問題, 那麼我覺得工程師的熱情就來自於改善人類的生活。我無法想像工程師只以賺錢為唯一的目的, 也不能是主要目的, 那會讓工程的樂趣整個消失不見, 只剩下金錢遊戲。你能想像廚師只愛賺錢, 而不以做好料理讓客人吃得愉快為熱情嗎?我並不是說賺錢不好, 相反的, 我覺得賺錢很好, 但是以賺錢為目的與熱情的, 有別的職業, 比方說學習巴菲特在股票證券市場上賺錢, 巴菲特就說過他對於賺錢有極大的熱情, 股票與金融市場的即時回報就是金錢, 你把這件事做得愈好, 賺的錢遇多, 如果你的熱情就來自於賺錢, 那麼在證券市場上的即時回報也會讓你的熱情不斷加增。而工程師的即時回報, 是把一個東西改善而變得更好, 而我們心裡知道這些小小的改善累積起來, 就會讓人類的生活變得更好更便利, 但是比較大筆的金錢也許是一年一次的回報, 如果工程師的熱情來自於金錢, 那麼在工程師生涯裡面, 你只有千分之二點七左右(1/365)的時間是有回報來增強你的熱情的, 絕大多數的時間, 你要做你不覺得有趣的事情, 我說這也太痛苦了吧!工程師生涯看似枯燥乏味, 但如果你的熱情來自於改善人類的生活, 那麼這些枯燥乏味的事情, 就會頓時變得很有趣!當你習慣於觀察周遭生活, 找出改善方法, 並且著手實踐它, 誰說下一個改善人類生活的發明家不會是你呢?


--
Albert Huang
Chun-Chieh Huang(黃俊傑)

Wednesday, December 12, 2012

寫實驗紀錄或工作日誌的重要性


從退伍之後, 真的開始有寫程式起, 我就開始寫工作日誌, 一直保持習慣到如今。我從中獲得不少的好處, 今天利用這篇文章來跟大家分享一下。



先從我為什麼開始寫工作日誌講起好了。如同 Donald E. Knuth 在 "Coders at Work"1 裡面所講的, 寫程式是一個很耗腦力, 需要全神貫注的一件事。大家應該都還記得大學要交程式作業前, 常常一寫程式就沒日沒夜, 通宵達旦, 不寫到一個段落不善罷甘休, 但是程式設計的一個段落常常又是一兩天的功夫才會到。萬一還沒寫到一個段落就先休息, 等休息回來又忘記本來的思路了, 於是只好重新思考, 如此會花更多的時間寫程式! 正因為害怕這種事情發生, 於是, 熬夜寫程式就變成了交作業前的常態。大學時作業交完了, 可以好好休息一陣子, 不用每天想程式, 一旦開始工作, 平常的週間五天就要每天寫程式了, 遇到趕專案進度的時候, 可能要一週工作六天!2 因此如何保持每天都能夠有效率的寫程式就變成了一個挑戰與學習, 熬夜變成一個儘量避免的事情, 因為熬夜很容易讓第二天的工作效率大幅下降, 而且晚上最好還是要有自己的生活, 工作才能長長久久的。所以, 我開始寫工作日誌的動機, 就是不想熬夜, 因此, 每天在下班之前, 把當天的工作進度以及對還沒實現的部份的所有想法, 儘量的寫下來, 要足夠清楚明瞭到自己心裡覺得沒什麼好寫了, 而且第二天還能夠看懂。如此一來, 一旦闔上工作日誌, 就可以下班而不會一直擔心自己會忘記原本的想法, 下班後就可以好好放鬆。第二天來辦公室工作的時候, 一看昨天的工作日誌, 也可以很快知道昨天的進度在哪裡, 馬上可以接手繼續下去。



那麼工作日誌要如何撰寫呢?工作日誌的內容可以區分成幾類: 1) 設計 2) 當日該完成事項 3) 工作紀錄 4) 實驗紀錄。



在設計的部份, 筆者的建議是儘量用圖形表示, 因為詳細的文字可能會被紀錄在文件或是程式的註解中, 而圖形是一個描述概念非常有力量的工具, 在工作日誌中就儘量以圖形加上一些重點文字來紀錄你的設計, 這樣在實作過程中可以隨時翻閱設計圖, 可以很快的從程式設計的細節中, 再度回到一個高度來鳥瞰整個叢林, 這樣才不會迷失在樹林中(實作細節)。



當日該完成事項是每天一開始的時候, 告訴自己還有哪些工作還沒完成, 每個工作的優先順序是如何, 這樣在寫任何程式之前, 可以在心中先建立一個清單, 工作效率會大幅提升。如果你有使用萬用手冊的習慣, 那麼這部份就不用太著墨, 只要在執行那個工作的時候, 把工作紀錄寫下來即可。



工作紀錄只要把重點記錄下來即可, 不必把每一個動作記錄下來, 但是要把 know-how 記錄下來, 才不會「知其然而不知其所以然。」



在追蹤某個問題的發生點時, 我們常常做的是如同建立樹狀圖一般, 從 root(issue) 一路往下追蹤到真正發生的原因(root cause), 而常常在分支點時, 都有很多個不同的追蹤方向, 有的時候, 我們會懷疑數個分支都有可能發生問題, 或是我們也許會判斷錯誤導致追蹤錯分支, 甚至有的時候, 一個 issue 是由多個錯誤累積產生的, 就有可能有數個 root cause, 所以數個分支都是問題。這時候有實驗紀錄的話, 就有非常大的幫助。實驗紀錄應該儘量詳盡的紀錄日後可能有幫助的細節, 比如說實驗的設定、過程與結果, 這些都要詳盡紀錄。如果是在追某個或某些 bug, 在分支點時, 應該把所有可能的方向、往這個分支追蹤的判斷理由、每個分支需要花費的成本估計記錄下來, 萬一日後發現不是那麼一回事, 還可以回頭往另一個方向追。或是當某個分支解決之後, 回頭來看該分支所屬的 parent, 看看那個 parent 是不是已經也被解決, 如果沒有, 就表示還有其他原因造成那個錯誤, 就要繼續追蹤其他分支。另外, 很多時候我們可以從統計上來了解我們是否解決完所有的問題, 比方說掉封包的機率(packet dropping probability), 在解網路 driver 或 physical layer 那一層相關問題的時候, 是一個頗適合的測量指標, 我們可以從掉封包的機率的改變看出我們解的問題佔的比例有多大, 是否已經解決大部分的問題。當然, 當掉封包的機率很小的時候, 也不代表我們把問題解決完了, 這時候可以用亂數的方式產生封包來找出我們可能沒發現的問題。這些猜測, 以及某個 root cause 解決完之後的掉封包機率的改變都要寫下來。以掉封包機率而言, 某個 bug 解完之後, 如果沒有一個數量級(10 倍)以上的改變, 那這個 bug 可能跟你的 issue 沒有太大相關。再來, 如果你做實驗之後發現傳送 1000 個封包之後, 掉了 1 個封包, 這時候也至少要把測試數量提升一個數量級以上, 也就是至少傳送 104 個封包來測試掉封包機率。



在每天工作要結束前, 重頭再把工作日誌翻閱一遍, 看看今日的工作還有哪些沒有完成, 然後要紀錄腦袋裡對於今日的工作還有什麼想法, 未來該追蹤的方向是什麼, 總之把心中覺得未完成的東西紀錄在紙上, 這樣心中就不會有牽掛, 之後也不會因為忘記某些非常好的想法而扼腕。



手寫的工作日誌最好有索引, 把每天的主題用一句話統一寫到那本工作日誌的開頭或結尾的地方, 以便日後快速翻閱。每個月或每一季再花一點時間把工作日誌重點整理一次, 以供日後學習之用, 如此就可以累積寶貴的經驗。



工作日誌以內頁的記號, 可以分成方格、直線、網點與空白。每個人都有不同的選擇, 方格與網點適合繪圖或實驗紀錄, 直線適合文字比較多的紀錄, 空白是比較少使用的格式, 但是限制也最少。我個人覺得方格頗適合繪圖, 會很鼓勵使用的人用圖形來表示, 比較適合創意多的設計。而直線則比較中規中矩, 會鼓勵使用的人用文字來呈現, 比較適合不需要圖形表現的紀錄。



在今天的文章裡, 我分享了過去十幾年我寫工作日誌的經驗與方法, 我從紀錄工作日誌的習慣, 以及整理工作日誌的重點, 學習到非常多自己在業界的經驗, 這些經驗都非常寶貴。各位在看完之後, 也許能夠從中獲得一些靈感, 也開始寫工作日誌, 並且享受到下班就把一切放下的愜意!有句話說:「經驗是你最好的老師」,在用工作日誌的形式來紀錄與整理你的經驗之後, 經驗絕對會變成你很好的老師!



Footnotes:



1 Peter Seibel 著、蔡學鏞 譯, 「編程的頂尖對話-閱讀 15 位軟體大師的核心思維」, 碁峰, 民 100 年。



2 筆者建議星期天還是好好休息, 以筆者過去的經驗, 如果每週工作七天沒有休息, 兩週之後每一天的工作效率大概就只剩下 50% 不到吧, 終究是要還回去的, 所以還是以每週工作六天為最大限度。





--
Albert Huang
Chun-Chieh Huang(黃俊傑)

Tuesday, December 4, 2012

平均同步訊號的意義 - 如何處理雜訊


這個世界上的事情基本上是不可預測的, 在訊號處理上, 我們把不能夠預測的部份都當作是雜訊來看待, 然後用統計的觀點來看我們想要的訊號。



在這篇文章裡, 筆者會介紹對待雜訊最基本的工具: 平均, 以及在平均這個運算上, 我們能夠得到什麼樣的好處, 也就是能夠得到多少增益(gain), 這樣我們就知道需要花多少次的平均能夠得到我們想要的結果。為了比較容易說明平均, 在這篇文章裡, 筆者只先專注在同步訊號的平均, 而這也是示波器的基本原理之一。






同步平均 (Coherent Averaging)




訊號有分非週期性與週期性序號, 要能夠同步, 必須是週期訊號, 所以像語音訊號這種非週期訊號, 我們就先不討論。週期訊號裡面, 又以正弦波在頻域上最單純, 所以我們先來看一段正弦波。這是週期為 20 的正弦波, 圖上總共兩個週期:

From SignalAveraging


我們把上述的數位訊號表列如下:




















X(0)X(1)X(2)X(3)X(4)X(5)X(6)X(7)X(8)X(9)
0.00000.30900.58780.80900.95111.00000.95110.80900.58780.3090
X(10)X(11)X(12)X(13)X(14)X(15)X(16)X(17)X(18)X(19)
0.0000-0.3090-0.5878-0.8090-0.9511-1.0000-0.9511-0.8090-0.5878-0.3090
X(20)X(21)X(22)X(23)X(24)X(25)X(26)X(27)X(28)X(29)
-0.00000.30900.58780.80900.95111.00000.95110.80900.58780.3090
X(30)X(31)X(32)X(33)X(34)X(35)X(36)X(37)X(38)X(39)
0.0000-0.3090-0.5878-0.8090-0.9511-1.0000-0.9511-0.8090-0.5878-0.3090




那麼平均這兩個週期的正弦波(週期為 20) 的動作就是:



Xavg(0) = X(0)+X(20)



Xavg(1) = X(1)+X(21)






Xavg(19) = X(19)+X(19+20)



最後 Xavg(0:19) 就會是平均後的正弦波, 如果以 N 來代表取平均的週期數, 而週期以 T 來帶進去, 那麼我們的運算式子會變成:



Xavg(i) = ( X(i) + X(i+T) + X(i+2*T) + … + X(i+(N-1)*T) ) / N, i = 0..T-1



上述的訊號還是相當的純淨沒有雜質, 看不出平均的意義, 接下來我們來看加入雜訊之後的樣子, 我們假設雜訊是 WGN(White Gaussian Noise), 意思是這些雜訊的振幅符合 Gaussian 分布, 而雜訊彼此之間沒有關聯, 白色表示頻譜一致分布在頻域上。



我們讓訊雜比是 0 dB, 意思是雜訊跟訊號的功率是一樣的, 訊號加雜訊會如下圖所示, 圖中的 N 代表平均的週期數:

From SignalAveraging


如果我們平均 2 個週期, 看起來還是跟 N=1 時差不多:
From SignalAveraging


如果我們平均 16 個週期, 稍微好一點點了:
From SignalAveraging


如果我們平均 1024 個週期, 喔, 已經開始有蠻漂亮的訊號形狀了:
From SignalAveraging


如果我們平均 4096 個週期, 哇, 訊號又更明顯了:
From SignalAveraging


如果我們平均 65536 個週期, 這個已經幾乎就跟沒有雜訊一樣了, 我們很少有機會能平均這麼多次, 放在這裡是要讓讀者明白平均的威力:
From SignalAveraging


我們把原來的純淨訊號與 N=65536 平均後的訊號放在一起看:
From SignalAveraging

From SignalAveraging


所以從上述幾張圖一路看下來, 很明顯的平均同步訊號能夠讓訊號浮現而雜訊變小, 用訊號處理的術語就是有增益(gain), 那麼我們從平均能夠得到的增益是多少呢?接下來我們來仔細算一下。







增益




假設我們想要得到的常數訊號振幅是 A, 而雜訊是 N(n) 那麼我們接收到的訊號 r(n) = A + N(n), 在統計上, 我們可以把 A 當作是這個 distribution 的平均值。雜訊的振幅, 亦即 r(n) 的標準差是 sigmain。



在雜訊本身的 distribution 不變的情況下, 取 N 個取樣做平均之後, 其標準差會變成:



sigmaavg = sigmain / sqrt(N), 亦即平均 N 次之後的標準差為原來的標準差除以根號 N。



原來的訊雜比 SNRin = A / sigmain



平均後的訊雜比 SNRavg = A / sigmaavg



Gain = SNRavg / SNRin = sigmain / sigmaavg = sqrt(N)



把增益用分貝表示: Gain = 20*log10(sqrt(N)) = 10*log10(N) dB, 第一個 log10 乘以 20 是因為這是振幅。



把之前的平均次數能夠得到的增益做成表格, 如下所示:















NGain(dB)
10
23.01
1612.04
102430.10
409636.12
6553648.16










結語




只要在現實生活中處理訊號, 免不了的就是要處理雜訊, 這是痛苦的地方, 也是這個世界迷人有趣的地方。如何與雜訊共存, 或是把雜訊對我們的影響變小, 是我們每一個要處理訊號的工程師必須要面對的問題。在這篇文章中, 我們了解到了在訊號同步的情況之下, 如何透過同步平均(coherent averaging) 來改善訊雜比, 使我們要得到的訊號「浮出水面」, 以及要作多少次平均可以得到多少增益, 將來各位如果遇到需要處理訊號的時候, 有最基本但也非常有用的工具可以把雜訊消除。







參考書目




Sheldon Ross, "A First Course in Probability," 6/e, Prentice-Hall, 2002.



Richard G. Lyons, "Understandding Digital Signal Processing," 3/e, Prentice-Hall, 2011.




--
Albert Huang
Chun-Chieh Huang(黃俊傑)