C++用 簡易音楽エフェクター

・標準ライブラリだけで作りました

・C++用簡易音楽エフェクターのヘッダーファイルです

・20種類位のエフェクターをかけることができます

・高校2年生の頃に作成し、定期的に拡張したものなのでメモリーの面などで効率が悪いかも

・説明のミスがあるかも

対応ファイル

16bit 2ch のwavファイル


ダウンロード

2025/1/4 Harmony関数を修正しました

Music.h


↓Webで実行版

Web版(コンソール画面が開けるPC推奨 JavaScriptなので一部処理が非常に重い)


使用音源

北朝鮮の音楽は著作権が無効らしいので使用

2.切りとり でフルの音源を切り取ってある


1.そのまま出力


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Export(2); //チャンネル数 1でモノラル
//wd.Export(2,"Example2.wav"); //のように名前指定可
wd.Dispose(); //破棄
				

2.切りとり

※ここだけフル音源を使用


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Cut(40.7, 43.8); //始点と終点を秒数で指定
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

3.再生速度変更


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Speed(1.5,-6); //再生速度(倍率) ピッチを指定 再生速度をピッチに合わせる場合は、PITCH(ピッチ)のマクロを推奨 倍率にマイナスを付けると逆再生
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

4.リバーブ(低負荷)


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.AlgorithmicReverb(300, 0.6, 0.6); //遅延ミリ秒 倍率 原曲に混ぜる割合
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

5.リバーブ(高負荷)

畳み込みリバーブ

※別途IRデータをネットから探してダウンロードしてください (ここではOpenAIRのものを使用)

4~5分の曲で20~30秒かかります


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.LRdel(1000); //片側をすこし遅延 これを付けると音が広がったように感じる?
wd.ConvolutionReverb("IR.wav", 0.4,150);//IRファイル(16bit 2ch wav) 原曲に混ぜる割合 x以下の周波数無効
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

6.調変更

この曲は短調(ハ短調 #,♭ともに0個)なので、長調(ハ長調 #×3)に変更した例を載せる


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Custom_Scale(MAJOR_SCALE,0); //ピッチ変更用配列(int[12]) 調号数(#×1 ♭×-1)
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

7.フランジャー


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Flanger(1,0.5);//スピード 原曲に混ぜる割合
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

8.コンプレッサー

音割れ注意


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Compressor(0.25);//波形の振幅を何乗するか
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

9.ボイスキャンセラー

中央にボーカルがいれば削除できる

モノラル音源になる


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Voicecanseller();
wd.LRdel(1000); //モノラルさを軽減する場合はこれを後に入れる
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

10.声を抽出

中央がボーカルのみならうまくいく


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.CenterMultiplier(5); //引数が大きいほど音が残りにくい 1~10位がいい?
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

11.サンプリング周波数変更 (ダウンサンプリング)

ダウンサンプリングでしか使わないかも


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Quality(8000); //サンプリング周波数を指定
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

12.エイリアン風


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Alien(1024, 0.1, 0.5, 1.5,1); //1フレームの長さ フレーム間の増加速度 最小速度 最大速度 開始速度
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

13.多重加速

Youtubeによくある多重加速シリーズみたいな音

長めの音源の方が面白いと思う


#include "Music.h"
WaveData wd = WaveData("Example.wav");
wd.Multiple(3, 10); //重なる場所(秒) 速度の差(%)
wd.Export(2); //チャンネル数
wd.Dispose(); //破棄
				

その他

似た機能の紹介は省略

抜けあるかも

引数はソースコードを参照してください

14.サンプリングレートだけ変更 Rate

15.異なるピッチを重ねる Harmony

16.オルゴール風 Orgel   ※wd.Edit(Orgel, 24, wd.Getsample(),8192); //の形でつかう

17.粗くする Rough

18.拍子入れ替え Swap

Youtubeにあったので作ってみた


以下解析用

19.サンプリングレート抽出 int Getsample

20.BPM検出 double BPM

2^k(k...自然数)倍ずれることがある


21.調検出 std::string Scale

結構不正確


wavファイルを読み込み、出力をしたいだけの人へ

次の各2つの関数があれば良い

読み込み


WaveData(std::string fname)
{
    this->fname = fname;
    std::ifstream ifs(fname, std::ios::binary);
    ifs.seekg(0, std::ios::end);
    fileSize = ifs.tellg();
    ifs.seekg(0);
    char* buf = new char[fileSize];
    ifs.read(buf, fileSize);
    bit8 = buf[34] / 8;
    for (int i = 0; i < fileSize; ++i)
    {
        if (i < fileSize - 4)
        {
            if (buf[i] == 0x64 && buf[i + 1] == 0x61 && buf[i + 2] == 0x74 && buf[i + 3] == 0x61)
            {
                fmt = new char[i + 8];
                fsize = i + 8;
                for (int j = 0;j < i + 8; j++)
                {
                    fmt[j] = buf[j];
                }
                wave = BtoI(buf, i + 8,fileSize);
                msize = fileSize - i - 8;
                break;
            }
        }
    }
    for (int i = 0; i < msize / 2; i++)
    {
        maxv = std::max(maxv, abs(wave[i]) + 0.0);
    }
    ch = ReadN(buf, 22, 23);
    sample = ReadN(buf, 24, 27);
    vol_min = -pow(256, bit8) / 2;
    vol_max = pow(256, bit8) / 2 - 1;
    ifs.close();
    if (ch != 2 && bit8 != 2) {
        this->Dispose();
    }
    delete[] buf;
}

//private関数.
int* BtoI(char* x, int start, int len)
{
    int* rt = new int[(len - start) / 2];
    for (int i = start; i < len; i += 2)
    {
        if (x[i] < 0)
        {
            rt[(i - start) / 2] = x[i + 1] * 256 + x[i] + 256;
        }
        else
        {
            rt[(i - start) / 2] = x[i + 1] * 256 + x[i];
        }
    }
    return rt;
}

//使用例.
WaveData wd = WaveData("ファイル名.wav");
				

出力


void Export(int cch, std::string name)
{
    int* rt;
    switch (cch)
    {
    case 1:
        rt = new int[msize / 4];
        for (int i = 0; i < msize / 2 - 1; i += 2)
        {
            rt[i / 2] = wave[i] / 2 + wave[i + 1] / 2;
        }
        wave = rt;
        WriteN(1, 22, 22);
        WriteN(fileSize - msize / 2 - 8, 4, 7);
        WriteN(fileSize - msize / 2 - 126, fsize - 4, fsize - 1);
        msize >>= 1;
        break;
    default:
        break;
    }
    char* bf = ItoB(wave, vol * vol_max / maxv, msize / 2);
    std::ofstream ifs(name, std::ios::binary);
    ifs.write(fmt, fsize);
    ifs.write(bf, msize);
    delete[] bf;
}

//private関数.
char* ItoB(int* cmp, double mult, int cl)
{
    char* rt = new char[cl * 2];
    for (int i = 0; i < cl; ++i)
    {
        if (cmp[i] < 0) {
            rt[i * 2 + 1] = std::max(cmp[i] * mult, vol_min + 0.0) / 256;
            rt[i * 2] = cmp[i] * mult - rt[i * 2 + 1] * 256;
        }
        else {
            rt[i * 2 + 1] = std::min(cmp[i] * mult, vol_max + 0.0) / 256;
            rt[i * 2] = cmp[i] * mult - rt[i * 2 + 1] * 256;
        }
    }
    return rt;
}

//使用例.
wd.Export(チャンネル数(1 or 2), "ファイル名.wav");