aboutsummaryrefslogtreecommitdiff
path: root/mix.bqn
blob: 5aafdbd0678197f90d97bd88bb08d5d08c4d06cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"mix.bqn takes a single option namespace, or no arguments" ! 1≥≠•args
o  •Import"options.bqn",  •args
fft  o •Import "fft.bqn"

# List of length |𝕩 that starts at 0 and stops just before 1,
# reversed if 𝕩<0.
I  <0  ÷|

# Add two signals 𝕨 and 𝕩 or a list of signals 𝕩,
# extending to the length of the longest signal.
Add  +´ ·(´(¯1⊑≢)¨)(1¨) 
# Like add, but concatenate instead (no extension).
Concat  ( (0˜·´=¨)(<⊣↓¨))  (1)
# Like ⌽⎉1, but the end of the signal does not wrap around.
Shift  <01 , (-⥊0˙)(1)
# Repeat signal 𝕩 𝕨 times.
Rep  (⥊/)1
# 𝕨 is location‿length. Obtain that part of signal 𝕩.
Slice  (SliceI  +(0⌊+↕|)´) 1 
# Apply 𝔽 to the slice of 𝕩 given by 𝕨.
_onSlice  { 𝔽((SliceI𝕨)1) 𝕩 }

# Convert possibly-mono signal to stereo
Stereo  ˜(2>=)
# Pan signal 𝕩 to position 𝕨, where 0 is hard left and 1 is hard right
Pan  (25×≍¬) 0»˘ ((=⌜˜2)-·(××0)·-1-˜2×⊣)(+˝×¯1)Stereo

# Clipping functions clip to [¯1,1] by default
# _norm changes this to match the format if it's an integer format
_norm  { (𝕨𝔽⊢)(÷(21-˜¯1o.fmt)) 𝕩 }
# Clip signal 𝕩 to the maximum possible range.
Clip  1¯1⌈⊢
# 𝕨 is an integer giving "sharpness". Perform a soft clip.
Softclip  { ÷(1+((2𝕨3))) 𝕩 }

# Multiply leading or trailing samples of 𝕩 by 𝕨.
FadefrontFadeback  {𝕊f: {𝕨×((F≠𝕨)↑⊢)𝕩}1 }¨ -

# 𝕗 is the overlap amount. Fade 𝕨 into 𝕩, linearly.
_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
  lwlx  (¯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𝕨)MFFT n
    {t0  k↑⥊ {rs(-o)(t+(o)↓⋈↑)CW𝕩tsr}˘ lk0𝕩}1 𝕩
  }(11+0⌈-˜=) 𝕩
}
# Apply stereo reverb by keeping early IR sides separate and later
# blending them together; can avoid some balance issues
ReverbStereoMix  {
  ir  (I 100) ((¬⊣×≠)1  Fadefront) 𝕨
  Add ir Reverb¨ (+˝÷≠) 𝕩
}