国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

程序 + 音樂: 我的自由鋼琴開發歷程

鄒立鵬 / 961人閱讀

摘要:原文鏈接最近用做了一款鋼琴類應用,名字定為自由鋼琴,人生如音樂,歡快且自由。就類似于多年前開發的鋼琴游戲,自由鋼琴只是換了的技術,同時支持了鋼琴曲的自動播放功能。目前采用的技術架構是框架。

原文鏈接

Hate 996? Come Here & Relax~

最近用Vue + Tone.js做了一款鋼琴類web應用,名字定為自由鋼琴(AutoPiano),人生如音樂,歡快且自由。

此文權當作該項目的總結和分享~

項目簡介

自由鋼琴(AutoPiano)是利用HTML5技術開發的在線鋼琴應用,致力于為鋼琴愛好者、音樂愛好者以及其他所有的創造者提供一個優雅、簡潔的平臺,在學習工作之余可以享受鋼琴、音樂的美好。就類似于多年前Flash開發的鋼琴游戲,自由鋼琴只是換了H5的技術,同時支持了鋼琴曲的自動播放功能。

AutoPiano支持鍵盤按鍵和鼠標點擊播放,同時琴鍵上會有按鍵和音名提示。另外,AutoPiano還有教學的功能,一種方式是快速入門,通過簡易的譜子按鍵進行演奏,另一種是演奏示例,通過鋼琴曲的自動播放來達到演示的目的。目前這兩個功能都在持續完善中,如下圖所示:

體驗地址: http://crystalworld.gitee.io/...

項目地址: https://github.com/WarpPrism/...

開發這樣的應用需要樂理知識嗎?

當然。基本的樂理知識還是要知道的,比如 CDEFGAB 音名、五線譜、調式、節奏等等還是要懂一點的。篇幅所限,這里就不展開討論了,推薦兩個網站:

https://www.bilibili.com/vide...

https://www.cnblogs.com/devym...

其他的就是編程知識了,以及如何將樂理知識轉化為程序邏輯。AutoPiano目前采用的技術架構是vue框架 + tone.js。

鋼琴界面效果是怎么寫的?

可以用CSS或貼圖。筆者這里直接用css實現了,考慮到鋼琴有黑鍵和白鍵,且黑鍵和白鍵有序地排列成 7:5的模式,所以實現起來并不復雜。

= 36 && note.id <= 40" @click="clickPianoKey($event, note.keyCode)">
.piano-wrap { width: 90%; margin: 20px auto;
  .piano-key-wrap {
    width: 100%;
    background: @dark;
    overflow: hidden;
    position: relative;
    .wkey {
      display: inline-block;
      width: 2.775%;
      height: 100%;
      margin: 0 auto;
      background: linear-gradient(white 10%, rgb(251, 251, 251) 92%, rgb(220, 220, 220) 93%, white 97%);
      border: solid 1px @dark;
      border-radius: 0 0 5px 5px;
      position: relative;
      &:active {
        background: linear-gradient(#eee 10%, #ffffd 60%, #bbb 93%, #ccc 97%);
      }
    }
    .wkey-active {
      background: linear-gradient(#eee 10%, #ffffd 60%, #bbb 93%, #ccc 97%);
    }
    .bkey-wrap {
      width: 20%;
      height: 0;
      position: absolute;
      top: 0;
    }
    .bkey-wrap1 {left: 0;}
    .bkey-wrap2 {left: 19.5%;}
    .bkey-wrap3 {left: 39%;}
    .bkey-wrap4 {left: 58.3%;}
    .bkey-wrap5 {left: 77.7%;}
    .bkey {
      display: inline-block;
      width: 10%;
      height: 70%;
      background: linear-gradient(#000 10%, rgb(86, 86, 86) 85%, #000 90%);
      border-radius: 0 0 3px 3px;
      position: absolute;
      top: 0;
      overflow: hidden;
      &:active {
        background: linear-gradient(rgb(86, 86, 86) 10%, #000 90%, #222 100%);
      }
    }
    .bkey-active {
      background: linear-gradient(rgb(86, 86, 86) 10%, #000 90%, #222 100%);
    }
    .bkey:nth-child(1) {left: 9%;}
    .bkey:nth-child(2) {left: 23%;}
    .bkey:nth-child(3) {left: 50%;}
    .bkey:nth-child(4) {left: 65%;}
    .bkey:nth-child(5) {left: 79%;}
  }
}

codepen上也有很多這樣的例子供參考,不一定采用上述實現:

https://codepen.io/search/pen...

相信只要合理地控制css變量和數值,大家能做出更好的 Piano 界面。

如何實現單個音符的播放?

實現音頻播放,最簡單的就是利用HTML5 中的 audio 標簽,通過觸發audio的play和pause方法,實現對音頻的控制,筆者一開始就是這么實現的。

// 
// //
// 預先為每個音符都建立一個audio元素 initAudioDom() { var vm = this for (let i = 0; i< vm.Notes.length; i++) { var note = vm.Notes[i] $(".audios-wrap").append(`

上述是我的第一種實現方式,即不同音符觸發不同audio的播放。之后也許是出于好奇,嘗試了 Tone.js,通過Tone.js + 內置采樣器實現對音頻播放更有效的控制,當然,其提供的很多復雜功能都還沒用上。。。

// 初始化合成器
this.synth = SmapleLibrary.load({
  instruments: "piano"
}).toMaster()

// 合成器觸發音頻釋放
playNote(notename = "C4", duration = "2n") {
  if (!this.synth) return
  this.synth.triggerAttackRelease(notename, duration);
}

嗯,現在的代碼就符合音樂美學和代碼美學了,美滋滋。當然筆者也期望Tone.js能快點完善中文文檔,不然上手還是很吃力的,感興趣的小伙伴可以先去其官網研究一番。

關于鋼琴曲的自動播放

這一部分應該是開發整個應用最難的地方了,因為音樂或者說樂譜本身是相當復雜的,根據百度百科的描述,五線譜起源于希臘,歷經上千年不斷完善才成為現在的樂譜標準。而簡譜的出現則要晚的多,但依然五臟俱全,可以說,簡譜也不簡單。

筆者的實現思路是,以一種樂譜格式為載體,將樂譜轉換為一種程序可識別的格式,然后導入到程序中進行播放,這種可識別格式如下所示,也是目前所采用的:

  {
    name: "小星星",
    step: "C",
    speed: "100",
    playState: "",
    mainTrack: ["1(1)"," 1(1)"," 5(1)"," 5(1)"," 6(1)"," 6(1)"," 5(2)"," 4(1)"," 4(1)"," 3(1)"," 3(1)"," 2(1)"," 2(1)"," 1(2)"," 5(1)"," 5(1)"," 4(1)"," 4(1)"," 3(1)"," 3(1)"," 2(2)"," 5(1)"," 5(1)"," 4(1)"," 4(1)"," 3(1)"," 3(1)"," 2(2)"," 1(1)"," 1(1)"," 5(1)"," 5(1)"," 6(1)"," 6(1)"," 5(2)"," 4(1)"," 4(1)"," 3(1)"," 3(1)"," 2(1)"," 2(1)"," 1(2)",
                "1<(1)", "1<(1)", "5<(1)", "5<(1)", "6<(1)", "6<(1)", "5<(2)", "4<(1)", "4<(1)", "3<(1)", "3<(1)", "2<(1)", "2<(1)", "1<(2)", "5<(1)", "5<(1)", "4<(1)", "4<(1)", "3<(1)", "3<(1)", "2<(2)", "5<(1)", "5<(1)", "4<(1)", "4<(1)", "3<(1)", "3<(1)", "2<(2)", "1<(1)", "1<(1)", "5<(1)", "5<(1)", "6<(1)", "6<(1)", "5<(2)", "4<(1)", "4<(1)", "3<(1)", "3<(1)", "2<(1)", "2<(1)", "1<(2)"],
    backingTrack: ["1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "1>(0.5)", "6>(0.5)", "4>(0.5)", "6>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "1>(0.5)", "6>(0.5)", "4>(0.5)", "6>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "7>>(0.5)", "5>(0.5)", "2>(0.5)", "5>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "1>(0.5)", "3>(0.5)", "5>(0.5)"," 1(0.5)", "1>(0.5)", "4>(0.5)", "6>(0.5)"," 1(0.5)", "1>(0.5)", "3>(0.5)", "5>(0.5)"," 1(0.5)", "5>>(0.5)", "7>>(0.5)", "2>(0.5)", "5>(0.5)",
                  "1>(0.5)", "3>(0.5)", "5>(0.5)"," 1(0.5)", "1>(0.5)", "4>(0.5)", "6>(0.5)"," 1(0.5)", "1>(0.5)", "3>(0.5)", "5>(0.5)"," 1(0.5)", "5>>(0.5)", "7>>(0.5)", "2>(0.5)", "5>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "1>(0.5)", "6>(0.5)", "4>(0.5)", "6>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "1>(0.5)", "6>(0.5)", "4>(0.5)", "6>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)", "7>>(0.5)", "5>(0.5)", "2>(0.5)", "5>(0.5)", "1>(0.5)", "5>(0.5)", "3>(0.5)", "5>(0.5)",

                  "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "1(0.75)", "6(0.25)", "4(0.5)", "6(0.5)", "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "1(0.75)", "6(0.25)", "4(0.5)", "6(0.5)", "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "7>(0.75)", "5(0.25)", "2(0.5)", "5(0.5)", "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "1(0.75)", "3(0.25)", "5(0.5)", "1<(0.5)", "1(0.75)", "4(0.25)", "6(0.5)", "1<(0.5)", "1(0.75)", "3(0.25)", "5(0.5)", "1<(0.5)", "5>(0.75)", "7>(0.25)", "2(0.5)", "5(0.5)",
                  "1(0.75)", "3(0.25)", "5(0.5)", "1<(0.5)", "1(0.75)", "4(0.25)", "6(0.5)", "1<(0.5)", "1(0.75)", "3(0.25)", "5(0.5)", "1<(0.5)", "5>(0.75)", "7>(0.25)", "2(0.5)", "5(0.5)", "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "1(0.75)", "6(0.25)", "4(0.5)", "6(0.5)", "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "1(0.75)", "6(0.25)", "4(0.5)", "6(0.5)", "1(0.75)", "5(0.25)", "3(0.5)", "5(0.5)", "7>(0.75)", "5(0.25)", "2(0.5)", "5(0.5)", "1>(2)"]
  }

額,是不是很復雜,很臃腫。。。它以簡譜為載體,通過特殊符號來標記音高和時長,從而產生mainTrack和backingTrack兩個音軌,然后同步播放即可。這種實現雖然簡單,但有很多致命缺點:

不兼容通用的計算機樂譜格式,如musicxml

不能完全表示音樂的所有維度,比如很多鋼琴譜不止有兩個音軌

過于抽象和復雜,不實用,很難制作這種識別格式

音樂專業人士: what are you 弄啥嘞?

所以筆者轉向另一種實現思路,解析musicxml,但奈何這個過程耗時耗力,目前只完成了一半,部分細節還沒有完全解析正確,如果讀者有好的想法,可以在評論區留言探討。

歡迎貢獻協作

貢獻代碼,直接PR

貢獻首頁展示的隨機歌詞: https://github.com/WarpPrism/...

貢獻快速入門的彈奏方法: https://github.com/WarpPrism/...

沒想到短時間內能有這么多star(`?ω?′),嚇得晚上下班回去又繼續碼代碼。。。不過此項目仍不完善,還在不斷更新中,特別是入門彈奏譜子比較少,目前只有:

小星星

新年好

因為愛情

隱形的翅膀

蒲公英的約定

紙短情長

同桌的你

晴天

千與千尋主題曲

明天你好

青花瓷

...

都是筆者一個一個手打出來的T_T,能力有限,會的就這么多,所以是時候見證社區的力量了。

FORK時,請遵循GPL開源協議。
最后
最后再貼一下體驗地址: http://crystalworld.gitee.io/...

歡迎體驗,分享。

解析musicxml的過程仍在進行中,如果某一天成功了,那么示例演奏里面就會加入海量的歌曲,以供學習,如果失敗了,額,那就是因為生活阻擋了我奮進的腳步。。。

原創不易,轉載分享時請注明出處~

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/114387.html

相關文章

  • 程序 + 音樂我的自由鋼琴開發歷程

    摘要:原文鏈接最近用做了一款鋼琴類應用,名字定為自由鋼琴,人生如音樂,歡快且自由。就類似于多年前開發的鋼琴游戲,自由鋼琴只是換了的技術,同時支持了鋼琴曲的自動播放功能。目前采用的技術架構是框架。 原文鏈接 Hate 996? Come Here & Relax~ 最近用Vue + Tone.js做了一款鋼琴類web應用,名字定為自由鋼琴(AutoPiano),人生如音樂,歡快且自由。 此文權...

    Euphoria 評論0 收藏0
  • 一起用Python做個自動化彈鋼琴腳本,我竟然彈出了《天空之城》!

    摘要:突然靈機一動,能不能用自動化腳本彈奏一曲美妙的鋼琴曲呢今天就一起帶大家如何用實現自動化彈出一首天空之城首先一起來看看最終實現的演奏效果下面,我們就開始介紹如何實現這個自動化彈鋼琴腳本的。 ...

    Kylin_Mountain 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<