バーチャルシンセを作成したとき参考にしたページなどをメモメモ…
Web Audio API について全く知らない状態から、ブラウザ上で動作する簡単なシンセサイザーを作成してみました。その際 Web Audio API の学習に役立ったページや、作る上で詰まった部分などをまとめておきます。
★ Web Audio API
Web Audio API - Web API | MDN
https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API
とりあえず困ったときのMDN。Web Audio API に関連する項目はほぼ網羅されていてかなり充実しています。具体的なコードや各ブラウザの対応状況などの情報も豊富。
https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API
とりあえず困ったときのMDN。Web Audio API に関連する項目はほぼ網羅されていてかなり充実しています。具体的なコードや各ブラウザの対応状況などの情報も豊富。
★ Web Audio API のチュートリアル
Web Audio API 解説 | g200kg Music & Software
https://www.g200kg.com/jp/docs/webaudio/index.html
基礎から応用まで Web Audio API の各機能と使い方が丁寧に説明されています。仕様書の日本語訳も公開されています。
https://www.g200kg.com/jp/docs/webaudio/index.html
基礎から応用まで Web Audio API の各機能と使い方が丁寧に説明されています。仕様書の日本語訳も公開されています。
Getting Started with Web Audio API - HTML5 Rocks
https://www.html5rocks.com/ja/tutorials/webaudio/intro/
本格的な学習を始める前に、Web Audio API で何ができるのか、「ノード」とはいったい何なのか、といった基本的な機能や概念を手早くざっくり掴みたいときにおすすめ。細かい内容が理解できなくても全体像を捉えるのに役立ちます。
https://www.html5rocks.com/ja/tutorials/webaudio/intro/
本格的な学習を始める前に、Web Audio API で何ができるのか、「ノード」とはいったい何なのか、といった基本的な機能や概念を手早くざっくり掴みたいときにおすすめ。細かい内容が理解できなくても全体像を捉えるのに役立ちます。
★ Web MIDI API (MIDIAccess)
Web MIDI APIを扱うためのMIDI基礎知識 - Qiita
https://qiita.com/okunokentaro/items/efaeb1124591e84fe9d3
MIDI キーボードを使って入力を受け取る場合の基本的な実装方法と入力データの中身について解説されています。
https://qiita.com/okunokentaro/items/efaeb1124591e84fe9d3
MIDI キーボードを使って入力を受け取る場合の基本的な実装方法と入力データの中身について解説されています。
入力データの各値は実際に MIDI キーボードをいじって確認するのが手っ取り早いです。ただし現時点(2020年2月)では Web MIDI API はメジャーなブラウザのうちではまだ Chrome と Opera くらいしか対応していません。最近では MIDI 規格が38年ぶりにバージョンアップして MIDI 2.0 になるなんていうニュースも目にしましたがどうなるんでしょうか…。
★ Canvasで波形を描画
Web Audio API 解説 - 12.アナライザーの使い方 | g200kg Music & Software
https://www.g200kg.com/jp/docs/webaudio/analyser.html
https://www.g200kg.com/jp/docs/webaudio/analyser.html
Web Audio API 解説 - 11.オシレーターのカスタム波形 | g200kg Music & Software
https://www.g200kg.com/jp/docs/webaudio/osccustom.html
https://www.g200kg.com/jp/docs/webaudio/osccustom.html
★ クリック音(プツプツという雑音)の対処法
Web Audio APIで、簡単なシンセサイザーを作ってみる / 2: 音をフェードアウトさせる - Qiita
https://qiita.com/tomoya_ozawa/items/bfd09b436075af916833
音の再生や停止の瞬間に発生する「プツッ」という雑音は、波形がブツ切られてしまうことによって起こります。こちらのページでは、音(Oscillatorノード)に対し個別にGainノードを割り当てておいて、急激な音量変化が起きないように音量を調節する対策方法が紹介されています。
https://qiita.com/tomoya_ozawa/items/bfd09b436075af916833
音の再生や停止の瞬間に発生する「プツッ」という雑音は、波形がブツ切られてしまうことによって起こります。こちらのページでは、音(Oscillatorノード)に対し個別にGainノードを割り当てておいて、急激な音量変化が起きないように音量を調節する対策方法が紹介されています。
基本的には、まず AudioParam.cancelAndHoldAtTime() 関数を使い、値を変更している途中の処理をいったん中止したうえで、AudioParam.linearRampToValueAtTime() 関数を利用することになるのですが…これがブラウザによって実装の方法がまちまちで、狙った動作にならないことがあるようです。たとえば Firefox だとそもそも cancelAndHoldAtTime() が実装されていません(2020年2月現在)。理由としては Web Audio API の仕様書の記述が曖昧で、どういう挙動で実装するのが正解なのかの議論が続いているからです。
(参考) https://github.com/WebAudio/web-audio-api-v2/issues/3
正式な実装がいつになるかわからなかったので、とりあえず Firefox では代わりに AudioParam.cancelScheduledValues() 関数を使って自前で実装することにしました。ただ、やっぱり動作は不安定です…。むむむ…。
(参考) https://github.com/WebAudio/web-audio-api-v2/issues/3
正式な実装がいつになるかわからなかったので、とりあえず Firefox では代わりに AudioParam.cancelScheduledValues() 関数を使って自前で実装することにしました。ただ、やっぱり動作は不安定です…。むむむ…。
Stopping a Web Audio oscillator at cycle completion (or zero-crossing) – Web Audio Tech
https://webaudiotech.com/2017/02/27/stopping-a-web-audio-oscillator-at-cycle-completion/
ちなみにこちらは「波形がゼロレベルになる瞬間に停止させる(ゼロクロッシング)」というアプローチです。ただしサイン波などの単純な波形でない限りは使えないと思います。
https://webaudiotech.com/2017/02/27/stopping-a-web-audio-oscillator-at-cycle-completion/
ちなみにこちらは「波形がゼロレベルになる瞬間に停止させる(ゼロクロッシング)」というアプローチです。ただしサイン波などの単純な波形でない限りは使えないと思います。
★ カスタム波形の生成
カスタム波形を使用するときには createPeriodicWave() 関数に2つの配列(real/imag)を渡します。この配列がどういう波形になるのかという計算式はもちろん仕様書にちゃんと記載されています。
\[x(t) = \sum_{k=1}^{L-1} \left(a[k]\cos2\pi k t + b[k]\sin2\pi k t\right) \]
一見すると「うへぇ!複雑そう!」と感じるかもしれませんが、落ち着いて見ると実はとってもシンプルです。「realの値(式ではa[k])とimagの値(式ではb[k])をそれぞれコサインとサインの係数として波形を作成し、それらを全部足し合わせていく」というただそれだけです。
ちなみに、仕様書には「実際の周波数として計算されるのは2番目の要素(real[1]/imag[1])からで、最初の要素は内部でゼロに設定されるべき」ということも書かれています。つまりreal[0]やimag[0]に値を入れても特に音色は変化しないということですね。3番目の要素、4番目の要素、5番目の要素…と増えていくにつれてコサイン波とサイン波の周期が短くなるので、高い音(倍音)が追加されていくことになるわけです。
\[x(t) = \sum_{k=1}^{L-1} \left(a[k]\cos2\pi k t + b[k]\sin2\pi k t\right) \]
一見すると「うへぇ!複雑そう!」と感じるかもしれませんが、落ち着いて見ると実はとってもシンプルです。「realの値(式ではa[k])とimagの値(式ではb[k])をそれぞれコサインとサインの係数として波形を作成し、それらを全部足し合わせていく」というただそれだけです。
ちなみに、仕様書には「実際の周波数として計算されるのは2番目の要素(real[1]/imag[1])からで、最初の要素は内部でゼロに設定されるべき」ということも書かれています。つまりreal[0]やimag[0]に値を入れても特に音色は変化しないということですね。3番目の要素、4番目の要素、5番目の要素…と増えていくにつれてコサイン波とサイン波の周期が短くなるので、高い音(倍音)が追加されていくことになるわけです。
★ ピアノの鍵盤
https://codepen.io/zastrow/pen/oDBki
ピアノの見た目はこちらを参考にして作成しました。シャドウによる高級感がおしゃれです。
ピアノの見た目はこちらを参考にして作成しました。シャドウによる高級感がおしゃれです。
★ アイコン
使い方は、まずアイコンを読み込んでおいて…
Filled だけではなく Outlined や Rounded のアイコンも使いたいのであれば
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
次に、実際に表示したい場所でアイコンを指定するだけです。
<i class="material-icons">thumb_up</i>
thumb_upFilled だけではなく Outlined や Rounded のアイコンも使いたいのであれば
<link href="https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Round" rel="stylesheet">
のように複数指定で読み込んでおき、クラス名に -outlined や -round を追加すればOK。
<i class="material-icons-outlined">thumb_up</i>
<i class="material-icons-round">thumb_up</i>
thumb_up
thumb_up
<i class="material-icons-round">thumb_up</i>
★ スライダーのデザイン
input type=range タグをカスタマイズするために | g200kg Music & Software
https://www.g200kg.com/archives/2017/12/input-typerange.html
各ブラウザにおけるスライダー(input[type=range])のスタイル指定の方法です。自分はツール類は使わずCSSをすべて手打ちでぺちぺち書いていたのですが、ベンダープレフィックスが入り組んでいて正直めちゃくちゃめんどくさかったです。開発環境が整っていない限り避けたほうが無難…。
https://www.g200kg.com/archives/2017/12/input-typerange.html
各ブラウザにおけるスライダー(input[type=range])のスタイル指定の方法です。自分はツール類は使わずCSSをすべて手打ちでぺちぺち書いていたのですが、ベンダープレフィックスが入り組んでいて正直めちゃくちゃめんどくさかったです。開発環境が整っていない限り避けたほうが無難…。
★ やり残したこと
コード名表示 … コードの一覧表さえ用意できれば実装するのは難しくない。ただし音楽理論のほうがさっぱりなので転回形の判定とかになるともうお手上げに…。まずそっちを勉強する。
フィルター … 単純な波形だとあまり面白くないのと、カスタム波形である程度は調整できるだろう…ということでとりあえず見送り。ディストーションとかは面白いかも。
ピッチコントロール … MIDI キーボードについてるツマミ類でピッチを操作できるようにする機能。どの入力値でどういう挙動になるかを確認するのがめんどくさかったので保留。
複数デバイス … MIDI 機器が複数挿さっていた場合の処理。
音声データ … オシレーターによる単純な波形ではなく音声ファイルを読み込んで再生。
タッチ操作 … スマホ・タブレットに対応。
正直最初は「音が出てコード名とかが表示されたらいいな。4~5日あればできるかな」くらいに軽く考えていたのですが、いざ作りはじめたらどっぷりハマってしまいビジュアライザーやらカスタム波形やら余計なものを追加して結局完成まで丸3週間かかりました。でも楽しかったからいっか!
0 件のコメント:
コメントを投稿