diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-02-19 17:34:41 -0500 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-02-19 17:34:41 -0500 |
| commit | 08ee1ff32b4d425134bc8d37c7cd2a31ff6ca94e (patch) | |
| tree | 73a0e8882a574d95e77d0101cbe9e842d213efc2 | |
| parent | 932ce855d74848c4721d7ec35dc92a6a3d628a22 (diff) | |
Add FFT-based reverb
| -rw-r--r-- | fft.bqn | 20 | ||||
| -rw-r--r-- | mix.bqn | 20 |
2 files changed, 40 insertions, 0 deletions
@@ -0,0 +1,20 @@ +# Fast Fourier transform +# Argument has shape ⟨l⟩ for real values or ⟨2,l⟩ for complex, l←2⋆n +# Result is complex encoded as shape ⟨2,l⟩. + +Sin‿Cos ← •math + +{ + 𝕨𝕊⁼𝕩: (-𝕨1⊘≢¯1)𝕊𝕩 ; + + inv ← 𝕨≡¯1 + "FFT argument must be a list or have two list cells" ! (3⌊=)◶⟨0,1,2=≠,0⟩𝕩 + n ← 2 ⋆⁼ l ← ¯1⊑≢𝕩 + "FFT length must be a power of two" ! ⌊⊸=n + s ← 2 ⥊˜ n + + r ← (Cos≍Sin) π × (1↓s) ⥊ -⍟inv ↕⊸÷ l÷2 # Roots of unity + M ← -˝∘× ≍ +˝∘×⟜⌽ # Complex multiplication + F ← { 𝕨 ⊏⎉1⊸𝕊⍟(1<=𝕨) (+˝˘≍⎉(-=𝕨)𝕨M-˝˘)𝕩 } # FFT loop + ÷⟜l⍟inv ⥊˘ r F s⊸⥊˘ ≍⟜(0¨)⍟(1==) 𝕩 +} @@ -1,5 +1,6 @@ "mix.bqn takes a single option namespace, or no arguments" ! 1≥≠•args o ← ≠◶⟨•Import∘"options.bqn", ⊑⟩ •args +fft ← •Import "fft.bqn" # List of length |𝕩 that starts at 0 and stops just before 1, # reversed if 𝕩<0. @@ -40,3 +41,22 @@ _crossfade ⇐ { G←↑≍○<↓ (-𝕗)⊸G⊸(∾ 1⌽∾˜○(1⊸↓) ∾⟜< (¬⊸≍I𝕗)+˝∘×≍○⊑)⟜(𝕗⊸G)⎉1 } + +# Apply reverb impulse response (IR) 𝕨 to 𝕩. +# Argument rows are extended, giving result length (𝕩+○≠𝕨)-1 (for lists). +# Equivalent to (+´¨+⌜○↕○≠⊔×⌜)⎉1 except for numeric precision. +Reverb ⇐ { + M ← -˝∘× ≍ +˝∘×⟜⌽ # Complex multiplication + lw‿lx ← (¯1⊑≢)¨ 𝕨‿𝕩 + ! 0<lw + # Use the overlap-add method. + o ← lw-1 # Overlap length + n ← ⌈⌾(2⋆⁼⊢) 3×o # Window length, including overlap + l ← n-o # Without overlap + k ← lx+o # Result length + k0← ⌈⌾(÷⟜l) k # Rounded up + 𝕨 { + CW ← ⊏ · (FFT n↑𝕨)⊸M⌾FFT n⊸↑ + {t←0 ⋄ k↑⥊ {r‿s←(-o)(t⊸+⌾(o⊸↑)∘↓≍○<↑)CW𝕩⋄t↩s⋄r}˘ ∘‿l⥊k0↑𝕩}⎉1 𝕩 + }⎉(1≍1+0⌈-˜○=) 𝕩 +} |
