【小程序】C语言实现简易钢琴-利用sin函数构造不同频率波形模拟各琴键发音
根據鋼琴音調頻率對照表,使用sin函數構造對應頻率正弦波數據模擬各琴鍵聲音,實現簡易鋼琴效果,結果寫入wav文件中。
目錄
- 程序效果
- 實現過程
- 樣例代碼
- 測試用例
- 參考資料
程序效果
截圖1:鍵位圖 鋼琴鍵盤結構,包含3組Do Re Mi Fa So La Xi以及空格靜音代表的空拍,使用字符'z'結束。
截圖2:使用效果-歡樂頌 輸入音符后,使用'z'回車即可結束錄入,生成的文件位于D盤根目錄下,播放即可。
實現過程
截圖3:流程圖
主要流程如上,需要注意的細節有以下幾處:
0.每秒44100采樣時,一個音符想要延續0.5秒左右就需要一個長度為22050的數組構造正弦波,不現實,采用s[1000]數組構造正弦波,使用for循環重復至30000左右。
1.使用有限長度數組構造正弦波,由于Π為無理數,在實際計算數值時,很難取到完整周期的分界點。
截圖4:不連續現象
分界點選取間隔不大時,人耳聽不出明顯的噪音。
2.每個音符末尾需要插入一小段短暫靜音,否則連續2各相同音會聽成一個長音。
截圖5:單音末尾靜音
3.空拍使用完整靜音
截圖6:空拍的靜音
樣例代碼
1.共享鏈接:C語言實現簡易鋼琴-利用sin函數構造不同頻率波形模擬各琴鍵發音
https://download.csdn.net/download/u013025955/11174606
2.關鍵代碼
//鋼琴鍵盤結構,包含3組Do Re Mi Fa So La Xi以及空格靜音代表的空拍 struct MusicNote {char noteName; //音符名稱int frequence; //音符頻率,根據鋼琴音高頻率對照表定義DWORD noteLength; //在使用sin函數構造正弦波信號的單個音實際字節長度,用于計算總長度,填寫在wav文件頭部,同時該長度讓每個音能延續0.5秒左右,由nearZero*4*2*40算出,可以自定義時長,只要是nearZero的整數倍都行DWORD nearZero; //在使用sin函數構造正弦波信號時,不同頻率采樣值最接近完整周期的數據點,避免取不到完整周期導致雜音出現 }note[NOTENUM] = {{'a', 130, 108800, 680}, {'q', 261, 81600, 170}, {'1', 523, 80960, 253},{'s', 146, 72640, 908}, {'w', 293, 60320, 754}, {'2', 587, 84320, 527},{'d', 164, 86400, 270}, {'e', 329, 75200, 940}, {'3', 659, 69680, 871},{'f', 174, 40460, 508}, {'r', 349, 101280, 633}, {'4', 698, 55680, 696},{'g', 195, 72480, 906}, {'t', 391, 90400, 565}, {'5', 784, 72320, 226},{'h', 220, 64320, 402}, {'y', 440, 64320, 402}, {'6', 880, 68240, 853},{'j', 246, 86240, 539}, {'u', 493, 78800, 985}, {'7', 988, 78720, 492},{' ', 0, 80000, 1000} };//正弦波生成函數 void sin_sound(WORD *p, int n, int f) {int i;double x, temp1;x = 2*PI*f/44100; //2Πf即可獲得對應頻率波形,44100為音頻文件頭定義的采樣率,也需要考慮進去for (i=0; i<n; i++) //n的值通過本地測試21次,分別確定的,確定方法為查看正弦函數值從負數變成整數,經過x軸時最接近0的點,即最接近完整周期的點{temp1 = 5000 * sin(x*i);p[i] = (WORD)temp1;} }測試用例
截圖7:測試用例
參考資料
1.利用正弦波產生WAV文件
https://download.csdn.net/download/guo19910426/5697181
2.鋼琴的音高與頻率對照表
https://max.book118.com/html/2016/0314/37632175.shtm
總結
以上是生活随笔為你收集整理的【小程序】C语言实现简易钢琴-利用sin函数构造不同频率波形模拟各琴键发音的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java行业认知报告_大学生专业认知报告
- 下一篇: KMP算法next数组构建形式(几种常见