【簡音單樂-聽見不同】Arduino 拍手音樂盒與 PCM 技術

此次實作主要是建構【聲音偵測 + 電子音樂盒】的 Arduino 綜合應用案例,只要直接下載安裝相關軟體及簡單組裝硬體,就能運用麥克風模組偵測我們的拍手聲音,Arduino內部程式再根據聲音大小進而播放預先錄製的音效,也就是名副其實的【拍手音樂盒】,而且只要更動下載程式的重點註解,不用額外多寫一行程式碼,就完成建構【按鈕開關 + 電子音樂盒】的 Arduino 綜合應用案例,例如後面還會提到的【鬧鐘變音樂鐘】。當然還會介紹如何製作自己的音效,只要按部就班跟著步驟做,這一點都不難,有了自己設計的個性音效,這樣就更能適應各種應用場合和環境。此外,由於坊間書籍或網頁博文,對Arduino程式介紹幾乎千篇一律用傳統觀念設計的,這對入門者甚有幫助,然而水能載舟也能覆舟,恰恰就是這傳統程式設計觀念,像緊箍咒般牢牢困住著入門者,無法展翅、談何高飛,創新開發之路總是仰之彌高望而生嘆,沒門。因而,唯有軟硬體兩手都要夠厚,才得以涅磐重生,當然也就必須學著運用物件導向設計觀念,為此,本次所附Arduino程式完全是筆者用物件導向觀念設計的,從實作入手,相信對學習物件導向程式設計會更加有效。以下所附照片,正是本次實作的【拍手音樂盒】,雖然沒有美麗盒子當外裝,但其功能基本是足夠的。

此次實作案例將教我們怎麼運用 Arduino資源與輔助工具,做一個自己定制的音效(聲音長度小於4秒鐘)。 此實作案例運用的軟體資源均是免費的,首要感謝這些公司團體或小組無私奉獻,讓我們擁有很好的學習環境與資源, 進而激發我們更多的教學靈感與開發更多的教學案例,在這種良性循環之下,讓世界變得更加美好。 來源於麻省理工“high-low tech”小組,所有軟體均是免費。 當決定用什麼聲音的時候,我們一定要考慮 Aduino UNO 的小容量-32kb。 必要軟體在MacOS, Linux, 和Windows不同作業環境下都能適用。需要預裝的軟體有Arduino IDE以及Audacity。
PCM與8K8-bit單音效應用

This tutorial explains how to do simple playback of short (~4 second), low-bitrate (8 KHz) audio samples from Arduino using only a speaker. 國外已經有這樣做PCM手法的Arduino應用( PCMAudio),這要感謝 Michael Smith 無私的奉獻,

器材準備與組裝:

拍手音樂盒主要用到下列器材:
  • Arduino Uno 或 Duemilanove 控制板
  • 麥克風模組(含放大器)
  • 連接Arduino與電腦之USB線
  • 8Ω小喇叭
拍手音樂盒組裝方面,首先將小喇叭兩條線接在Arduino板的 pin 3 埠和 GND 上,並將麥克風模組的供電腳與接地腳,分別接在 Arduino 板上的 5V 和 GND 上,之外,切記把麥克風模組的類比訊號輸出腳(注意!不是數位訊號輸出腳)接在Arduino板的pin (A0)上,再用USB線將 Arduino 與電腦連接起來,就這樣簡單,組裝工程就大功告成了。

拍手音樂盒工作原理介紹:

【拍手音樂盒】的運作方式,是由一個拍手有效輸入信號,來激發輸出聲音。這裡會分別談到此實作的輸出入運作情形。首先在輸入方面,我們運用Arduino具有的類比輸入功能,也就是在其pin (A0)腳位連接上麥克風模組的類比訊號輸出腳,並設定一個啟動門檻,當麥克風模組偵測我們的拍手聲音超過此門檻時,就會啟動播放預先錄製的音效。至於是如何輸出音效的呢?為了播放取樣率為 8KHz 的聲音,同時用了 Timer1 和 Timer2,Timer1 負責每秒產生 8000 次中斷(即 8KHz 的義思),也就是每隔 125μs (>即 8KHz 換算成週期的義思)輸出 PCM 採樣值,而 Timer2 則負責將音效採樣數值資料以 PWM 方式送出信號到pin 3 埠,再傳給喇叭發聲。

拍手音樂盒音效PCM技術介紹:

【PCM是指將真實樂器聲音進行實地採集後,利用採集的數據合成音樂的音源模式。它以能真實表現豐富的音色見長。也叫wavetable音源。 PCM(Pulse Code Modulation) 脈波編碼調製是將聲音信號數字化的最常用的模式。 編碼技術首推脈波碼調變(PCM),而影響PCM執行效能有二個主要因素,一是取樣率(Sampling Rate),另一個是取樣位元數(Sample Bit),動作原理是依據定義的取樣率,可以決定每隔多少時間要取得一次聲音資料,然後將此類此資料依定義的取樣位元數轉換成數位資料儲存起來,就完成了 一次編碼的動作。 PCM(Pulse Code Modulation)合成:PCM與FM合成最大的不同點,在於PCM不是使用震盪器或載波器來產生聲音,而是直接錄下各種樂器的部份音色,然後以儀器 加以分析演算,使之成為一組數位資料,儲存在ROM(唯讀記憶體)中。等到使用再把資料取出,透過機器將它轉化成為原來的聲音。 現代的電子琴一般使用PCM採樣音源。所謂採樣就是錄製樂器的聲音,將其數位化後存入ROM或FLASH裡,然後按下鍵時CPU或DSP晶片重播該音。甚至有一些高級編曲鍵盤可以使用外置採樣(比如Tyros 3的硬碟音色)。現代電子琴並非“模仿”樂器音色。它使用的就是真實樂器音色 PCM方式是由取樣,量化和編碼三個基本環節完成的。她的工作原理是這樣的:採集聲音源在最有特點的音域發出的幾個音,然後再對所記錄下來的聲音的音高、產生和衰減時間、上升率、衰減率進行調整,把調節好的聲音按音區分配給鍵盤從而達到逼真的還原採樣前的聲音效果。 音源參數有採樣頻率,量化精度和波形容量,以及最大複音數幾個重要的參數。如果讀者需要更多詳情,請點擊維基百科的脈衝編碼調變

物件導向設計拍手音樂盒底層硬體運作概要:

本次演示的 PCM 應用場景是為了播放 8KHz 的單聲道音效,音效發聲程式同時用了 Timer1 和 Timer2 兩個計時器協同運作,其中 Timer1 負責每秒產生 8000 次中斷,並於每次中斷服務裡逐次切換下一個要交給 Timer2 播放的 PCM 八位元採樣值,而 Timer2 則專門負責將Timer1 定時中斷服務遞交的 PCM 八位元取樣資料以 PWM 方式送出給喇叭發聲。這裡面的硬體運作核心之一會用到硬體 Timer1 計時器CTC模式下的定時中斷服務,有關Timer1 計時器CTC模式的運作方式有兩種做法,一種是以 ICR1 暫存器儲存TOP,當Timer1 計數器 TCNT1 數到這個 TOP 最高值時,本身會歸零同時引發硬體中斷並將執行權交給引發ISR(TIMER1_OVF_vect),有名的 TimerOne 程式庫就是採此模式;一種是以 ORC1A 暫存器儲存 TOP 值,當Timer1 計數器 TCNT1 數到預定最高值 TOP(也就是剛剛在 OCR1A 的設定值),本身會歸零同時引發硬體中斷並將執行權交給ISR(TIMER1_COMPA_vect)中斷服務,本人開發的CltTimer1CTC程式庫是屬於此模式,可以補充 TimerOne 程式庫的不足。至於另一個硬體運作核心,就是將Timer2設為八位元快速PWM輸出,並得以從Timer1定時呼叫中斷服務裡設定Timer2其PWM輸出的佔空比(也就是 PCM 八位元取樣資料),這樣硬體就能順利執行音效輸出。

下載拍手音樂盒物件導向設計範例程式模組與安裝:

要手動安裝拍手音樂盒程式與程式庫,首先關閉 Arduino 開發環境。然後點擊這裡提供的GitHub下載連結處:arduino-KISS-drivers-libraries-master.zip,下載成功後,接著對剛剛所下載包含相關應用程式與程式庫的 zip 檔案進行解壓縮,待解壓縮完成後,其中有兩個相關資料夾至關重要,再來就是針對這兩個資料夾進行下列安裝步驟:
  1. [複製拍手音樂盒所有程式放到草稿碼簿的資料夾]將解壓縮完整資料夾所屬 “arduino-KISS-drivers-libraries-master\PCM-Timer1tick-Timer2audio\” 資料夾底下的 “CltTimer1CTC-06PCMTinkler” 資料夾所有內容(包含此資料夾)整個複製放到 Arduino 草稿碼簿的資料夾(sketchbook folder),也就是 “My Documents\Arduino\” 資料夾內(若不清楚,可以在 Arduino 開發環境主功能表上點擊【檔案】→【偏好設定】,就能找到草稿碼簿的位置)。
  2. [檢視本次示範拍手音樂盒的主程式] CltTimer1CTC-06PCMTinkler.ino 是否存在,如有問題,需仔細重做第一步驟。
  3. [檢視本次示範拍手音樂盒的Timer2類別檔] CltTimer1CTC-06PCMTimer2Class.h 是否存在,如有問題,需仔細重做第一步驟。
  4. [檢視本次示範拍手音樂盒的音效數位檔] CltTimer1CTC-06PCMTinklerData.h 是否存在,如有問題,需仔細重做第一步驟。
  5. [複製筆者極簡開發的Timer1程式庫放到libraries資料夾] 接下來,將解壓縮完整資料夾所屬 “arduino-KISS-drivers-libraries-master\Timer1CTCmode\” 資料夾底下的 “CltTimer1CTC” 資料夾所有內容(包含此資料夾)整個複製放到草稿碼簿的 “libraries” 資料夾內。把程式庫安裝妥當之後,在 Windows 系統檔案管理下開啟該程式庫資料夾,應可看到下列包含重要檔案的資料夾結構:
    • Arduino\
      • libraries\
        • CltTimer1CTC\examples
        • CltTimer1CTC\CltTimer1CTC.cpp
        • CltTimer1CTC\CltTimer1CTC.h
        • CltTimer1CTC\keywords.txt

主程式重要功能說明:

The library only has two functions: startPlayback() and stopPlayback(). The first takes two arguments: the array of audio samples and its length. For example: startPlayback(sample, sizeof(sample));

The stopPlayback() function doesn’t take any arguments and will stop playback of the current sample.

Note that the example also uses a couple of unusual Arduino constructions. First, the sample[]array is declared using the keyword PROGMEM, which causes the data to be stored in the Arduino’s program memory (Flash) instead of its RAM (which is much smaller). It also uses the sizeof() function, which returns the number of bytes used by an array.函式庫是以 zip 檔或資料夾型式來發佈的。資料夾名稱即為程式庫名稱。資料夾內通常包含 .cpp檔、.h 檔、keywords.txt 檔、範例資料夾以及其他函式庫需要的檔案。有兩個相關資料夾 Now quit the Arduino IDE and reopen it.

,需要將 DuinoParty 資料夾放入特定資料夾內。在 Windows 系統,須放入 ”My Documents\86Duino\libraries” 資料夾內。在 Mac 系統,須放入 ”Documents/86Duino/libraries” 資料夾內。在 Linux 系統,須Now you should be able to go open all the examples codes by navigating to "File>Examples>USB_Host_Shield_20" and then select the example you will like to open.

再來解壓縮包含函式庫的 zip 檔案。例如:若要安裝的程式庫稱為 “DuinoParty”,解壓縮後資料夾應該是DuinoParty,內部應包含DuinoParty.cpp以及DuinoParty.h檔。(若.cpp與 .h 檔不在資料夾內,則必須自行建立。以上面為例,此時使用者必須建立DuinoParty.cpp與DuinoParty.h。)

上傳範例並加以執行:

在先前已成功安裝了下載範例情況下,首先開啟 Arduino 開發環境,然後在其主功能表上點擊【檔案】→【草稿碼簿】→【CltTimer1CTC-06PCMTinkler】,接著執行上傳動作,這要給 Arduino 一些時間,因為音效資料較大。當 Arduino 接收完畢重新啟動後,並不會發出任何聲音,當我們靠近麥克風模組拍手時,Arduino偵測到足夠大聲響後會自動播放預先錄製的音效,【拍手音樂盒】會發出很小聲的“這是鄧崇林的測試音效"。當Arduino直接推送喇叭播放聲音,第一個會遇到的問題就是 “聲音太小”。這時可使用簡單的NPN電晶體(例如BC546/BC548B)來放大電流達到加大音量的效果。從本次實作經驗來看,由於Arduino Uno其Flash Memory受到 32 KB大小的限制,當存放約三秒左右的音訊時,程式編譯之後用了25KB(77%),至於存放大約四秒左右的音訊,編譯之後用了31KB左右,這四秒音訊大概就是上限了。

如何錄製自己特有的音效:

To encode your own audio samples,PCM與8K8-bit單音效應用 you’ll first need to down-sample the audio to 8 KHz, 8-bit mono sound, then convert it to a series of numbers that can be pasted into your Arduino program. Note that you’re only going to be able to store approximately 4 seconds of audio on the Arduino, so you might want to trim your clip first (e.g. using Quicktime).

用Audacity來轉換成這樣的格式,只是在這裡有兩個重要技巧:一是更改歌曲取樣頻率時(比如說從44.1kHz -> 8KHz),要改的是專案的取樣頻率而非音軌的取樣頻率,如果改了音軌的取樣頻率,音樂速度會變得更快。第二是Stereo改Mono時,功能在音軌最左方的下拉選單裡。One easy way to down-sample the audio is with iTunes. First, Import your original sample into iTunes. Then open the preferences dialog and, on the general tab, click “Import Settings…”. From there, select “Custom” from the “Setting” drop-down. Inside the custom settings, select “Stereo Bit Rate” of 16 KHz, a “Sample Rate” of 8 KHz, and Mono “Channels”. 

To convert the down-sampled audio file to numeric values you can paste into your Arduino program, you can use the EncodeAudio application. This is a simple Processing program (source code on GitHub) that reads an audio file and copies its audio data to the clipboard in numeric form.

A.下載所需輔助工具:

Unzip and run the application. It should prompt you for an audio file to encode. Select the new mp3 file you created with iTunes (you can locate it by right-clicking it within iTunes and selecting “Show in Finder”). The EncodeAudio application will convert it to numeric values and then copy them to the clipboard. It may take a few seconds. A dialog will appear notifying you whether or not the encoding was successful.

  • 問題:
  • 如何一般錄製的立體音效轉成8khz, 8bit Mono WAV file?? 再從8khz, 8bit Mono WAV 檔轉成數位資料檔?? >以上是許多網頁裡的思路,因為大家電腦所用的作業系統是微軟視窗,自然以其方便錄製的WAV為考量對象, >但是Win10裡的"語音錄音機"所錄製的檔案,卻是"M4A"檔,這下麻煩大了,很多音效編輯軟體都無法直接匯入它,(例如) >顯然"語音錄音機"已經無法提供簡便的幫助,得另行想辦法
    [01-微軟Win10視窗提供的語音錄音機.JPG]
  • 8K8-bit單聲音頻採集-Apple:
  • 由於Win10沒有可供音效編輯的iTunes工具,於是借用前面介紹的免費聲音編輯軟體Audacity工具,然而操作原理大體上還是以此網頁文章為準
    1. 錄音並經裁剪:
    2. 心動如行動,馬上跟著步驟往下做吧!做中學必有收穫。請啟動Audacity軟體並點擊主功能表列下面的錄製,停止以及播放鍵。
    3. 設定專案頻率與重新取樣選單:
    4. [重新取樣][再以設好要建重新取樣]Audacity[軌道]有一個“重新取樣”的功能可以幫助我們將音效檔占更少的容量。在左下角改變聲音的項目取樣速率,從44000改到8000。在作業畫面左下角之"專案頻率(赫茲)"下拉式選單裡挑選"8000"這個選項
      [02-設定專案頻率與重新取樣選單.JPG]
    5. 重新取樣設定:
    6. [填入新的重新取樣 8000],然後點擊功能表列的軌道,選重採樣,並且點擊確定。?由於前頭已經在左下角改變聲音的項目取樣速率,從44000改到8000。 [03A對話盒.JPG]
    7. 檢視重新取樣效果:
    8. [03B原波形馬上瘦身.JPG]
    9. 設定單聲道:
    10. 於主選單禮點擊[軌道](Track)→[立體聲軌道轉為單聲道](Stereo Track to Mono).
      [04-單聲道選項.JPG]
    11. 正規化選單:
    12. 由於Arduino的聲音很小,所以我們選擇功能表列"效果"裡的"正規化",使聲音變的更大聲。 [05-效果正規化.JPG]
    13. 正規化預設值:
    14. [06-正規化前預設值.JPG]
    15. 正規化設db值:
    16. 將正規化最大化振幅調為0.0 db。 [07-正規化設db值為0.JPG]
    17. 觀察原先未經正規化的波形:
    18. 原先未經正規化的波形如下: [08-原先未經正規化裁剪錄音.JPG]
    19. 觀察正規化後的波形:
    20. 經過正規化處理後的波形如下: [09-正規化後觀察波形果然振幅放大許多.JPG]
    21. 匯出音訊選單:
    22. 接下來,選擇你要存儲的聲音片段並且選擇"檔案" →"匯出音訊"選擇的音訊。
      [10-檔案-匯出音訊做選擇.JPG]
    23. 挑選音效檔案儲存格式:
    24. +4>在"存檔類型"欄位裡頭挑選 [AIFF(Apple) signed 16-bit PCM],緊接著在"檔案名稱"欄位裡輸入自訂的檔名文字後直接點擊"存檔"
      "檔案名稱"AppleLike, "存檔類型"欄位裡頭挑選 [AIFF(Apple) signed 16-bit PCM] [11A-AppleLike.JPG]
    25. 直接跳過編輯後設資料標籤:
    26. 馬上會出現"編輯後設資料標籤"對話盒,直接點擊"確定",就能成功完成將Apple 8K 8-bit單聲音檔的錄製
      [12-編輯後設資料標籤.JPG]
    27. 執行去音效檔表頭兼轉換數位數據工具:
    28. 用檔案總管到先前儲存Apple聲音檔的資料夾裡,就可看到以".aiff"為檔型的聲音檔,互動式程式是以Processing的形式展現的,所以我們需要Java。接著利用此網頁提供的 EncodeAudio.exe 工具(要先下載並解壓縮),直接執行該工具再按照畫面指示操作即可
      <(工具源碼開放, 已下載)damellis/EncodeAudio>>https://github.com/damellis/EncodeAudio
      運行“EndoAudio”,這個程式僅僅要求你選擇剛匯出的wav檔。 [13-執行Processing程式.JPG]
    29. a
    30. [14-數位陣列轉換成功並複製於剪貼簿(clipboard)裡只要在任何文件貼上即可.JPG]
      接下來,我們就可以打開Arduino編輯程式,在畫面中,在適當陣列的地方貼上剛剛所複製的聲音數位資料並儲存檔。 const unsigned char sounddataPGM[] PROGMEM 陣列顯示的是本次示範的聲音數位數據,此時有了自訂的聲音數據,也就是剛剛用Encode Audio裡得出的聲音數位數據資料來替換。此做法很直覺,只要選取(塗黑)-CltTimer1CTC-06PCMTinklerData.h 裡的整條數位資料(數以千計的資料),然後control-V粘貼你自己剛剛自訂的聲音。
      [15-CltTimer1CTC-06PCMTinklerData.h.JPG]
  • 8K8-bit單聲音頻採集-Microsoft
  • 由於Win10沒有可供音效編輯的iTunes工具,於是借用前面介紹的免費聲音編輯軟體Audacity工具,然而操作原理大體上還是以此網頁文章為準
    1. 錄音並經裁剪:同前面操作。
    2. 設定專案頻率與重新取樣選單:首先設定專案頻率,操作方式如同前面所述。又,由於有了前述改變音軌取樣頻率的使用經驗,這會讓音效速度聽起來變得較快且更加不平順,因此重新取樣動作就此省略不做,以避免音效呈現更加糟糕,所以結論是:取樣頻率操作要改的是專案頻率的設定,而非音軌的重新取樣頻率。
    3. 設定單聲道:同前面操作。
    4. 正規化選單:同前面操作。
    5. 正規化設db值:同前面操作。
    6. 匯出音訊選單:同前面操作。
    7. [11B看到之前存的AIFF型檔案.JPG]
    8. 挑選音效檔案儲存格式:
    9. 在匯出菜單裡,應用軟體提供我們改變音效檔案儲存格式的機會,"存檔類型"通常有MP3, WAV, M4A等等諸多選項,這裡將和前面不一樣,我們在"存檔類型"欄位裡頭要選擇"其他非壓縮音格式檔案",然後點擊選項,檔頭為WAV(microsoft),編碼為Unsigned 8-bit PCM,緊接著在"檔案名稱"欄位裡輸入自訂的檔名文字後直接點擊"存檔"。操作畫面,將如下圖所示:
      [11C新的檔案型態選定.JPG]
    10. 直接跳過編輯後設資料標籤:同前面操作。
    11. 執行去音效檔表頭兼轉換數位數據工具:同前面操作。
    12. 運行“EndoAudio”,這個程式僅僅要求你選擇剛匯出的wav檔。
    13. 數位陣列轉換成功並複製於剪貼簿(clipboard)裡只要在任何文件貼上即可.同前
    14. 接下來,我們就可以打開Arduino並儲存檔。 +8>在Arduino編輯程式畫面中,在適當陣列的地方貼上剛剛所複製的聲音數位資料,同前
  • 程式一 [前面
  • 程式二
  • 程式三
  • 拍手音樂盒測試
  • 開關啟動音樂盒測試
  • 進階應用 - 讓鬧鐘能夠定時觸發Arduino的音樂

如何自訂開關啟動音樂盒的推廣應用:

拍手音樂盒主要用到下列器材:下列代碼用booleans來在被觸碰時播放不同的聲音。 這個教程包含的是我們做的鬼嚎聲,所以你可以上傳這個,並且自己嘗試。 簡單觸發器 硬體接線部分,小喇叭接法保持不變,並卸除麥克風模組,然後在pin 3埠和GND上,triggerPin接在A0和5V上。。 軟體搭配調整部分,只要在兩處用解除註解的封印以及追加另一個註解封印即可,不用再撰寫任何一行程式碼就搞定了。 首先第一處在setup()裡解除對triggerPin註解的封印,就恢復了pinMode()將triggerPin連上內部提升電阻的功能。 接著第二處在loop()裡解除對triggerPin註解的封印,並對麥克風模組的輸入門檻偵測程式碼進行註解封印。 下面是用於按鍵式開關之類的應用場合的最終程式碼形式: [19-解除註解的封印.JPG]
  • Arduino Uno 或 Duemilanove 控制板
  • 麥克風模組(含放大器)
  • 連接Arduino與電腦之USB線
  • 8Ω小喇叭
Comments