• 173
    Like
  • 2
    Comment

自己紹介

128.png

  • 名前: notargs

作ったもの

  • LGTM Shaders

LGTM

  • CRT Shader

CRT


宣伝

  • 音楽と世界が融合するVRゲームプロジェクト『walkplay』

- クラウドファンディング中!!

walkplay


今回話す内容


?「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を使っていません