
Photo from theglassdesk from Pixabay
學c++感覺好像很厲害,但我現在連字串印出都有問題…
我要學到什時候才有能力可以寫出一個有gui的程式呢?
想到這邊突然覺得孤單、寂寞、覺得冷
其實現在寫到一個像樣的程式,花的時間可能比你想像中的要短
因為現在大部份軟體都已經發展出所謂 application framework (wiki)
由於近來程式發展到大部分都有所謂的圖形化界面 (gui),而在早期對程式開發者其實是不小的負擔,因為他們必須學習如何使用圖像化函式庫語法,甚至還要自己處理因使用圖像化函式庫產生的臭蟲,但現在application framework 就提供了常用的gui基本架構,透過一些簡單的設定,開發者就可以產生出符合他們需求的gui 架構,並開始在上面開發軟體。
這次就來介紹一個跟c++有關的application framework,他可以讓你在不更改code的情況下,產生出可在不同平台上運行的程式(cross platform)甚至是手機app,聽起來超棒的對吧
,他的名字就是JUCE
JUCE 原先是由 Jules Storer 為了開發 數位音樂工作站 (daw) 所寫的,所以現在常見使用JUCE開發的程式都是有gui的音樂相關軟體或是插件
https://juce.com/discover/stories?tags=made%20with%20juce
JUCE 官網也很貼心準備了一些新手練功的教學 還有專案檔(真是佛心來的
)
這邊也來和大家分享如何在Debian 上玩JUCE
0. Projuicer - JUCE 專案管理軟體安裝
在JUCE官網選擇personal 然後下載=> 根據你目前使用的OS 下載對應的JUCE library
下載解壓縮後可以在JUCE資料夾裡發現2個可執行檔
1.Projucer (之後會常用的JUCE專案管理軟體)
2.Demorunner (示範使用JUCE可以寫出哪些程式,同時提供code給開發者參考)
如何開啟Projucer ?
1.滑鼠雙擊 (不知為何小編無法以此方式開啟程式)
2.在console 移到 Projucer所在的資料夾並執行
./Projucer

如果有發生找不到package問題可以到這邊找找是否以下package皆有安裝
https://packages.debian.org/source/stretch/juce
1. 開發者帳號申請
這邊JUCE提供兩種選擇
1. 申請帳號
2. 修改原始碼重新compile以藉此跳過帳號登入畫面
如果使用2.的同學要注意使用規範(似乎是修改之後就代表你已同意遵守GPL規範)
依照流程申請好後登入就可以來正式進入JUCE開發畫面了


這邊細節小編也還不是很了解,有興趣的同學可以到官網tutorial 研究一番
從這裡開始 https://docs.juce.com/master/tutorial_new_projucer_project.html
或是直接看各種不同project 如何選擇 https://docs.juce.com/master/tutorial_choosing_projucer_template.html
2. 新手練功 : 開啟現有project
我們現在就選一個來試試看吧(tutorial sine synth 找到zip 下載)並解壓縮
然後開啟我們的Projucer 從工具列選到File -> Open 找到我們剛剛下載的 SineSynthTutorial.jucer
應該可以看到以下畫面

接著我們來設定global path :從工具列選到File -> Global Path...
這邊我們先把上面選單改成Linux,設定對應函式庫路徑請按 ... 進行設定
請注意,至少Path to JUCE 以及 JUCE Modules 路徑位置要設定正確 (設定為應為白字,而非紅字)
這邊請設定好Global Path 否則在後續執行 make 會發生library 找不到的問題發生

設定完後,來看Projucer如何產生我們的makefile
選擇左邊sidebar的exporters後在點選右下角的 (+) 新增Linux makefile
小編是已經新增過了,所以截圖中才會已經存在linux makefile在左側列表

最後File->Save Project 就完成了 (在project/Builds/LinuxMakefile)
超方便對吧 看到落落長的Makefile就開始慶幸還好我不用從0開始寫

開始編譯,直接執行
make
然後就是
./build/SineSynthTutorial
編譯完的檔名會因為project而異,請確認後再執行
完成了,接上耳機按下滑鼠,開始試玩我們的第一個新手作品 - 正弦波產生器

3. 新手村第一個任務解析:sine wave synthesizer
這邊我們就直接拿synth 練習教學來玩,像這種方便修改可以很快獲得回饋的程式對初學者來說無疑是練功神器。
在進入之前來小小科普何謂synthesizer (wiki:合成器)
合成器是一種以電子方式產生聲音,早期常用來模擬現有樂器,到現在用來產生全新的音色,目前常見於流行樂曲,電影配樂中。
而在合成器常用的基礎元件有︰振盪器 (oscillator),濾波器(filter) , 封包(envelope) ,低頻振盪器(low frequency oscillator) 還有噪音產生器(noise)。合成器產生的聲音就是由振盪器發出聲音再透過不同的濾波器,封包調整,調整程度可以在透過低頻振盪器調整,最後將多個振盪器發出的聲音透過不同程度的混合就可以發出新的聲音。詳細介紹可以看這邊 Digilog - [教學] 合成器入門教學 – 總複習
今天要介紹的是sine wave產生(tutorial sine synth 找到zip 下載),sine wave是合成器中常見的基本波形,其他還有saw wave(鋸齒波) , triangle wave(三角波), square wave(方波)。
原始教學中是使用std::sin 有興趣的同學可以自行修改成其他波型
Medium -Part 2. Basic sound waves with C++ and JUCE
Stack overflow - Is there a one-line function that generates a triangle wave?
這邊實做細節就不多談,留給有興趣的同學自行探索
這邊就畫張簡單的圖協助大家理解實做大致流程

小編自己作的示意圖,不要鞭太兇
1. 建立slider控制volume 以及 frequency
文章中有提到如何設定
1. slider最大、最小值設定 setRange (min, max);
2. 特定動作觸發函式執行 (XXX.onValueChange)
2. 如何平順的遞增、遞減slider值並影響結果
頻率︰請參考 if (targetFrequency != currentFrequency) 段落
音量︰bufferToFill.buffer->applyGainRamp (...)
3. sine wave 產生
這邊是使用 std::sin 函數作計算
計算 currentSample = (float) std::sin (currentAngle);
更新 currentAngle =currentAngle + angleDelta;
更新 angleDelta :updateAngleDelta()
如果你覺得這個sine wave的寫法無法理解 試試看著這張圖 或許你就能理解為何這樣能產生sine wave
wikipedia : sine wave
把裡面每一個綠色的點都想成currentSample,是不是豁然開朗了呢?
4. 聲音播放
getNextAudioBlock() / prepareToPlay() / releaseResources() 這三個主要和聲音播放有關
詳細請看這裡的 Processing the audio 部份介紹
有興趣的大家也去下載其他教學project下來,依照上面的步驟試試看吧。
如果你想挑戰一點刺激的,試試下面的題目吧
Using rtmidi send midi signal when keystroke detected and interact with midi synthesizer made with juce
簡單描述期望結果,就是按鍵盤按鈕可以讓 JUCE midi synthesizer 有反應並發出聲音
參考資料︰
RTmidi library (可以將按鍵轉換成midi訊號)
Tutorial synth using midi input (用JUCE作的接收midi 訊號的合成器)