JUCEプログラミング、Tutorial: Wavetable synthesis6、サイン波に倍音を付加する

倍音が付加されると、一気に音に複雑さが増します。

ウェーブテーブルの波形をいろいろといじれるようになるね~

JUCEチュートリアル、「Synth:Wavetable synthesis」の最後の項目、「Selecting the Harmonics」をやっていきたいと思います。今回は、今まで単調たったサイン波に倍音を付けた波形をウェーブテーブルとするような内容となります。

あわせて読みたい
JUCE: Tutorial: Wavetable synthesis

公式ドキュメントからダウンロードできる該当サンプルは、「WavetableSynthTutorial_04.h」となります。

こんな人の役に立つかも

・JUCEでプログラミングの勉強をしている人

・JUCEチュートリアル「Wavetable synthesis」を勉強している人

・ウェーブテーブルのサイン波に倍音を付加したい人

目次

プログラムの実装

プログラムは、前回までのチュートリアルのプログラムを変更する形で実装していきます。

createWavetable関数

createWavetable関数は、コンストラクタで実行され、AudioBufferクラスの音声バッファにサイン波のウェーブテーブルデータを作成する関数でした。今回は、このcreateWavetable関数で作成するサイン波に指定した倍音を付加した波形データをウェーブテーブルに作成するように作り変えています。

void MainComponent::createWavetable()
{
    sineTable.setSize(1, (int)tableSize + 1);

    //[1]追加しました。
    sineTable.clear();

    auto* samples = sineTable.getWritePointer(0);

    //[2]以下通常のサイン波を作成する処理をコメントアウトしました。
    /*auto angleDelta = juce::MathConstants<double>::twoPi / (double)(tableSize - 1);
    auto currentAngle = 0.0;

    for (unsigned int i = 0; i < tableSize; ++i)
    {
        auto sample = std::sin(currentAngle);
        samples[i] = (float)sample;
        currentAngle += angleDelta;
    }*/

    //[3]↑の処理の代わりに倍音を付加したサイン波を作成します。===
    //[3-1]倍音作成の変数を定義します。
    int harmonics[] = { 1, 3, 5, 6, 7, 9, 13, 15 };
    float harmonicWeights[] = { 0.5f, 0.1f, 0.05f, 0.125f, 0.09f, 0.005f, 0.002f, 0.001f };

    jassert(juce::numElementsInArray(harmonics) == juce::numElementsInArray(harmonicWeights));

    //[3-2]波形を作成します。
    for (auto harmonic = 0; harmonic < juce::numElementsInArray(harmonics); ++harmonic)
    {
        auto angleDelta = juce::MathConstants<double>::twoPi / (double)(tableSize - 1) * harmonics[harmonic];
        auto currentAngle = 0.0;

        for (unsigned int i = 0; i < tableSize; ++i)
        {
            auto sample = std::sin(currentAngle);
            samples[i] += (float)sample * harmonicWeights[harmonic];
            currentAngle += angleDelta;
        }
    }

    //===

    samples[tableSize] = samples[0];
}

[1]では、AudioBufferクラスの「clear」関数でウェーブテーブルとする音声バッファを初期化しています。(なぜ今までこの行がなかったのでしょうか^^;)

[2]は、今までのサイン波を作成する処理です。比較しやすいようにコメントアウトしてみました。

[3]からが、今回の倍音を付け加えた波形を作成する処理になります。

[3-1]では、倍音作成のための変数を準備します。harmonics配列に、何次倍音を付加するかの数値を格納します。チュートリアルでは、奇数倍音とのことでしたが、6がはいっていますね~。harmonicWeights変数として、各倍音のサイン波の音量を設定します。高次倍音になるほど、音量を下げていっていますね。

jassertは、アサーションマクロを表示してくれますので、harmonicsとharmonicWeightsの配列数が一致しないと診断メッセージを表示します。

[3-2]では、波形を作成しています。外側のforで、harmonics配列の数分ループ、内側のループで、ウェーブテーブルのサンプルバッファ数分ループです。harmonics数分のサイン波形を作成して、サンプルに重ねていっている様子がうかがえます。倍音の作成としては、angleDeltaをharmonics倍して進めることで、周期がその倍率になりますので、通常のサイン波に対して周期の早いサイン波が生成できます。

angleDeltaを3倍すると、ラジアンが3倍早く増加するので、sin関数で生成するサイン波も同じサンプル数で3倍の周期が収まることになります。

以下のページの「三角波」をみるとわかるのですが、この配列は三角波を生成しようとしているような気もします。(6次倍音はタイプミス??代わりに11次倍音がないですね。)

GIGAZINE
音の原理や「音色は基音と倍音によって決まる」ことがよく理解できる「Let’s Learn About Waveforms」 この世に存在する「音」は、空気や水などの物体が振動することで生み出されています。そんな「音の成り立ち」をインタラクティブに知ることができるサイトが「Let's Learn ...

prepareToPlay関数

prepareToPlay関数の発音数を200から変更しました。チュートリアルでは10となっているのですが、わかりにくいので、1にして確認しました。

void MainComponent::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
    auto numberOfOscillators = 1;//発音数を指定します。

//...略...

以前より複雑な音色になっている感じがします。

よかったらシェアしてね!
目次
閉じる