Help us understand the problem. What is going on with this article?

GLSL作曲入門

More than 1 year has passed since last update.

GLSL作曲入門

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

virtualcast
VRシステム(バーチャルキャスト)の開発、運営、企画
https://virtualcast.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした