2026/07/17

有限差分に基づく ADAA の誤差

有限差分に基づく ADAA の誤差を読む (github.io)

任意の次数の ADAA を楽に計算する方法を見つけたのですが、計算誤差の問題で使えないということを確認しました。歪みをかけるときは +60 dB 程のゲインをかけたいですが、中点近似では誤差の大きくなる範囲をカバーしきれないという問題があります。

ADAA は antiderivative antialiasing の略で、歪みのアンチエイリアシングを行う手法です。画像はハードクリップについて有限差分に基づく ADAA を計算すると 3 次以上では値がおかしくなることを示した図です。

2026/07/05

Polyphase IIR フィルタ

Polyphase IIR フィルタを読む (github.io)

ダウンサンプリングに使う IIR フィルタをポリフェイズ分割する方法について検証しました。

Butterworth フィルタであれば動作しています。 32-bit float では 8 次、 64-bit float では 16 次あたりが挙動がおかしくならない上限です。楕円フィルタについても簡単に動作確認したところ動いていました。正面から transposed direct form II でダウンサンプリングするよりも高速かつ正確に計算できます。

画像は 8 次、 4 フェイズ、カットオフ 1/32 [rad/2π] のポリフェイズ Butterworth フィルタの周波数特性です。振幅特性が -120 dB 以下となる高い周波数でノイズが乗っているのはすべて 32-bit float の実装です。

2026/06/28

1-pole 複素ローパスフィルタ

1-pole 複素ローパスフィルタを読む (github.io)

GenericDrum で使った 1-pole 複素ローパスフィルタについて性質を調べました。

このフィルタは -6 dB/oct のスロープでレゾナンスが調節できるフィルタが欲しかったので、複素レゾネータに基づいて適当に作ったものです。カットオフ周波数は極の位置と対応しているので、レゾナンスのピークと一致します。振幅が -3 dB となる周波数とは一致しません。また、レゾナンスが低いときの挙動に癖があります。

画像はレゾナンスを固定してカットオフ周波数を変えたときの 1-pole 複素ローパスフィルタの振幅特性です。

2026/06/27

Chamberlin SVF

Chamberlin SVF を読む (github.io)

Chamberlin SVF と呼ばれる 2 次フィルタについて調べました。バイリニア変換ではなくオイラー法に基づく離散化を行ったバイクアッドフィルタで、周波数特性の歪みが大きい代わりに高速に計算できるという特徴があります。サンプリング周波数が 48000 Hz のときにカットオフの上限が約 8000 Hz となるため使いづらいですが、 4 倍以上のオーバーサンプリングを行うのであれば選択肢に入ります。

Chamberlin SVF からは以前紹介した「3-pole ローパスフィルタ」の α = 1 の場合について等価出力を得ることができます。

画像は Q = 1 / sqrt(2) としたときの振幅特性です。カットオフがナイキスト周波数に近いと特性がおかしくなっていることが見て取れます。

2026/06/24

Sum of Square Roots の近似関数の詳細


Sum of Square Roots の近似関数の詳細を読む (github.io) 

上のリンク先の記事は、このブログの「Sum of square roots の近似関数」に掲載しているコードの詳細です。画像は f64 で計算したときの誤差です。  3 ULP を超える誤差は今のところ見つかっていません。

2026/06/18

EMA フィルタのカットオフの正確な計算


EMA フィルタのカットオフの正確な計算を読む (github.com)

ふと思いついて Gemini 3 Pro に exponential moving average (EMA) フィルタのカットオフ周波数からフィルタ係数を正確に計算する方法を聞いてみたところ、使える回答が出てきました。 Gemini はバージョンが上がって 3.1 Preview や 3.5 Flash などが出ていますが、基本的な式変形は 3 Pro から得たものです。浮動小数点数の計算誤差に関する知識がなかったので検証に時間をかけました。

上の画像は素朴な計算方法の誤差、下の画像は正確な計算方法の誤差です。赤と青の線であらわされた誤差が対応するマシンイプシロンを示す黒い横線を下回っていれば完全に正確です。ところどころマシンイプシロンを上回っているので完全に正確ではなく、ほぼ正確といった性能です。

2026/04/15

ShockFlanger


Download ShockFlanger (github.com)
Read the manual (github.io)

ShockFlanger is a hybrid of a distortion and a flanger. It sounds like a guitar amp. The internals are close to a through-zero flanger with saturators and waveshapers on the feedback paths. High CPU load.

This is an improved version of CombDistortion with better anti-aliasing. ShockFlanger can add better frequency modulation using delay time modulations.

The cause of the high CPU load is memory accesses. DAWs flush the CPU cache for each processing cycle which create a load to read the delay buffers from RAM. This is unavoidable because it's impossible to allocate a space in cache, and DAWs are handling other jobs and plugins. 

---

ShockFlanger をダウンロード (github.com)
マニュアルを読む (github.io)

ShockFlangerはフランジャーの構造をしたディストーションで、ギターアンプのような音が出ます。内部はスルーゼロフランジャーに近く、フィードバック経路に配置されたサチュレーターと、オーディオレートでのディレイ時間変調の組み合わせで歪みが出ます。CPU 負荷はとても高いです。

ShockFlanger は CombDistortion と基本的には同じで、アンチエイリアシングに改良を加えています。 CombDistortion ではほぼ不可能だった、ディレイ時間の変調による FM をかけることもできます。

高 CPU 負荷の原因はメモリーアクセスです。 DAW はオーディオ処理のサイクルごとに CPU キャッシュを消し飛ばしてしまうので、 ShockFlanger は処理を始めるたびにメモリからディレイのバッファを読み込まなければならず、速度が大幅に落ちます。 CPU キャッシュには固定したメモリを確保できず(できると色々なアプリケーションが壊れそうですが)、 DAW は ShockFlanger 以外のプラグインやオーディオ処理をいろいろと回しているのでどうしようもないところではあります。 

2025/12/31

Sum of square roots の近似関数

以下は sum of square roots (√1 + √2 + … + √N) を計算する関数です。 f32 か f64 ならほぼ正確ですが、任意精度実装と比較したときの相対誤差がマシンイプシロンを超える箇所がいくらかあります。 x^2 mod 1.0 の逆微分を計算するときに使えます。

「Sum of Square Roots の近似関数」 (gtihub.io) に詳細を掲載しています。

#include <array>
#include <cmath>
#include <cstdint>
#include <type_traits>

template<typename Real> inline Real sum_of_sqrt(uint64_t N)
{
  alignas(64) static constexpr std::array<Real, 64> table{
    Real(0.00000000000000000e00), Real(1.00000000000000000e00),
    Real(2.41421356237309492e00), Real(4.14626436994197256e00),
    Real(6.14626436994197256e00), Real(8.38233234744176237e00),
    Real(1.08318220902249394e01), Real(1.34775734012895310e01),
    Real(1.63060005260357208e01), Real(1.93060005260357208e01),
    Real(2.24682781862040990e01), Real(2.57849029765595006e01),
    Real(2.92490045916972541e01), Real(3.28545558671612454e01),
    Real(3.65962132539351828e01), Real(4.04691966001426024e01),
    Real(4.44691966001426024e01), Real(4.85923022257602639e01),
    Real(5.28349429128795478e01), Real(5.71938418564202209e01),
    Real(6.16659778114198005e01), Real(6.62485535063756430e01),
    Real(7.09389692661990665e01), Real(7.57348007895117945e01),
    Real(8.06337802750781520e01), Real(8.56337802750781520e01),
    Real(9.07327997886709312e01), Real(9.59289522113775632e01),
    Real(1.01220454833506750e02), Real(1.06605619640641251e02),
    Real(1.12082845215692913e02), Real(1.17650609578522932e02),
    Real(1.23307463828015315e02), Real(1.29052026474553344e02),
    Real(1.34882978369398643e02), Real(1.40799058152498247e02),
    Real(1.46799058152498247e02), Real(1.52881820682796473e02),
    Real(1.59046234685765455e02), Real(1.65291232684163845e02),
    Real(1.71615788004500615e02), Real(1.78018912241933464e02),
    Real(1.84499652940341321e02), Real(1.91057091464643321e02),
    Real(1.97690341045354131e02), Real(2.04398544977853476e02),
    Real(2.11180874960978770e02), Real(2.18036529561379808e02),
    Real(2.24964732791655308e02), Real(2.31964732791655308e02),
    Real(2.39035800603520784e02), Real(2.46177229032063622e02),
    Real(2.53388331582991611e02), Real(2.60668441472272150e02),
    Real(2.68016910700621679e02), Real(2.75433109187717321e02),
    Real(2.82916423961265195e02), Real(2.90466258396535977e02),
    Real(2.98082031502399843e02), Real(3.05763177250268484e02),
    Real(3.13509143942683295e02), Real(3.21319393618589970e02),
    Real(3.29193401492601765e02), Real(3.37130655425795567e02),
  };
  if (N < static_cast<uint64_t>(table.size())) return table[N];

  Real n = static_cast<Real>(N);
  Real sqrt_n = std::sqrt(n);

  constexpr Real zeta_term = Real(-0.207886224977354566); // zeta(-0.5).
  Real base = ((Real(2) / Real(3)) * n + Real(0.5)) * sqrt_n + zeta_term;

  constexpr Real C3 = Real(1) / Real(9216);
  constexpr Real C2 = Real(-1) / Real(1920);
  constexpr Real C1 = Real(1) / Real(24);
  if constexpr (std::is_same_v<Real, float>) {
    return base + C1 / sqrt_n;
  } else {
    Real m = Real(1) / (n * n);
    return base + (((C3 * m + C2) * m + C1) / sqrt_n);
  }
}

参考文献: Ramanujan, Srinivasa. “On the sum of the square roots of the first n natural numbers.” J. Indian Math. Soc 7 (1915): 173-175.

2025/11/17

Windowed Sinc フィルタの高速な計算

Windowed Sinc フィルタの高速な計算を読む (github.io)

sin を再帰的に計算する方法を使って、高速に windowed sinc フィルタを設計する方法について調べました。

ディレイ時間変更時のアンチエイリアシングにおいて、リアルタイムで 1 サンプルごとにフィルタ係数を更新する必要があったので調べました。実験環境では std::sin を使った通常の計算方法に比べると 2~3 倍ほど速くなりました。リンク先の記事の方法は計算精度が低くなるので、フィルタ係数が固定の用途には不向きです。

記事中で触れていますが、 sinc 関数の 0 の周りでは Padé approximant に切り替えて近似しています。このアイデアには Gemini 2.5 Flash を使ってたどり着きました。

(追記: 2026-01-01) Gemini 3 Pro に繰り返しレビューを行わせたところ、テイラー展開を使ったよりまともな近似が得られました。関連する部分について記事の変更、追記を行いました。

画像はディレイの補間方法を変えたときのエイリアシングを比較するスペクトログラムです。下段の 3 つが今回実装したアンチエイリアシングの結果です。

2025/08/22

魔法

魔法 (magic) is an electronic album featuring repetitive melodies played with simple synthesizer sounds.

The album title comes from a comment that says "It sounds like magic," as in some sound effects used in shows. The track titles are given to match the glittering texture. For some reason, the word 魔法 reminds me of Buddhist terminology.

In this album, there aren't much technically interesting sounds. This album was started from 明晰 (lucid), and the tracks that have similar textures are put together. 自在 (to freely do at will) has a unique texture that most of the pitched sounds are sine waves. It depends on the speakers, but the lower bass drum of 超越 (to exceed) somehow rises my heart rate.

The font used for the album art is 崇羲篆體 (chongxi_seal.otf) by 小學堂. It is based on the small seal script written in 大徐本《說文解字》 that is a historical dictionary of chinese characters. 崇羲篆體 is licensed under CC-BY-ND-3.0-TW-or-later. Below is a link to the font distribution page.

https://xiaoxue.iis.sinica.edu.tw/chongxi/

---

魔法は単純なシンセサイザーの音によるメロディーの繰り返しを主とした、エレクトロニック系のアルバムです。

アルバム名は「きらきらとした音が魔法っぽい」というコメントからとったもので、曲名はそれに合わせて適当にぎらぎらとした単語をつけています。魔法というと、どうも仏教用語のような言葉を連想してしまいます。

今回は技法的に面白い音が少ないです。このアルバムの発端となったのは明晰で、この曲と似たような質感の曲を集めています。自在は音程のある音のほとんどがサイン波なので、やや独特の質感があります。スピーカーとの相性もありますが、超越の途中から入るバスドラムを聞いていると心拍数が上がる気がします。

アルバムアートのフォントは小學堂による崇羲篆體 (chongxi_seal.otf) で、說文解字という歴史的な書物の大徐本と呼ばれる版の小篆体に基づいたフォントです。ライセンスは CC-BY-ND-3.0-TW-or-later なので、ほぼ自由に使えます。以下はフォントの配布ページへのリンクです。

https://xiaoxue.iis.sinica.edu.tw/chongxi/

2025/07/18

About Discord Server / Discord サーバーについて

I apologize for leaving Discord server for 3 months. I was misunderstanding that the service sends the notifications email for each post.

---

Discord サーバーについて、投稿ごとにメール通知が来ると勘違いしていたので、3か月ほど放置した状態になっていました。ごめんなさい。