落胆がらくた街

多分三日坊主で終わると思うんですけど

ファンタム式アクティブDIを作った

パナ改をギターに応用し、ギターとA/Iを直でつないで録音できる機材を作成した。
f:id:suzumodoki:20180612082209j:plain:w300
ファンタム電源を搭載したインターフェースであれば、廉価に高音質な録音ができる。
回路はパナ改同様コネクタの中にしまいこんだので、取り回しも楽勝だ。
オーディオインターフェースにはハイインピーダンスな楽器を繋ぐためのHi-Z入力が用意されているが、何分そいつの出来が宜しくないときなんかに活躍するぞ。

続きを読む

もっと真面目にパナ改を作った

suzublog.hatenablog.com

 元ネタの「パナ改」に若干の改良が加えられており、ここにきてようやく自分でも回路の動作原理が理解できたので部品選定しつつまた作った。
1804 :「ファンタム式パナ改マイク fetⅡ」誕生8年記念。進化した回路を発表 | ShinさんのPA工作室

結論としてはホワイトノイズの低減に成功しつつ、コストと作りやすさが向上するという満足行く結果が出た。
テスト結果は以下のように。

↓あたらしいの


↓ふるいの

詳細は以下より。

続きを読む

JUCEプログラミング::Projucerで作ったLabel/Textの色が反映されない

JUCEのAudioPluginをProjucerのGUIデザイナで作ってると、Labelの色情報が正しく反映されない。

f:id:suzumodoki:20180224094609j:plain f:id:suzumodoki:20180224094611j:plain

色設定のコードおかしくね?みたいな記事を昨日書いたんだけど違ったから消した。

どうも、デフォルトの設定でOK!wとしてると色設定コードを吐いてくれないらしい。
一旦色設定画面↓を開くだけ開いて閉じるとコードがちゃんと生成される。なんじゃそりゃ。
f:id:suzumodoki:20180225103619j:plain

UINT32正規化版高速sinは何をしてるのか

suzublog.hatenablog.com
この記事でやってる、0~2PIをUINT32に正規化してやると高速でSinを計算できるという話。
ようやくこいつが何をしてるのか理解できたので忘れない内に書いとく。

続きを読む

2PIでループする位相変数をUINTに正規化すると美味い

http://www.musicdsp.org/archive.php?classid=1
これの Fast SIN approximation for usage in e.g. additive synthesizers を試してみた。

float fastsin(UINT32 phase)
{
    const float frf3 = -1.0f / 6.0f;
    const float frf5 = 1.0f / 120.0f;
    const float frf7 = -1.0f / 5040.0f;
    const float frf9 = 1.0f / 362880.0f;
    const float f0pi5 = 1.570796327f;
    float x, x2, asin;
    UINT32 tmp = 0x3f800000 | ( phase >> 7 );
    if (phase & 0x40000000)
        tmp ^= 0x007fffff;
    x = ( *( (float*)&tmp ) - 1.0f ) * f0pi5;
    x2 = x * x;
    asin = ( ( ( ( frf9 * x2 + frf7 ) * x2 + frf5 ) * x2 + frf3 ) * x2 + 1.0f ) * x;
    return ( phase & 0x80000000 ) ? -asin : asin;
}

検証コード↓

int main() {
    timerInit();

    float delta_f = 2 * PI * 1000 / SRATE;
    float phase_f = 0;
    UINT32 delta_i = 1000.0 / SRATE * UINT32_MAX;
    UINT32 phase_i = 0;
    

    //特に工夫無く、位相phaseと角速度deltaをfloatにしてmath.hのsinfを呼ぶ
    double t = 0;
    float test = 0;

    for (size_t i = 0; i < SRATE; i++)
    {
        timerStart();

        test += sinf(phase_f);
        phase_f += delta_f;

        t += timerStop();

        if (phase_f >= 2 * PI)phase_f -= 2 * PI; //2PIで位相がループするのはとりあえず時間計測の外とする
    }

    cout << "sinf(float)::" << "total:" << t << "[ms]\n";

    //UINT32正規化版
    t = 0;
    float test2 = 0;

    for (size_t i = 0; i < SRATE; i++)
    {
        timerStart();

        test2 += fastsin(phase_i);
        phase_i += delta_i;

        t += timerStop();
    }

    cout << "sinf(UINT32)::" << "total:" << t << "[ms]\n";

    cout << "test:" << test << ", test2:" << test2 << endl; //何らかの形で変数を参照してやらないと最適化で省かれる

}

結果。

sinf(float)::total:3.06791[ms]
sinf(UINT32)::total:0.292572[ms]
test:0.0168861, test2:6.52373e-05

UINT32、速い(確信)。
ちなみに計測環境はWin8.1、cpu:intel 4690k、DRAM 16GBでコンパイル環境はVisual studio 2015のVisual C++、x64 Releaseビルドで最適化レベル最大。
sinの出力結果の総和が微妙に異なってるのは精度の問題なんだが、別に精度計測のソース書いたら1サンプル毎の精度は十分だったので割愛。


位相をUINT32に正規化するメリットを考えてみる。

  • 検証コードでは時間計測から省いたけど、真面目に2PIでループさせようとする場合1サンプル毎に位相が2PI超えたら戻す処理がいる。UINTならオーバーフローするので不要。
  • 位相を元にテーブルを引きたいみたいな時、位相変数の上何桁と下何桁を分けるみたいな処理が高速で出来る float->intキャストよりずっとはやい!
  • fastsinが速い
  • 位相変数そのものの計算もビット演算が使える分そこそこ速い。特に頻出の2n倍が高速なのは嬉しい

とかこんな感じかな。結構嬉しいと思うんだけど、逆にデメリットはどんなんあるんだろう。誰か教えてください。