Belaで色々作ってみる。(2)

今日実装したやつ(成果)

  • スイッチによってサイン波のON・OFFを切り替える。
  • LEDも同期させる
  • 可変抵抗で音量を変更する

所見

  • 回路を作れるようになってきてる。
    これは仕組みからどこに電気が流れるかを把握しているからにほかならない
  • ただ、抵抗の定義方法がいまいちわからないところがあるので、
    これは別途確認を行う。
  • また、ピンの入出力について知見が深まっている。
    アナログ/デジタルの入出力について適切な選択ができつつある。

ソースコード

今回は単にツマミで音量を更新するコード。
電源・アナログピン・GND+可変抵抗があればすぐできるお手軽な構成。


#include <Bela.h>
#include <cmath>

//改造:
//参照元:http://docs.bela.io/analog-input_2render_8cpp-example.html#a7

//サイン波を出力するための位相。
float gPhase;

//サンプリングレートで割る値。
float gInverseSampleRate;

//アナログフレーム1フレあたりのオーディオフレーム値。
int gAudioFramesPerAnalogFrame = 0;

// アナログピンの番号を定義しておく。
int gSensorInputAmplitude = 0;

bool setup(BelaContext *context, void *userData)
{
    // アナログチャンネルが利用可能だったらOK、利用不可だったら強制終了
    if(context->analogFrames == 0 || context->analogFrames > context->audioFrames)
    {
        rt_printf("Error: this example needs analog enabled, with 4 or 8 channels\n");
        return false;
    }
    // アナログフレームあたりのオーディオフレーム数を予め算出しておく。
    if(context->analogFrames)
        gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames;

    //計算を掛け算に寄せるため、最初からサンプリングレートの逆数を求めておく。
    gInverseSampleRate = 1.0 / context->audioSampleRate;

    //初期定義。
    gPhase = 0.0;

    return true;
}

void render(BelaContext *context, void *userData)
{
    //周波数。
    float frequency;

    //音量
    float amplitude;

    //オーディオフレームの読込を行う。
    for(unsigned int n = 0; n < context->audioFrames; n++)
    {
        if(gAudioFramesPerAnalogFrame && !(n % gAudioFramesPerAnalogFrame))
        {
            //アナログ入力を読み取って、
            //サンプリングレートの値(44100/22050)で処理する。

            //周波数定義
            frequency = 440.0f;

            //音量、ピンから電圧の値を読み取る
            //フレーム数については、「analog input」のフレーム数なので計算で算出することになる。
            //(オーディオフレームと同じくらいに処理されるアナログフレーム数)
            amplitude = analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputAmplitude);
        }

        //サイン波の出力
        float out = amplitude * sinf(gPhase);

        //2chにオーディオ出力を行う。(もしくはもっといっぱい)
        for(unsigned int channel = 0; channel < context->audioOutChannels; channel++)
        {
            //オーディオフレームに書き込みを行う
            audioWrite(context, n, channel, out);
        }

        // 位相の更新を行う。
        gPhase += 2.0f * (float)M_PI * frequency * gInverseSampleRate;

        //360度以上になったら、0-360度の範囲に収める
        if(gPhase > M_PI)
            gPhase -= 2.0f * (float)M_PI;
    }
}

void cleanup(BelaContext *context, void *userData)
{
    //処理なし。
}