LoginSignup
208
142

More than 5 years have passed since last update.

GLSL作曲入門

Last updated at Posted at 2017-01-25
1 / 27

自己紹介

128.png

  • 名前: notargs

作ったもの

  • LGTM Shaders

LGTM

  • CRT Shader

CRT


今回話す内容


?「Game Jamでプログラマーのみのチームになってしまった…」


?「Game Jamでプログラマーのみのチームになってしまった…」
?「音楽素材どうしよう…」


?「Game Jamでプログラマーのみのチームになってしまった…」
?「音楽素材どうしよう…」

@「それ、シェーダーで作れますよ!!」


メリット

  • プログラマーだけで楽曲制作が完結できる
  • OpenGLとPCMにさえ対応していれば動くため、移植性が高い
  • プロシージャルなので圧縮率が高い

デメリット

  • 高度な知識と実装力が必要
  • めんどくさい

手法


Transform Feedback

  • 頂点シェーダでの計算結果を頂点バッファオブジェクトに再度格納する機能
  • CPUからアクセス可能

Transform Feedback

  • 頂点シェーダでの計算結果を頂点バッファオブジェクトに再度格納する機能
  • CPUからアクセス可能
  • GPGPUできる!!

シェーダーの中身

  • gl_vertexIDを元に、そのタイミングでの波形を返す関数
  • 戻り値はステレオに対応したvec2型
void main() 
{
    float time = gl_VertexID / 44100.0;
    out_sample = mainSound(time) * 0.5;
}

再生処理

waveOutOpenとかで適当に流す

waveOutOpen(&h_wave_out, WAVE_MAPPER, &wave_format, reinterpret_cast<DWORD_PTR>(hWnd), 0, CALLBACK_WINDOW);
waveOutPrepareHeader(h_wave_out, &wave_hdr, sizeof(wave_hdr));
waveOutWrite(h_wave_out, &wave_hdr, sizeof(wave_hdr));

音階と周波数


SnapCrab_NoName_2017-1-25_11-20-6_No-00.png

  • みんな大好きsinカーブ
  • 濁りの無い音

SnapCrab_NoName_2017-1-24_5-8-6_No-00.png
- 横幅が周波数(音の高さ)で、1秒間の振幅数、hz(ヘルツ)で表す
- 縦幅が音量に対応している


SnapCrab_NoName_2017-1-25_11-17-52_No-00.png
- 間隔が狭ければ高い音に


SnapCrab_NoName_2017-1-25_11-19-21_No-00.png

  • 間隔が大きければ低い音になります

音階の計算方法

  • ラ(A)の音が440hz
  • 周波数が二倍になると、音階が1オクターブ上がる
  • 1オクターブは12音なので、下記の式で特定の音についての周波数が計算できる
float calcHertz(float scale)
{
    return 440.0 * pow(2.0, scale / 12.0);
}

バスドラムの音を作る

  • 低音でちょっとずつ音量を下げていく
  • 音量とともに周波数も下げても面白い

SnapCrab_NoName_2017-1-25_14-4-45_No-00.png


ハイハット

  • 一瞬だけ乱数を鳴らしてフェードアウトさせる

SnapCrab_NoName_2017-1-25_14-12-51_No-00.png


矩形波

  • サインカーブと比べると少しトゲのある音

SnapCrab_NoName_2017-1-25_14-16-7_No-00.png


ストリングス(和音)

  • 複数の音を鳴らすには単純に足し算すればいい
  • 下の例文はAm7のコードを鳴らすコード
sound += rect(time * calcHertz(24.0)); // ラ(A)
sound += rect(time * calcHertz(28.0)); // ド(C)
sound += rect(time * calcHertz(31.0)); // ミ(E)
sound += rect(time * calcHertz(35.0)); // ソ(G)

ストリングス(和音)

  • グラフで見るとこんな感じ SnapCrab_NoName_2017-1-25_14-23-59_No-00.png

ミキシング

  • それぞれの音を関数として定義
  • main直下で足し算することでミキシング
  • 0.5などの数値を掛け算してボリュームを変更
  • vec2を掛けることでパン(音の低位)を振る
vec2 mainSound(float time)
{
    float sound = 0.0;
    sound += bassDrum(time) * 0.5;
    sound += snereDrum(time) * 0.5;
    sound += hiHat(time) * 0.5;
    sound += strings(time) * 0.2;
    sound += bass(time) * 0.2;
    if (abs(sound) > 1.0) sound /= abs(sound);
    return vec2(sound);
}

最終的な曲のグラフ

SnapCrab_NoName_2017-1-25_14-27-2_No-00.png


実演

https://www.shadertoy.com/view/4l3GD2
※ このサンプルで使っているShaderToyではTransform Feedbackを使っていません

208
142
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
208
142