※補足:図とか出力を見やすくするため、DxLibを使ってますが表題とはあまり関係ないです。
また、後日追記更新する可能性があります。(絶対するとは言ってない)
構成
No.1 経緯
No.2 サイン波
No.3 二乗カーブ
No.4 線形補間
No.1 経緯
サウンドの勉強してたらフェードの話になって、半分の数値では半分の音量ならないから一気に下げてゆっくり0にしなって言われたので
色んなやり方でやってみようと思いました。
ちなみにそこでは、最大音量に対して0.27倍くらいが半分くらいになると書かれていた。
No.2 サイン波
サイン波だとこんな感じなると思います。分かりやすいように、左の数値では0から1までを25フレームとして、右の図では160フレームにしています。
関わりそうなコードだけを上げるとこんな感じです。
struct XY
{
float x, y;
};
float Sin_ZeroToOne(const int t_maxCount, int t_nowCount)
{
int temp = t_maxCount * 2;
return std::sin(DX_PI / temp * t_nowCount);
}
/// --------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
if (Init(640, 480, 32, "Game") == false) return -1;
const int max = 25;
for (int i = 0; i <= max; ++i)
{
printfDx("%2d: %f\n", i, Sin_ZeroToOne(max, i));
}
const int maxDraw = 160;
XY xy[maxDraw];
for (int i = 1; i <= maxDraw; ++i)
{
int temp = i - 1;
xy[temp].x = i + 240;
xy[temp].y = 240 - Sin_ZeroToOne(maxDraw, i) * 120;
}
// メインループ
while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !CheckHitKey(KEY_INPUT_ESCAPE))
{
for (int i = 1; i <= maxDraw; ++i)
{
int temp = i - 1;
DrawPixel(xy[temp].x, xy[temp].y, GetColor(255, 255, 255));
}
}
まぁ実行すればfloatからint型の変換ですうんたらかんたら言われますが、それは置いといて
こんな感じですと。特に説明はいらないと思います。
No.3 二乗カーブ
ぶっちゃけ合っているかわからないけど二乗カーブなってると思いながら作ってみたらこんな感じになった。
細かい部分はサイン波のやつと大体一緒。
さっきのサイン波のコードと違う部分だけ上げるとこんなところです。
float Squared_ZeroToOne(const int t_maxCount, int t_nowCount)
{
float temp = 1.0f / t_maxCount * t_nowCount;
return temp * temp;
}
数値だけ見たら凄いゆっくりなように見えますが、フェードアウトという意味で見たら良いのかもしれない。
No.4 線形補間
C++20で追加されてるらしい線形補間でやってみた。波だとのこぎり波みたいな感じだし、サウンドのフェードという意味では思った通りのフェードにならないかもしれないけど一応作ってみた。
さっきのサイン波のコードと違う部分だけ上げるとこんなところです。
float lerp(float a, float b, float t)
{
return a + t * (b - a);
}
float Lerp_ZeroToOne(const int t_maxCount, int t_nowCount)
{
float temp = 1.0f / t_maxCount * t_nowCount;
return lerp(0.0f, 1.0f, temp);
}
シーンのフェードとか演出用とかでなら使えるかもしれない。