1 # MPEG-1 Layer III synthesis: antialias, IMDCT-36, sign flip, DCT-II, polyphase. 2 import Base 3 import ./mp3_tab.bend as Tab 4 import ./mp3_enc.bend as Enc 5 6 # add two binary32 values 7 def f.add(+aa: F32, +bb: F32) -> F32: 8 (aa + bb : F32) 9 10 # subtract two binary32 values 11 def f.sub(+aa: F32, +bb: F32) -> F32: 12 (aa - bb : F32) 13 14 # multiply two binary32 values 15 def f.mul(+aa: F32, +bb: F32) -> F32: 16 (aa * bb : F32) 17 18 # sample at an index, or 0 past the end 19 def f.at(+xs: List<&2, F32>, +ii: U32) -> F32: 20 Enc.f.nth(xs, ii) 21 22 # replace one sample 23 def f.set(xs: List<&2, F32>, +ii: U32, +vv: F32) -> List<&2, F32>: 24 Enc.f.put(xs, ii, vv) 25 26 # unsigned add 27 def u.add(+aa: U32, +bb: U32) -> U32: 28 (aa + bb : U32) 29 30 # unsigned subtract 31 def u.sub(+aa: U32, +bb: U32) -> U32: 32 (aa - bb : U32) 33 34 # unsigned multiply 35 def u.mul(+aa: U32, +bb: U32) -> U32: 36 (aa * bb : U32) 37 38 # low bit 39 def u.and(+kk: U32) -> U32: 40 (kk .&. 1 : U32) 41 42 # 0.5 43 def c.half() -> F32: 44 Enc.f32.bits(1056964608) 45 46 # 0.93969262 47 def c.c939() -> F32: 48 Enc.f32.bits(1064341426) 49 50 # 0.76604444 51 def c.c766() -> F32: 52 Enc.f32.bits(1061428093) 53 54 # 0.17364818 55 def c.c173() -> F32: 56 Enc.f32.bits(1043452116) 57 58 # 0.86602540 59 def c.c866() -> F32: 60 Enc.f32.bits(1063105495) 61 62 # 0.98480775 63 def c.c984() -> F32: 64 Enc.f32.bits(1065098332) 65 66 # 0.34202014 67 def c.c342() -> F32: 68 Enc.f32.bits(1051663684) 69 70 # 0.64278761 71 def c.c642() -> F32: 72 Enc.f32.bits(1059360187) 73 74 # 0.70710677 75 def c.c707() -> F32: 76 Enc.f32.bits(1060439283) 77 78 # 0.198912367 79 def c.c198() -> F32: 80 Enc.f32.bits(1045147567) 81 82 # 0.382683432 83 def c.c382() -> F32: 84 Enc.f32.bits(1053028117) 85 86 # 0.50979561 87 def c.c509() -> F32: 88 Enc.f32.bits(1057128951) 89 90 # 0.54119611 91 def c.c541() -> F32: 92 Enc.f32.bits(1057655764) 93 94 # 0.60134488 95 def c.c601() -> F32: 96 Enc.f32.bits(1058664893) 97 98 # 0.89997619 99 def c.c899() -> F32: 100 Enc.f32.bits(1063675095) 101 102 # 1.30656302 103 def c.c130() -> F32: 104 Enc.f32.bits(1067924853) 105 106 # 2.56291556 107 def c.c256() -> F32: 108 Enc.f32.bits(1076102863) 109 110 # 1/32768, the polyphase scale 111 def c.inv() -> F32: 112 Enc.f32.bits(939524096) 113 114 # drop a prefix 115 def ls.drop(hop: Nat, xs: List<&2, F32>) -> List<&2, F32>: 116 match hop xs: 117 case 0n ys: 118 ys 119 case _ Nil{}: 120 [] 121 case 1n+p _hd <> tl: 122 ls.drop(p, tl) 123 124 # take a prefix, reversed into acc 125 def ls.take(hop: Nat, xs: List<&2, F32>, acc: List<&2, F32>) -> List<&2, F32>: 126 match hop xs: 127 case 0n _: 128 List.reverse(&2, F32, acc) 129 case _ Nil{}: 130 List.reverse(&2, F32, acc) 131 case 1n+p +hd <> tl: 132 ls.take(p, tl, hd <> acc) 133 134 # a slice of length hop starting at an index 135 def ls.slice(+xs: List<&2, F32>, +at: U32, hop: Nat) -> List<&2, F32>: 136 ls.take(hop, ls.drop(U32.to_nat(at), xs), []) 137 138 # write a short list over a destination starting at an index 139 def ls.poke(hop: Nat, dst: List<&2, F32>, src: List<&2, F32>, +at: U32) -> List<&2, F32>: 140 match hop src: 141 case 0n _: 142 dst 143 case _ Nil{}: 144 dst 145 case 1n+p +hd <> tl: 146 ls.poke(p, f.set(dst, at, hd), tl, u.add(at, 1)) 147 148 # nine samples, index 0 first 149 def cs.pack( 150 +v0: F32, +v1: F32, +v2: F32, +v3: F32, +v4: F32, +v5: F32, +v6: F32, +v7: F32, +v8: F32 151 ) -> List<&2, F32>: 152 v0 <> (v1 <> (v2 <> (v3 <> (v4 <> (v5 <> (v6 <> (v7 <> (v8 <> [])))))))) 153 154 # cosine half of one IMDCT-36 band 155 def cs.co(+gg: List<&2, F32>) -> List<&2, F32>: 156 cs.pack(F32.neg(f.at(gg, 0)), f.add(f.at(gg, 1), f.at(gg, 2)), 157 F32.neg(f.add(f.at(gg, 3), f.at(gg, 4))), f.add(f.at(gg, 5), f.at(gg, 6)), 158 F32.neg(f.add(f.at(gg, 7), f.at(gg, 8))), f.add(f.at(gg, 9), f.at(gg, 10)), 159 F32.neg(f.add(f.at(gg, 11), f.at(gg, 12))), f.add(f.at(gg, 13), f.at(gg, 14)), 160 F32.neg(f.add(f.at(gg, 15), f.at(gg, 16)))) 161 162 # sine half of one IMDCT-36 band 163 def cs.si(+gg: List<&2, F32>) -> List<&2, F32>: 164 cs.pack(f.at(gg, 17), f.sub(f.at(gg, 16), f.at(gg, 15)), f.sub(f.at(gg, 13), f.at(gg, 14)), 165 f.sub(f.at(gg, 12), f.at(gg, 11)), f.sub(f.at(gg, 9), f.at(gg, 10)), 166 f.sub(f.at(gg, 8), f.at(gg, 7)), f.sub(f.at(gg, 5), f.at(gg, 6)), 167 f.sub(f.at(gg, 4), f.at(gg, 3)), f.sub(f.at(gg, 1), f.at(gg, 2))) 168 169 # even-part sum used by the 9-point DCT 170 def d9.t0(+y0: F32, +y6: F32) -> F32: 171 f.add(y0, f.mul(y6, c.half())) 172 173 # even-part difference 174 def d9.s0(+y0: F32, +y6: F32) -> F32: 175 f.sub(y0, y6) 176 177 # twiddle on bins 4 and 2 178 def d9.t4(+y4: F32, +y2: F32) -> F32: 179 f.mul(f.add(y4, y2), c.c939()) 180 181 # twiddle on bins 8 and 2 182 def d9.t2(+y8: F32, +y2: F32) -> F32: 183 f.mul(f.add(y8, y2), c.c766()) 184 185 # twiddle on bins 4 and 8 186 def d9.s6(+y4: F32, +y8: F32) -> F32: 187 f.mul(f.sub(y4, y8), c.c173()) 188 189 # even residual 190 def d9.s4(+y4: F32, +y8: F32, +y2: F32) -> F32: 191 f.sub(f.add(y4, y8), y2) 192 193 # scaled residual 194 def d9.s2(+s0: F32, +s4: F32) -> F32: 195 f.sub(s0, f.mul(s4, c.half())) 196 197 # centre bin of the even DCT 198 def d9.y4(+s4: F32, +s0: F32) -> F32: 199 f.add(s4, s0) 200 201 # high even output 202 def d9.s8c(+t0: F32, +t2: F32, +s6: F32) -> F32: 203 f.add(f.sub(t0, t2), s6) 204 205 # low even output 206 def d9.s0c(+t0: F32, +t4: F32, +t2: F32) -> F32: 207 f.add(f.sub(t0, t4), t2) 208 209 # mid even output 210 def d9.s4c(+t0: F32, +t4: F32, +s6: F32) -> F32: 211 f.sub(f.add(t0, t4), s6) 212 213 # odd centre 214 def d9.s3(+y3: F32) -> F32: 215 f.mul(y3, c.c866()) 216 217 # odd low twiddle 218 def d9.tb0(+y5: F32, +y1: F32) -> F32: 219 f.mul(f.add(y5, y1), c.c984()) 220 221 # odd high twiddle 222 def d9.tb4(+y5: F32, +y7: F32) -> F32: 223 f.mul(f.sub(y5, y7), c.c342()) 224 225 # odd mid twiddle 226 def d9.tb2(+y1: F32, +y7: F32) -> F32: 227 f.mul(f.add(y1, y7), c.c642()) 228 229 # odd residual 230 def d9.s1(+y1: F32, +y5: F32, +y7: F32) -> F32: 231 f.mul(f.sub(f.sub(y1, y5), y7), c.c866()) 232 233 # odd combination 234 def d9.s5c(+t0: F32, +s3: F32, +t2: F32) -> F32: 235 f.sub(f.sub(t0, s3), t2) 236 237 # odd combination 238 def d9.s7c(+t4: F32, +s3: F32, +t0: F32) -> F32: 239 f.sub(f.sub(t4, s3), t0) 240 241 # odd combination 242 def d9.s3c(+t4: F32, +s3: F32, +t2: F32) -> F32: 243 f.sub(f.add(t4, s3), t2) 244 245 # even and odd 9-point DCT results, ready to interleave 246 type D9 is Data: 247 D9{ 248 s2b: F32, y4o: F32, s8c: F32, s0c: F32, s4c: F32, s1b: F32, s5c: F32, s7c: F32, s3c: F32 249 } 250 251 # assemble the nine DCT outputs from the even and odd parts 252 def d9.from( 253 +t0: F32, +s0: F32, +t4: F32, +t2: F32, +s6: F32, +s4: F32, +s3: F32, +u0: F32, +u4: F32, 254 +u2: F32, +s1: F32 255 ) -> D9: 256 D9{d9.s2(s0, s4), d9.y4(s4, s0), d9.s8c(t0, t2, s6), d9.s0c(t0, t4, t2), d9.s4c(t0, t4, s6), s1, 257 d9.s5c(u0, s3, u2), d9.s7c(u4, s3, u0), d9.s3c(u4, s3, u2)} 258 259 # 9-point DCT of one half 260 def d9.build( 261 +y0: F32, +y1: F32, +y2: F32, +y3: F32, +y4: F32, +y5: F32, +y6: F32, +y7: F32, +y8: F32 262 ) -> D9: 263 d9.from(d9.t0(y0, y6), d9.s0(y0, y6), d9.t4(y4, y2), d9.t2(y8, y2), d9.s6(y4, y8), 264 d9.s4(y4, y8, y2), d9.s3(y3), d9.tb0(y5, y1), d9.tb4(y5, y7), d9.tb2(y1, y7), d9.s1(y1, y5, y7)) 265 266 # nine DCT outputs in bin order 267 def d9.list(dd: D9) -> List<&2, F32>: 268 match dd: 269 case D9{+s2b, +y4o, +s8c, +s0c, +s4c, +s1b, +s5c, +s7c, +s3c}: 270 cs.pack(f.sub(s4c, s7c), f.add(s2b, s1b), f.sub(s0c, s3c), f.add(s8c, s5c), y4o, 271 f.sub(s8c, s5c), f.add(s0c, s3c), f.sub(s2b, s1b), f.add(s4c, s7c)) 272 273 # 9-point DCT 274 def d9.run(+ys: List<&2, F32>) -> List<&2, F32>: 275 d9.list(d9.build(f.at(ys, 0), f.at(ys, 1), f.at(ys, 2), f.at(ys, 3), f.at(ys, 4), f.at(ys, 5), 276 f.at(ys, 6), f.at(ys, 7), f.at(ys, 8))) 277 278 # negate the odd bins of a sine DCT 279 def d9.neg(+ys: List<&2, F32>) -> List<&2, F32>: 280 f.set(f.set(f.set(f.set(ys, 1, F32.neg(f.at(ys, 1))), 3, F32.neg(f.at(ys, 3))), 5, 281 F32.neg(f.at(ys, 5))), 7, F32.neg(f.at(ys, 7))) 282 283 # one windowed band: 18 time samples and 9 new overlap samples 284 type Wn is Data: 285 Wn{out: List<&2, F32>, nov: List<&2, F32>} 286 287 # window product and the overlap it saves 288 type Ws is Data: 289 Ws{sm: F32, nv: F32} 290 291 # aliasing pair for one window index 292 def wn.pair(+co: List<&2, F32>, +si: List<&2, F32>, +tw: List<&2, F32>, +ii: U32) -> Ws: 293 Ws{f.add(f.mul(f.at(co, ii), f.at(tw, u.add(ii, 9))), f.mul(f.at(si, ii), f.at(tw, ii))), 294 f.sub(f.mul(f.at(co, ii), f.at(tw, ii)), f.mul(f.at(si, ii), f.at(tw, u.add(ii, 9))))} 295 296 # write one window index into the band 297 def wn.put(st: Wn, +ov: List<&2, F32>, +win: List<&2, F32>, +ii: U32, ws: Ws) -> Wn: 298 match st ws: 299 case Wn{out, nov} Ws{+sm, +nv}: 300 Wn{f.set(f.set(out, ii, f.sub(f.mul(f.at(ov, ii), f.at(win, ii)), f.mul(sm, f.at(win, u.add(ii, 9))))), 301 u.sub(17, ii), f.add(f.mul(f.at(ov, ii), f.at(win, u.add(ii, 9))), f.mul(sm, f.at(win, ii)))), 302 f.set(nov, ii, nv)} 303 304 # one of the nine window steps 305 def wn.one( 306 st: Wn, +co: List<&2, F32>, +si: List<&2, F32>, +ov: List<&2, F32>, +tw: List<&2, F32>, 307 +win: List<&2, F32>, +ii: U32 308 ) -> Wn: 309 wn.put(st, ov, win, ii, wn.pair(co, si, tw, ii)) 310 311 # window all nine indices 312 def wn.go( 313 hop: Nat, st: Wn, +co: List<&2, F32>, +si: List<&2, F32>, +ov: List<&2, F32>, +tw: List<&2, F32>, 314 +win: List<&2, F32>, +ii: U32 315 ) -> Wn: 316 match hop: 317 case 0n: 318 st 319 case 1n+p: 320 wn.go(p, wn.one(st, co, si, ov, tw, win, ii), co, si, ov, tw, win, u.add(ii, 1)) 321 322 # IMDCT-36 of one 18-point band 323 def im.band(+gg: List<&2, F32>, +ov: List<&2, F32>, +tw: List<&2, F32>, +win: List<&2, F32>) -> Wn: 324 wn.go(9n, Wn{List.replicate(F32, 18n, 0.0), List.replicate(F32, 9n, 0.0)}, d9.run(cs.co(gg)), 325 d9.neg(d9.run(cs.si(gg))), ov, tw, win, 0) 326 327 # one F32 read from the IMDCT/DCT spectrum Array 328 type Dx is Type: 329 Dx{acc: Array, +v: F32} 330 331 def dx.of(got: Array & F32) -> Dx: 332 (acc, v) = got 333 Dx{acc, v} 334 335 def dx.at(acc: Array, +ii: U32) -> Dx: 336 dx.of(Array.get(F32, acc, ii)) 337 338 # spectrum Array beside the samples just read 339 type Il is Type: 340 Il{acc: Array, xs: List<&2, F32>} 341 342 # pull one sample; hop is remaining after this read 343 def ix.pull(hop: Nat, got: Dx, +ii: U32, ys: List<&2, F32>) -> Il: 344 match hop got: 345 case 0n Dx{acc, +cur}: 346 Il{acc, List.reverse(&2, F32, cur <> ys)} 347 case 1n+p Dx{acc, +cur}: 348 ix.pull(p, dx.at(acc, u.add(ii, 1)), u.add(ii, 1), cur <> ys) 349 350 # hop+1 samples starting at `at`. The spectrum Array is handed back. 351 def ix.take(acc: Array, +at: U32, hop: Nat) -> Il: 352 ix.pull(hop, dx.at(acc, at), at, []) 353 354 # write a short list into the spectrum Array 355 def ix.poke(hop: Nat, acc: Array, src: List<&2, F32>, +at: U32) -> Array: 356 match hop src: 357 case 0n _: 358 acc 359 case _ Nil{}: 360 acc 361 case 1n+p +hd <> tl: 362 ix.poke(p, Array.set(F32, acc, at, hd), tl, u.add(at, 1)) 363 364 # 576 lines in the spectrum Array, and 288 overlap samples 365 type Im is Type: 366 Im{buf: Array, ov: List<&2, F32>} 367 368 # write one band back into the spectrum Array and the overlap 369 def im.store(buf: Array, +ov: List<&2, F32>, ww: Wn, +jj: U32, +base: U32) -> Im: 370 match ww: 371 case Wn{out, nov}: 372 Im{ix.poke(18n, buf, out, u.add(base, u.mul(jj, 18))), ls.poke(9n, ov, nov, u.mul(jj, 9))} 373 374 # band samples in hand; window them and store 375 def im.got( 376 got: Il, +ov: List<&2, F32>, +tw: List<&2, F32>, +win: List<&2, F32>, +jj: U32, +base: U32 377 ) -> Im: 378 match got: 379 case Il{buf, gg}: 380 im.store(buf, ov, im.band(gg, ls.slice(ov, u.mul(jj, 9), 9n), tw, win), jj, base) 381 382 # IMDCT-36 of band jj. Each of the 18 samples is an Array.get. 383 def im.one(st: Im, +tw: List<&2, F32>, +win: List<&2, F32>, +jj: U32, +base: U32) -> Im: 384 match st: 385 case Im{buf, +ov}: 386 im.got(ix.take(buf, u.add(base, u.mul(jj, 18)), 17n), ov, tw, win, jj, base) 387 388 # IMDCT-36 over 32 bands. base is the channel offset in the spectrum Array. 389 def im.go(hop: Nat, st: Im, +tw: List<&2, F32>, +win: List<&2, F32>, +jj: U32, +base: U32) -> Im: 390 match hop: 391 case 0n: 392 st 393 case 1n+p: 394 im.go(p, im.one(st, tw, win, jj, base), tw, win, u.add(jj, 1), base) 395 396 # high index of one aliasing pair 397 def aa.ixh(+base: U32, +bb: U32, +ii: U32) -> U32: 398 u.add(base, u.add(u.mul(u.add(bb, 1), 18), ii)) 399 400 # low index of one aliasing pair 401 def aa.ixl(+base: U32, +bb: U32, +ii: U32) -> U32: 402 u.add(base, u.add(u.mul(bb, 18), u.sub(17, ii))) 403 404 # spectrum Array beside the two aliasing samples 405 type Ia is Type: 406 Ia{acc: Array, +up: F32, +dp: F32} 407 408 # low sample, then both indices are in hand 409 def aa.lo(got: Dx, +up: F32) -> Ia: 410 match got: 411 case Dx{acc, dp}: 412 Ia{acc, up, dp} 413 414 # high sample in hand; read the low sample next 415 def aa.rd1(got: Dx, +lo: U32) -> Ia: 416 match got: 417 case Dx{acc, up}: 418 aa.lo(dx.at(acc, lo), up) 419 420 # read both samples of one aliasing pair. Each read is an Array.get. 421 def aa.rd(acc: Array, +hi: U32, +lo: U32) -> Ia: 422 aa.rd1(dx.at(acc, hi), lo) 423 424 # butterfly of one aliasing pair. c0 and c1 are the two cosine rows. 425 def aa.wr( 426 acc: Array, +up: F32, +dp: F32, +c0: F32, +c1: F32, +hi: U32, +lo: U32 427 ) -> Array: 428 Array.set(F32, Array.set(F32, acc, hi, f.sub(f.mul(c0, up), f.mul(c1, dp))), lo, 429 f.add(f.mul(c1, up), f.mul(c0, dp))) 430 431 # write the pair once both samples have been read 432 def aa.use(got: Ia, +c0: F32, +c1: F32, +hi: U32, +lo: U32) -> Array: 433 match got: 434 case Ia{acc, up, dp}: 435 aa.wr(acc, up, dp, c0, c1, hi, lo) 436 437 # one butterfly at index ii of band bb 438 def aa.one(acc: Array, +aa: List<&2, F32>, +bb: U32, +ii: U32, +base: U32) -> Array: 439 aa.use(aa.rd(acc, aa.ixh(base, bb, ii), aa.ixl(base, bb, ii)), f.at(aa, ii), f.at(aa, u.add(ii, 8)), 440 aa.ixh(base, bb, ii), aa.ixl(base, bb, ii)) 441 442 # eight butterflies between band bb and the next 443 def aa.i(hop: Nat, acc: Array, +aa: List<&2, F32>, +bb: U32, +ii: U32, +base: U32) -> Array: 444 match hop: 445 case 0n: 446 acc 447 case 1n+p: 448 aa.i(p, aa.one(acc, aa, bb, ii, base), aa, bb, u.add(ii, 1), base) 449 450 # antialias from low bands toward high bands 451 def aa.b(hop: Nat, acc: Array, +aa: List<&2, F32>, +bb: U32, +base: U32) -> Array: 452 match hop: 453 case 0n: 454 acc 455 case 1n+p: 456 aa.b(p, aa.i(8n, acc, aa, bb, 0, base), aa, u.add(bb, 1), base) 457 458 # 31 long-block aliasing pairs. base is the channel offset in the spectrum Array. 459 def aa.run(acc: Array, +aa: List<&2, F32>, +base: U32) -> Array: 460 aa.b(31n, acc, aa, 0, base) 461 462 # negate the sample just read 463 def sg.neg(got: Dx, +at: U32) -> Array: 464 match got: 465 case Dx{acc, v}: 466 Array.set(F32, acc, at, F32.neg(v)) 467 468 # negate one odd sample of an odd band 469 def sg.i(hop: Nat, acc: Array, +base: U32, +ii: U32) -> Array: 470 match hop: 471 case 0n: 472 acc 473 case 1n+p: 474 sg.i(p, sg.neg(dx.at(acc, u.add(base, ii)), u.add(base, ii)), base, u.add(ii, 2)) 475 476 # odd samples of 16 odd bands, starting at sample 18 477 def sg.b(hop: Nat, acc: Array, +base: U32) -> Array: 478 match hop: 479 case 0n: 480 acc 481 case 1n+p: 482 sg.b(p, sg.i(9n, acc, base, 1), u.add(base, 36)) 483 484 # frequency inversion after the IMDCT. base is the channel offset. 485 def im.sign(st: Im, +base: U32) -> Im: 486 match st: 487 case Im{buf, ov}: 488 Im{sg.b(16n, buf, u.add(base, 18)), ov} 489 490 # four DCT-II column results 491 type Q4 is Data: 492 Q4{a0: F32, a1: F32, a2: F32, a3: F32} 493 494 # column sample i of the 32-band vector 495 def dc.x0(acc: Array, +kk: U32, +ii: U32) -> Dx: 496 dx.at(acc, u.add(kk, u.mul(ii, 18))) 497 498 # mirrored column 499 def dc.x1(acc: Array, +kk: U32, +ii: U32) -> Dx: 500 dx.at(acc, u.add(kk, u.mul(u.sub(15, ii), 18))) 501 502 # upper column 503 def dc.x2(acc: Array, +kk: U32, +ii: U32) -> Dx: 504 dx.at(acc, u.add(kk, u.mul(u.add(16, ii), 18))) 505 506 # upper mirror 507 def dc.x3(acc: Array, +kk: U32, +ii: U32) -> Dx: 508 dx.at(acc, u.add(kk, u.mul(u.sub(31, ii), 18))) 509 510 # finish the column butterfly 511 def dc.q2(+t0: F32, +t1: F32, +t2: F32, +t3: F32, +s2: F32) -> Q4: 512 Q4{f.add(t0, t1), f.mul(f.sub(t0, t1), s2), f.add(t3, t2), f.mul(f.sub(t3, t2), s2)} 513 514 # one DCT-II column from four samples and three secants 515 def dc.q(+x0: F32, +x1: F32, +x2: F32, +x3: F32, +s0: F32, +s1: F32, +s2: F32) -> Q4: 516 dc.q2(f.add(x0, x3), f.add(x1, x2), f.mul(f.sub(x1, x2), s0), f.mul(f.sub(x0, x3), s1), s2) 517 518 # spectrum Array beside one finished column 519 type Dq is Type: 520 Dq{acc: Array, q: Q4} 521 522 # fourth sample, then the column butterfly 523 def dc.rd3(got: Dx, +x0: F32, +x1: F32, +x2: F32, +s0: F32, +s1: F32, +s2: F32) -> Dq: 524 match got: 525 case Dx{acc, x3}: 526 Dq{acc, dc.q(x0, x1, x2, x3, s0, s1, s2)} 527 528 # third sample and the three secants 529 def dc.rd2(got: Dx, +sec: List<&2, F32>, +kk: U32, +ii: U32, +x0: F32, +x1: F32) -> Dq: 530 match got: 531 case Dx{acc, x2}: 532 dc.rd3(dc.x3(acc, kk, ii), x0, x1, x2, f.at(sec, u.mul(ii, 3)), 533 f.at(sec, u.add(u.mul(ii, 3), 1)), f.at(sec, u.add(u.mul(ii, 3), 2))) 534 535 # second sample 536 def dc.rd1(got: Dx, +sec: List<&2, F32>, +kk: U32, +ii: U32, +x0: F32) -> Dq: 537 match got: 538 case Dx{acc, x1}: 539 dc.rd2(dc.x2(acc, kk, ii), sec, kk, ii, x0, x1) 540 541 # read column ii. Each of the four samples is an Array.get. 542 def dc.cell(got: Dx, +sec: List<&2, F32>, +kk: U32, +ii: U32) -> Dq: 543 match got: 544 case Dx{acc, x0}: 545 dc.rd1(dc.x1(acc, kk, ii), sec, kk, ii, x0) 546 547 # store one column into the 4 by 8 working Array 548 def dc.store(xs: Array, qq: Q4, +ii: U32) -> Array: 549 match qq: 550 case Q4{a0, a1, a2, a3}: 551 Array.set(F32, Array.set(F32, Array.set(F32, Array.set(F32, xs, ii, a0), u.add(ii, 8), a1), 552 u.add(ii, 16), a2), u.add(ii, 24), a3) 553 554 # spectrum Array beside the 4 by 8 working rows 555 type Dr is Type: 556 Dr{acc: Array, xs: Array} 557 558 # write one gathered column and keep both Arrays 559 def dc.stored(got: Dq, xs: Array, +ii: U32) -> Dr: 560 match got: 561 case Dq{acc, q}: 562 Dr{acc, dc.store(xs, q, ii)} 563 564 # gather all eight columns before any write-back 565 def dc.cols(hop: Nat, got: Dr, +sec: List<&2, F32>, +kk: U32, +ii: U32) -> Dr: 566 match hop got: 567 case 0n Dr{acc, xs}: 568 Dr{acc, xs} 569 case 1n+p Dr{acc, xs}: 570 dc.cols(p, dc.stored(dc.cell(dc.x0(acc, kk, ii), sec, kk, ii), xs, ii), sec, kk, u.add(ii, 1)) 571 572 # eight floats carried through the DCT-II row butterfly 573 type E8 is Data: 574 E8{z0: F32, z1: F32, z2: F32, z3: F32, z4: F32, z5: F32, z6: F32, z7: F32} 575 576 # finish the first stage 577 def but.sum2( 578 +xt: F32, +y0: F32, +y7: F32, +y1: F32, +y6: F32, +y2: F32, +y5: F32, +y3: F32 579 ) -> E8: 580 E8{f.add(y0, y3), f.add(y1, y2), y6, f.sub(y1, y2), f.sub(y0, y3), y5, y7, xt} 581 582 # first add/sub stage of a DCT-II row 583 def but.sum(+x0: F32, +x1: F32, +x2: F32, +x3: F32, +x4: F32, +x5: F32, +x6: F32, +x7: F32) -> E8: 584 but.sum2(f.sub(x0, x7), f.add(x0, x7), f.sub(x1, x6), f.add(x1, x6), f.sub(x2, x5), f.add(x2, x5), 585 f.sub(x3, x4), f.add(x3, x4)) 586 587 # second stage: the 45-degree rotations 588 def but.mid(ee: E8) -> E8: 589 match ee: 590 case E8{+z0, +z1, +z2, +z3, +z4, +z5, +z6, +z7}: 591 E8{f.add(z0, z1), f.mul(f.add(z3, z4), c.c707()), f.mul(f.add(z2, z6), c.c707()), z4, 592 f.mul(f.sub(z0, z1), c.c707()), f.add(z5, z2), f.add(z6, z7), z7} 593 594 # last rotation update 595 def but.rot3( 596 +o0: F32, +w3: F32, +w6: F32, +y4: F32, +o4: F32, +p5: F32, +p7: F32, +xt: F32 597 ) -> E8: 598 E8{o0, p7, w3, y4, o4, f.sub(p5, f.mul(p7, c.c198())), f.sub(xt, w6), f.add(xt, w6)} 599 600 # complete the rotation 601 def but.rot2( 602 +o0: F32, +w3: F32, +w6: F32, +y4: F32, +o4: F32, +p5: F32, +w7: F32, +xt: F32 603 ) -> E8: 604 but.rot3(o0, w3, w6, y4, o4, p5, f.add(w7, f.mul(p5, c.c382())), xt) 605 606 # third stage: the small-angle rotation, using the updated values 607 def but.rot(ee: E8) -> E8: 608 match ee: 609 case E8{+z0, +z1, +z2, +z3, +z4, +z5, +z6, +z7}: 610 but.rot2(z0, z1, z2, z3, z4, f.sub(z5, f.mul(z6, c.c198())), z6, z7) 611 612 # eight row outputs 613 def but.end(ee: E8) -> List<&2, F32>: 614 match ee: 615 case E8{+z0, +z1, +z2, +z3, +z4, +z5, +z6, +z7}: 616 cs.pack(z0, f.mul(f.add(z7, z1), c.c509()), f.mul(f.add(z3, z2), c.c541()), 617 f.mul(f.sub(z6, z5), c.c601()), z4, f.mul(f.add(z6, z5), c.c899()), 618 f.mul(f.sub(z3, z2), c.c130()), f.mul(f.sub(z7, z1), c.c256()), 0.0) 619 620 # cs.pack takes 9; the row is 8. Drop the padding below. 621 def but.out(ee: E8) -> List<&2, F32>: 622 ls.take(8n, but.end(ee), []) 623 624 # butterfly the eight samples and write the row back 625 def but.sum8(acc: Array, +ys: List<&2, F32>, +base: U32) -> Array: 626 ix.poke(8n, acc, but.out(but.rot(but.mid(but.sum(f.at(ys, 0), f.at(ys, 1), f.at(ys, 2), 627 f.at(ys, 3), f.at(ys, 4), f.at(ys, 5), f.at(ys, 6), f.at(ys, 7))))), base) 628 629 # butterfly one row. The eight inputs are one slice of the working Array. 630 def but.use(got: Il, +base: U32) -> Array: 631 match got: 632 case Il{acc, ys}: 633 but.sum8(acc, ys, base) 634 635 # butterfly one row of eight and write it back 636 def but.row(xs: Array, +base: U32) -> Array: 637 but.use(ix.take(xs, base, 7n), base) 638 639 # butterfly all four rows 640 def dc.fly(hop: Nat, xs: Array, +base: U32) -> Array: 641 match hop: 642 case 0n: 643 xs 644 case 1n+p: 645 dc.fly(p, but.row(xs, base), u.add(base, 8)) 646 647 # seven samples of one scatter column, row-major 648 type Sv is Type: 649 Sv{xs: Array, +p0: F32, +p1: F32, +p2: F32, +p3: F32, +p4: F32, +p5: F32, +p6: F32} 650 651 # row 3, column ii+1 652 def sc.v6(got: Dx, +r0: F32, +r1: F32, +r1n: F32, +r2: F32, +r2n: F32, +r3: F32) -> Sv: 653 match got: 654 case Dx{acc, r3n}: 655 Sv{acc, r0, r1, r1n, r2, r2n, r3, r3n} 656 657 # row 3, column ii 658 def sc.v5(got: Dx, +ii: U32, +r0: F32, +r1: F32, +r1n: F32, +r2: F32, +r2n: F32) -> Sv: 659 match got: 660 case Dx{acc, r3}: 661 sc.v6(dx.at(acc, u.add(ii, 25)), r0, r1, r1n, r2, r2n, r3) 662 663 # row 2, column ii+1 664 def sc.v4(got: Dx, +ii: U32, +r0: F32, +r1: F32, +r1n: F32, +r2: F32) -> Sv: 665 match got: 666 case Dx{acc, r2n}: 667 sc.v5(dx.at(acc, u.add(ii, 24)), ii, r0, r1, r1n, r2, r2n) 668 669 # row 2, column ii 670 def sc.v3(got: Dx, +ii: U32, +r0: F32, +r1: F32, +r1n: F32) -> Sv: 671 match got: 672 case Dx{acc, r2}: 673 sc.v4(dx.at(acc, u.add(ii, 17)), ii, r0, r1, r1n, r2) 674 675 # row 1, column ii+1 676 def sc.v2(got: Dx, +ii: U32, +r0: F32, +r1: F32) -> Sv: 677 match got: 678 case Dx{acc, r1n}: 679 sc.v3(dx.at(acc, u.add(ii, 16)), ii, r0, r1, r1n) 680 681 # row 1, column ii 682 def sc.v1(got: Dx, +ii: U32, +r0: F32) -> Sv: 683 match got: 684 case Dx{acc, r1}: 685 sc.v2(dx.at(acc, u.add(ii, 9)), ii, r0, r1) 686 687 # row 0, column ii, then the six neighbour slots 688 def sc.v0(got: Dx, +ii: U32) -> Sv: 689 match got: 690 case Dx{acc, r0}: 691 sc.v1(dx.at(acc, u.add(ii, 8)), ii, r0) 692 693 # the seven samples of column ii, each an Array.get 694 def sc.vals(xs: Array, +ii: U32) -> Sv: 695 sc.v0(dx.at(xs, ii), ii) 696 697 # spectrum Array beside the rows Array 698 type Sc is Type: 699 Sc{acc: Array, xs: Array} 700 701 # four band values from the seven column samples 702 def sc.bands( 703 +p0: F32, +p1: F32, +p2: F32, +p3: F32, +p4: F32, +p5: F32, +p6: F32 704 ) -> Q4: 705 Q4{p0, f.add(f.add(p3, p5), p6), f.add(p1, p2), f.add(f.add(p4, p5), p6)} 706 707 # store the four bands and hand both Arrays back 708 def sc.put4(xs: Array, acc: Array, qq: Q4, +yy: U32) -> Sc: 709 match qq: 710 case Q4{a0, a1, a2, a3}: 711 Sc{Array.set(F32, Array.set(F32, Array.set(F32, Array.set(F32, acc, yy, a0), u.add(yy, 18), a1), 712 u.add(yy, 36), a2), u.add(yy, 54), a3), xs} 713 714 # write one scatter group from the seven samples 715 def sc.put(got: Sv, acc: Array, +yy: U32) -> Sc: 716 match got: 717 case Sv{xs, p0, p1, p2, p3, p4, p5, p6}: 718 sc.put4(xs, acc, sc.bands(p0, p1, p2, p3, p4, p5, p6), yy) 719 720 # scatter one group of four bands into the spectrum Array 721 def sc.one(acc: Array, xs: Array, +yy: U32, +ii: U32) -> Sc: 722 sc.put(sc.vals(xs, ii), acc, yy) 723 724 # seven scatter steps; the eighth is the tail 725 def sc.go(hop: Nat, got: Sc, +yy: U32, +ii: U32) -> Sc: 726 match hop got: 727 case 0n Sc{acc, xs}: 728 Sc{acc, xs} 729 case 1n+p Sc{acc, xs}: 730 sc.go(p, sc.one(acc, xs, yy, ii), u.add(yy, 72), u.add(ii, 1)) 731 732 # row 0, 1, 2 and 3 of column 7 733 type Sf is Type: 734 Sf{xs: Array, +r0: F32, +r1: F32, +r2: F32, +r3: F32} 735 736 # fourth tail sample, index 31 737 def sc.e3(got: Dx, +r0: F32, +r1: F32, +r2: F32) -> Sf: 738 match got: 739 case Dx{acc, r3}: 740 Sf{acc, r0, r1, r2, r3} 741 742 # third tail sample, index 23 743 def sc.e2(got: Dx, +r0: F32, +r1: F32) -> Sf: 744 match got: 745 case Dx{acc, r2}: 746 sc.e3(dx.at(acc, 31), r0, r1, r2) 747 748 # second tail sample, index 15 749 def sc.e1(got: Dx, +r0: F32) -> Sf: 750 match got: 751 case Dx{acc, r1}: 752 sc.e2(dx.at(acc, 23), r0, r1) 753 754 # first tail sample, index 7, then the other three rows 755 def sc.e0(got: Dx) -> Sf: 756 match got: 757 case Dx{acc, r0}: 758 sc.e1(dx.at(acc, 15), r0) 759 760 # four tail bands. r3 is both the high sum and the last band. 761 def sc.tset(acc: Array, +r0: F32, +r1: F32, +r2: F32, +r3: F32, +yy: U32) -> Array: 762 Array.set(F32, Array.set(F32, Array.set(F32, Array.set(F32, acc, yy, r0), u.add(yy, 18), 763 f.add(r2, r3)), u.add(yy, 36), r1), u.add(yy, 54), r3) 764 765 # drop the rows Array once the four tail samples have been read 766 def sc.tend(got: Sf, acc: Array, +yy: U32) -> Array: 767 match got: 768 case Sf{xs, r0, r1, r2, r3}: 769 match xs: 770 case _xs: 771 sc.tset(acc, r0, r1, r2, r3, yy) 772 773 # last scatter group, which has no i+1 neighbour. The rows Array ends here. 774 def sc.tail(got: Sc, +yy: U32) -> Array: 775 match got: 776 case Sc{acc, xs}: 777 sc.tend(sc.e0(dx.at(xs, 7)), acc, yy) 778 779 # scatter every band of frequency bin kk 780 def sc.run(acc: Array, xs: Array, +kk: U32) -> Array: 781 sc.tail(sc.go(7n, Sc{acc, xs}, kk, 0), u.add(kk, 504)) 782 783 # butterfly the gathered rows, then scatter them back into the spectrum 784 def dc.rows(got: Dr) -> Dr: 785 match got: 786 case Dr{acc, xs}: 787 Dr{acc, dc.fly(4n, xs, 0)} 788 789 # scatter one frequency bin. The working rows are consumed here. 790 def dc.scat(got: Dr, +kk: U32) -> Array: 791 match got: 792 case Dr{acc, xs}: 793 sc.run(acc, xs, kk) 794 795 # one frequency bin of the 32-point DCT-II. The working rows stay an Array. 796 def dc.one(acc: Array, +sec: List<&2, F32>, +kk: U32) -> Array: 797 dc.scat(dc.rows(dc.cols(8n, Dr{acc, Array.new(F32, 5n, 0.0)}, sec, kk, 0)), kk) 798 799 # DCT-II of 18 frequency bins. kk is the first bin's index in the spectrum Array. 800 def dc.run(hop: Nat, acc: Array, +sec: List<&2, F32>, +kk: U32) -> Array: 801 match hop: 802 case 0n: 803 acc 804 case 1n+p: 805 dc.run(p, dc.one(acc, sec, kk), sec, u.add(kk, 1)) 806 807 # one F32 read from the polyphase delay Array 808 type La is Type: 809 La{lin: Array, +v: F32} 810 811 def la.of(got: Array & F32) -> La: 812 (lin, v) = got 813 La{lin, v} 814 815 def ln.at(lin: Array, +ii: U32) -> La: 816 la.of(Array.get(F32, lin, ii)) 817 818 def ln.set(lin: Array, +ii: U32, +vv: F32) -> Array: 819 Array.set(F32, lin, ii, vv) 820 821 def ln.fill(xs: List<&2, F32>, a: Array, +ii: U32) -> Array: 822 match xs: 823 case Nil{}: 824 a 825 case +hd <> tl: 826 ln.fill(tl, Array.set(F32, a, ii, hd), u.add(ii, 1)) 827 828 # pull one sample into an accumulator; hop is remaining after this read 829 def ln.pull(hop: Nat, got: La, +ii: U32, acc: List<&2, F32>) -> List<&2, F32>: 830 match hop got: 831 case 0n La{lin, +cur}: 832 match lin: 833 case _l: 834 List.reverse(&2, F32, cur <> acc) 835 case 1n+p La{lin, +cur}: 836 ln.pull(p, ln.at(lin, u.add(ii, 1)), u.add(ii, 1), cur <> acc) 837 838 # first hop+1 slots of an Array as a list 839 def ln.list(a: Array, hop: Nat) -> List<&2, F32>: 840 ln.pull(hop, ln.at(a, 0), 0, []) 841 842 # four running polyphase sums, a and b 843 type Mac is Data: 844 Mac{aa: List<&2, F32>, bb: List<&2, F32>} 845 846 # MAC state plus the delay line handle mac.* only reads 847 type Mk is Type: 848 Mk{st: Mac, lin: Array} 849 850 # mode 0 replaces, mode 2 flips the a product, otherwise both add 851 def mac.av(+mode: U32, +zv: F32, +yv: F32, +w0: F32, +w1: F32) -> F32: 852 match mode: 853 case 2: 854 f.sub(f.mul(yv, w1), f.mul(zv, w0)) 855 case _: 856 f.sub(f.mul(zv, w0), f.mul(yv, w1)) 857 858 # apply one lane of a window load 859 def mac.wr( 860 +aa: List<&2, F32>, +bb: List<&2, F32>, +mode: U32, +jj: U32, +bv: F32, +av: F32 861 ) -> Mac: 862 match mode: 863 case 0: 864 Mac{f.set(aa, jj, av), f.set(bb, jj, bv)} 865 case _: 866 Mac{f.set(aa, jj, f.add(f.at(aa, jj), av)), f.set(bb, jj, f.add(f.at(bb, jj), bv))} 867 868 # one of the four lanes, y slot 869 def mac.jy( 870 st: Mac, got: La, +w0: F32, +w1: F32, +mode: U32, +jj: U32, +zv: F32 871 ) -> Mk: 872 match st got: 873 case Mac{aa, bb} La{lin2, yv}: 874 Mk{mac.wr(aa, bb, mode, jj, f.add(f.mul(zv, w1), f.mul(yv, w0)), mac.av(mode, zv, yv, w0, w1)), lin2} 875 876 # one of the four lanes, z slot 877 def mac.jz( 878 st: Mac, got: La, +w0: F32, +w1: F32, +vy: U32, +mode: U32, +jj: U32 879 ) -> Mk: 880 match got: 881 case La{lin1, zv}: 882 mac.jy(st, ln.at(lin1, u.add(vy, jj)), w0, w1, mode, jj, zv) 883 884 # one of the four lanes 885 def mac.j( 886 st: Mac, lin: Array, +w0: F32, +w1: F32, +vz: U32, +vy: U32, +mode: U32, +jj: U32 887 ) -> Mk: 888 mac.jz(st, ln.at(lin, u.add(vz, jj)), w0, w1, vy, mode, jj) 889 890 # four lanes of one load, advance one lane 891 def mac.js_next(mk: Mk, +w0: F32, +w1: F32, +vz: U32, +vy: U32, +mode: U32, +jj: U32) -> Mk: 892 match mk: 893 case Mk{st, lin}: 894 mac.j(st, lin, w0, w1, vz, vy, mode, jj) 895 896 # four lanes of one load 897 def mac.js( 898 hop: Nat, mk: Mk, +w0: F32, +w1: F32, +vz: U32, +vy: U32, +mode: U32, +jj: U32 899 ) -> Mk: 900 match hop: 901 case 0n: 902 mk 903 case 1n+p: 904 mac.js(p, mac.js_next(mk, w0, w1, vz, vy, mode, jj), w0, w1, vz, vy, mode, u.add(jj, 1)) 905 906 # odd or even load 907 def mac.mode3(odd: Bool) -> U32: 908 match odd: 909 case True{}: 910 2 911 case False{}: 912 1 913 914 # pick the load mode 915 def mac.mode2(zero: Bool, odd: Bool) -> U32: 916 match zero: 917 case True{}: 918 0 919 case False{}: 920 mac.mode3(odd) 921 922 # k = 0 replaces, odd k uses mode 2, other even k uses mode 1 923 def mac.mode(+kk: U32) -> U32: 924 mac.mode2(U32.is_eq(kk, 0), U32.is_eq(u.and(kk), 1)) 925 926 # window-coefficient index for block row ii and load kk 927 def mac.pos(+ii: U32, +kk: U32) -> U32: 928 u.add(u.mul(u.sub(14, ii), 16), u.mul(kk, 2)) 929 930 # one window coefficient handed back beside the table Array.get just read 931 type Sw is Type: 932 Sw{syn: Array, +w: F32} 933 934 def sw.of(got: Array & F32) -> Sw: 935 (syn, w) = got 936 Sw{syn, w} 937 938 def sw.at(syn: Array, +ii: U32) -> Sw: 939 sw.of(Array.get(F32, syn, ii)) 940 941 # 242 synthesis-window coefficients. 256 slots cover every mac.pos index. 942 def sw.tab() -> Array: 943 ln.fill(Enc.f.of(Tab.tab.syn()), Array.new(F32, 8n, 0.0), 0) 944 945 # MAC state plus the window table the next load still reads 946 type Mw is Type: 947 Mw{mk: Mk, syn: Array} 948 949 # second coefficient, then the eight-lane load 950 def mac.step2(mk: Mk, got: Sw, +w0: F32, +zlin: U32, +ii: U32, +kk: U32) -> Mw: 951 match mk got: 952 case Mk{st, lin} Sw{syn, w1}: 953 Mw{mac.js(4n, Mk{st, lin}, w0, w1, u.sub(u.add(zlin, u.mul(ii, 4)), u.mul(kk, 64)), 954 u.sub(u.add(zlin, u.mul(ii, 4)), u.mul(u.sub(15, kk), 64)), mac.mode(kk), 0), syn} 955 956 # first coefficient, then its neighbour 957 def mac.step1(mk: Mk, got: Sw, +pos: U32, +zlin: U32, +ii: U32, +kk: U32) -> Mw: 958 match got: 959 case Sw{syn, w0}: 960 mac.step2(mk, sw.at(syn, u.add(pos, 1)), w0, zlin, ii, kk) 961 962 # one of the eight loads. Each tap reads the window Array. 963 def mac.step(mk: Mk, syn: Array, +zlin: U32, +ii: U32, +kk: U32) -> Mw: 964 mac.step1(mk, sw.at(syn, mac.pos(ii, kk)), mac.pos(ii, kk), zlin, ii, kk) 965 966 # eight loads 967 def mac.k(hop: Nat, got: Mw, +zlin: U32, +ii: U32, +kk: U32) -> Mw: 968 match hop got: 969 case 0n Mw{mk, syn}: 970 Mw{mk, syn} 971 case 1n+p Mw{mk, syn}: 972 mac.k(p, mac.step(mk, syn, zlin, ii, kk), zlin, ii, u.add(kk, 1)) 973 974 # scale a polyphase sum into a sample 975 def mac.sc(+vv: F32) -> F32: 976 f.mul(vv, c.inv()) 977 978 # write the eight samples this row produces 979 def mac.p8( 980 pcm: Array, +aa: List<&2, F32>, +bb: List<&2, F32>, +nch: U32, +pcmi: U32, +ii: U32 981 ) -> Array: 982 ln.set(ln.set(ln.set(ln.set(ln.set(ln.set(ln.set(ln.set(pcm, 983 u.add(pcmi, u.add(u.mul(u.sub(15, ii), nch), u.sub(nch, 1))), mac.sc(f.at(aa, 1))), 984 u.add(pcmi, u.add(u.mul(u.add(17, ii), nch), u.sub(nch, 1))), mac.sc(f.at(bb, 1))), 985 u.add(pcmi, u.mul(u.sub(15, ii), nch)), mac.sc(f.at(aa, 0))), 986 u.add(pcmi, u.mul(u.add(17, ii), nch)), mac.sc(f.at(bb, 0))), 987 u.add(pcmi, u.add(u.mul(u.sub(47, ii), nch), u.sub(nch, 1))), mac.sc(f.at(aa, 3))), 988 u.add(pcmi, u.add(u.mul(u.add(49, ii), nch), u.sub(nch, 1))), mac.sc(f.at(bb, 3))), 989 u.add(pcmi, u.mul(u.sub(47, ii), nch)), mac.sc(f.at(aa, 2))), 990 u.add(pcmi, u.mul(u.add(49, ii), nch)), mac.sc(f.at(bb, 2))) 991 992 # store the row 993 def mac.put(pcm: Array, st: Mac, +nch: U32, +pcmi: U32, +ii: U32) -> Array: 994 match st: 995 case Mac{+aa, +bb}: 996 mac.p8(pcm, aa, bb, nch, pcmi, ii) 997 998 # fresh accumulators 999 def mac.z() -> Mac: 1000 Mac{List.replicate(F32, 4n, 0.0), List.replicate(F32, 4n, 0.0)} 1001 1002 # channel offset: the right channel starts at 576 when there are two 1003 def blk.off(+nch: U32, right: Bool) -> U32: 1004 match right: 1005 case False{}: 1006 0 1007 case True{}: 1008 u.mul(u.sub(nch, 1), 576) 1009 1010 # one F32 read from the post-DCT granule Array 1011 type Ga is Type: 1012 Ga{gr: Array, +v: F32} 1013 1014 def ga.of(got: Array & F32) -> Ga: 1015 (gr, v) = got 1016 Ga{gr, v} 1017 1018 def ga.at(gr: Array, +ii: U32) -> Ga: 1019 ga.of(Array.get(F32, gr, ii)) 1020 1021 # delay line handed back beside the granule Array a write just read 1022 type Lg is Type: 1023 Lg{lin: Array, gr: Array} 1024 1025 # subband index. right selects the second channel, which starts at 576. 1026 def blk.ix(+nch: U32, +band: U32, +tm: U32, right: Bool) -> U32: 1027 u.add(u.add(blk.off(nch, right), u.mul(band, 18)), tm) 1028 1029 def blk.rd(gr: Array, +nch: U32, +band: U32, +tm: U32, right: Bool) -> Ga: 1030 ga.at(gr, blk.ix(nch, band, tm, right)) 1031 1032 # fourth sample of a four-lane write 1033 def blk.w4d(g: Ga, lin: Array, +at: U32, +v0: F32, +v1: F32, +v2: F32) -> Lg: 1034 match g: 1035 case Ga{gr, v3}: 1036 Lg{ln.set(ln.set(ln.set(ln.set(lin, at, v0), u.add(at, 1), v1), u.add(at, 2), v2), u.add(at, 3), v3), 1037 gr} 1038 1039 # third sample: band 0, this channel's left slot 1040 def blk.w4c(g: Ga, lin: Array, +nch: U32, +at: U32, +tm: U32, +v0: F32, +v1: F32) -> Lg: 1041 match g: 1042 case Ga{gr, v2}: 1043 blk.w4d(blk.rd(gr, nch, 0, tm, True{}), lin, at, v0, v1, v2) 1044 1045 # second sample: the right channel of this band 1046 def blk.w4b(g: Ga, lin: Array, +nch: U32, +at: U32, +tm: U32, +v0: F32) -> Lg: 1047 match g: 1048 case Ga{gr, v1}: 1049 blk.w4c(blk.rd(gr, nch, 0, tm, False{}), lin, nch, at, tm, v0, v1) 1050 1051 # first sample: the left channel of this band 1052 def blk.w4a(g: Ga, lin: Array, +nch: U32, +at: U32, +band: U32, +tm: U32) -> Lg: 1053 match g: 1054 case Ga{gr, v0}: 1055 blk.w4b(blk.rd(gr, nch, band, tm, True{}), lin, nch, at, tm, v0) 1056 1057 # write the four samples at zlin + 4*slot 1058 def blk.w4( 1059 lin: Array, gr: Array, +nch: U32, +at: U32, +band: U32, +tm: U32 1060 ) -> Lg: 1061 blk.w4a(blk.rd(gr, nch, band, tm, False{}), lin, nch, at, band, tm) 1062 1063 # right channel of a two-lane write 1064 def blk.w2b(g: Ga, lin: Array, +at: U32, +v0: F32) -> Lg: 1065 match g: 1066 case Ga{gr, v1}: 1067 Lg{ln.set(ln.set(lin, at, v0), u.add(at, 1), v1), gr} 1068 1069 # left channel of a two-lane write 1070 def blk.w2a(g: Ga, lin: Array, +nch: U32, +at: U32, +band: U32, +tm: U32) -> Lg: 1071 match g: 1072 case Ga{gr, v0}: 1073 blk.w2b(blk.rd(gr, nch, band, tm, True{}), lin, at, v0) 1074 1075 # the second write of a row uses band (1+ii), not band 0 1076 def blk.w2( 1077 lin: Array, gr: Array, +nch: U32, +at: U32, +band: U32, +tm: U32 1078 ) -> Lg: 1079 blk.w2a(blk.rd(gr, nch, band, tm, False{}), lin, nch, at, band, tm) 1080 1081 # second preamble write: band 16 at the next time 1082 def blk.pre2(got: Lg, +nch: U32, +zlin: U32, +tm: U32) -> Lg: 1083 match got: 1084 case Lg{lin, gr}: 1085 blk.w4(lin, gr, nch, u.add(zlin, 124), 16, u.add(tm, 1)) 1086 1087 # preamble: bands 16 and 0 at the current and next time 1088 def blk.pre( 1089 lin: Array, gr: Array, +nch: U32, +zlin: U32, +tm: U32 1090 ) -> Lg: 1091 blk.pre2(blk.w4(lin, gr, nch, u.add(zlin, 60), 16, tm), nch, zlin, tm) 1092 1093 # index of the history write, which steps back 16 slots 1094 def blk.hist(+zlin: U32, +ii: U32) -> U32: 1095 u.add(u.sub(zlin, u.mul(u.sub(16, ii), 4)), 2) 1096 1097 # fourth lane: this band at the next time, right channel 1098 def blk.wsd(g: Ga, lin: Array, +at: U32, +v0: F32, +v1: F32, +v2: F32) -> Lg: 1099 match g: 1100 case Ga{gr, v3}: 1101 Lg{ln.set(ln.set(ln.set(ln.set(lin, at, v0), u.add(at, 1), v1), u.add(at, 2), v2), u.add(at, 3), v3), 1102 gr} 1103 1104 # third lane: this band at the next time, left channel 1105 def blk.wsc( 1106 g: Ga, lin: Array, +nch: U32, +at: U32, +band: U32, +tm: U32, +v0: F32, +v1: F32 1107 ) -> Lg: 1108 match g: 1109 case Ga{gr, v2}: 1110 blk.wsd(blk.rd(gr, nch, band, u.add(tm, 1), True{}), lin, at, v0, v1, v2) 1111 1112 # second lane: this band at this time, right channel 1113 def blk.wsb(g: Ga, lin: Array, +nch: U32, +at: U32, +band: U32, +tm: U32, +v0: F32) -> Lg: 1114 match g: 1115 case Ga{gr, v1}: 1116 blk.wsc(blk.rd(gr, nch, band, u.add(tm, 1), False{}), lin, nch, at, band, tm, v0, v1) 1117 1118 # first lane: this band at this time, left channel 1119 def blk.wsa(g: Ga, lin: Array, +nch: U32, +at: U32, +band: U32, +tm: U32) -> Lg: 1120 match g: 1121 case Ga{gr, v0}: 1122 blk.wsb(blk.rd(gr, nch, band, tm, True{}), lin, nch, at, band, tm, v0) 1123 1124 # same band at this time and the next, four lanes 1125 def blk.ws( 1126 lin: Array, gr: Array, +nch: U32, +at: U32, +band: U32, +tm: U32 1127 ) -> Lg: 1128 blk.wsa(blk.rd(gr, nch, band, tm, False{}), lin, nch, at, band, tm) 1129 1130 # current-slot writes for row ii 1131 def blk.i1( 1132 lin: Array, gr: Array, +nch: U32, +zlin: U32, +tm: U32, +ii: U32 1133 ) -> Lg: 1134 blk.ws(lin, gr, nch, u.add(zlin, u.mul(ii, 4)), u.sub(31, ii), tm) 1135 1136 # history write, after the next-slot write has returned the granule 1137 def blk.i2b(got: Lg, +nch: U32, +zlin: U32, +tm: U32, +ii: U32) -> Lg: 1138 match got: 1139 case Lg{lin, gr}: 1140 blk.w2(lin, gr, nch, blk.hist(zlin, ii), u.add(1, ii), tm) 1141 1142 # next-slot and history writes for row ii 1143 def blk.i2( 1144 lin: Array, gr: Array, +nch: U32, +zlin: U32, +tm: U32, +ii: U32 1145 ) -> Lg: 1146 blk.i2b(blk.w2(lin, gr, nch, u.add(u.add(zlin, u.mul(ii, 4)), 64), u.add(1, ii), u.add(tm, 1)), nch, 1147 zlin, tm, ii) 1148 1149 # history writes, after the current-slot write has returned the granule 1150 def blk.ib(got: Lg, +nch: U32, +zlin: U32, +tm: U32, +ii: U32) -> Lg: 1151 match got: 1152 case Lg{lin, gr}: 1153 blk.i2(lin, gr, nch, zlin, tm, ii) 1154 1155 # both writes for row ii 1156 def blk.i( 1157 lin: Array, gr: Array, +nch: U32, +zlin: U32, +tm: U32, +ii: U32 1158 ) -> Lg: 1159 blk.ib(blk.i1(lin, gr, nch, zlin, tm, ii), nch, zlin, tm, ii) 1160 1161 # (z+896) - z, times 29 1162 def sp.a1a3(g1: La, +v896: F32) -> La: 1163 match g1: 1164 case La{lin2, vz}: 1165 La{lin2, f.mul(f.sub(v896, vz), Enc.f32.bits(1105723392))} 1166 1167 def sp.a1a2(g0: La, +zz: U32) -> La: 1168 match g0: 1169 case La{lin1, v896}: 1170 sp.a1a3(ln.at(lin1, zz), v896) 1171 1172 def sp.a1a(lin: Array, +zz: U32) -> La: 1173 sp.a1a2(ln.at(lin, u.add(zz, 896)), zz) 1174 1175 # slots 1 and 13, times 213 1176 def sp.a1b2(g1: La, +acc: F32, +v64: F32) -> La: 1177 match g1: 1178 case La{lin2, v832}: 1179 La{lin2, f.add(acc, f.mul(f.add(v64, v832), Enc.f32.bits(1129644032)))} 1180 1181 def sp.a1b1(g0: La, +acc: F32, +zz: U32) -> La: 1182 match g0: 1183 case La{lin1, v64}: 1184 sp.a1b2(ln.at(lin1, u.add(zz, 832)), acc, v64) 1185 1186 def sp.a1b(+acc: F32, lin: Array, +zz: U32) -> La: 1187 sp.a1b1(ln.at(lin, u.add(zz, 64)), acc, zz) 1188 1189 # slots 12 and 2, times 459 1190 def sp.a1c2(g1: La, +acc: F32, +v768: F32) -> La: 1191 match g1: 1192 case La{lin2, v128}: 1193 La{lin2, f.add(acc, f.mul(f.sub(v768, v128), Enc.f32.bits(1139113984)))} 1194 1195 def sp.a1c1(g0: La, +acc: F32, +zz: U32) -> La: 1196 match g0: 1197 case La{lin1, v768}: 1198 sp.a1c2(ln.at(lin1, u.add(zz, 128)), acc, v768) 1199 1200 def sp.a1c(+acc: F32, lin: Array, +zz: U32) -> La: 1201 sp.a1c1(ln.at(lin, u.add(zz, 768)), acc, zz) 1202 1203 # slots 3 and 11, times 2037 1204 def sp.a1d2(g1: La, +acc: F32, +v192: F32) -> La: 1205 match g1: 1206 case La{lin2, v704}: 1207 La{lin2, f.add(acc, f.mul(f.add(v192, v704), Enc.f32.bits(1157537792)))} 1208 1209 def sp.a1d1(g0: La, +acc: F32, +zz: U32) -> La: 1210 match g0: 1211 case La{lin1, v192}: 1212 sp.a1d2(ln.at(lin1, u.add(zz, 704)), acc, v192) 1213 1214 def sp.a1d(+acc: F32, lin: Array, +zz: U32) -> La: 1215 sp.a1d1(ln.at(lin, u.add(zz, 192)), acc, zz) 1216 1217 # slots 10 and 4, times 5153 1218 def sp.a1e2(g1: La, +acc: F32, +v640: F32) -> La: 1219 match g1: 1220 case La{lin2, v256}: 1221 La{lin2, f.add(acc, f.mul(f.sub(v640, v256), Enc.f32.bits(1168181248)))} 1222 1223 def sp.a1e1(g0: La, +acc: F32, +zz: U32) -> La: 1224 match g0: 1225 case La{lin1, v640}: 1226 sp.a1e2(ln.at(lin1, u.add(zz, 256)), acc, v640) 1227 1228 def sp.a1e(+acc: F32, lin: Array, +zz: U32) -> La: 1229 sp.a1e1(ln.at(lin, u.add(zz, 640)), acc, zz) 1230 1231 # slots 5 and 9, times 6574 1232 def sp.a1f2(g1: La, +acc: F32, +v320: F32) -> La: 1233 match g1: 1234 case La{lin2, v576}: 1235 La{lin2, f.add(acc, f.mul(f.add(v320, v576), Enc.f32.bits(1171091456)))} 1236 1237 def sp.a1f1(g0: La, +acc: F32, +zz: U32) -> La: 1238 match g0: 1239 case La{lin1, v320}: 1240 sp.a1f2(ln.at(lin1, u.add(zz, 576)), acc, v320) 1241 1242 def sp.a1f(+acc: F32, lin: Array, +zz: U32) -> La: 1243 sp.a1f1(ln.at(lin, u.add(zz, 320)), acc, zz) 1244 1245 # slots 8 and 6, times 37489, then slot 7 times 75038 1246 def sp.a1g4(g2: La, +acc: F32, +v512: F32, +v384: F32) -> La: 1247 match g2: 1248 case La{lin3, v448}: 1249 La{lin3, 1250 f.add(f.add(acc, f.mul(f.sub(v512, v384), Enc.f32.bits(1192390912))), 1251 f.mul(v448, Enc.f32.bits(1200787200)))} 1252 1253 def sp.a1g3(g1: La, +acc: F32, +v512: F32, +zz: U32) -> La: 1254 match g1: 1255 case La{lin2, v384}: 1256 sp.a1g4(ln.at(lin2, u.add(zz, 448)), acc, v512, v384) 1257 1258 def sp.a1g2(g0: La, +acc: F32, +zz: U32) -> La: 1259 match g0: 1260 case La{lin1, v512}: 1261 sp.a1g3(ln.at(lin1, u.add(zz, 384)), acc, v512, zz) 1262 1263 def sp.a1g(+acc: F32, lin: Array, +zz: U32) -> La: 1264 sp.a1g2(ln.at(lin, u.add(zz, 512)), acc, zz) 1265 1266 def sp.a1go6(g: La, +zz: U32) -> La: 1267 match g: 1268 case La{lin6, acc6}: 1269 sp.a1g(acc6, lin6, zz) 1270 1271 def sp.a1go5(g: La, +zz: U32) -> La: 1272 match g: 1273 case La{lin5, acc5}: 1274 sp.a1go6(sp.a1f(acc5, lin5, zz), zz) 1275 1276 def sp.a1go4(g: La, +zz: U32) -> La: 1277 match g: 1278 case La{lin4, acc4}: 1279 sp.a1go5(sp.a1e(acc4, lin4, zz), zz) 1280 1281 def sp.a1go3(g: La, +zz: U32) -> La: 1282 match g: 1283 case La{lin3, acc3}: 1284 sp.a1go4(sp.a1d(acc3, lin3, zz), zz) 1285 1286 def sp.a1go2(g: La, +zz: U32) -> La: 1287 match g: 1288 case La{lin2, acc2}: 1289 sp.a1go3(sp.a1c(acc2, lin2, zz), zz) 1290 1291 def sp.a1go1(g: La, +zz: U32) -> La: 1292 match g: 1293 case La{lin1, acc1}: 1294 sp.a1go2(sp.a1b(acc1, lin1, zz), zz) 1295 1296 # first grouped window sum 1297 def sp.a1(lin: Array, +zz: U32) -> La: 1298 sp.a1go1(sp.a1a(lin, zz), zz) 1299 1300 # taps 898, 770, 642, 514 1301 def sp.a2a4(g3: La, +v898: F32, +v770: F32, +v642: F32) -> La: 1302 match g3: 1303 case La{lin4, v514}: 1304 La{lin4, 1305 f.add(f.add(f.add(f.mul(v898, Enc.f32.bits(1120927744)), f.mul(v770, Enc.f32.bits(1153687552))), 1306 f.mul(v642, Enc.f32.bits(1175976960))), f.mul(v514, Enc.f32.bits(1199182592)))} 1307 1308 def sp.a2a3(g2: La, +v898: F32, +v770: F32, +zz: U32) -> La: 1309 match g2: 1310 case La{lin3, v642}: 1311 sp.a2a4(ln.at(lin3, u.add(zz, 514)), v898, v770, v642) 1312 1313 def sp.a2a2(g1: La, +v898: F32, +zz: U32) -> La: 1314 match g1: 1315 case La{lin2, v770}: 1316 sp.a2a3(ln.at(lin2, u.add(zz, 642)), v898, v770, zz) 1317 1318 def sp.a2a1(g0: La, +zz: U32) -> La: 1319 match g0: 1320 case La{lin1, v898}: 1321 sp.a2a2(ln.at(lin1, u.add(zz, 770)), v898, zz) 1322 1323 def sp.a2a(lin: Array, +zz: U32) -> La: 1324 sp.a2a1(ln.at(lin, u.add(zz, 898)), zz) 1325 1326 # taps 386 and 258 1327 def sp.a2b2(g1: La, +acc: F32, +v386: F32) -> La: 1328 match g1: 1329 case La{lin2, v258}: 1330 La{lin2, f.add(f.add(acc, f.mul(v386, Enc.f32.bits(3323714560))), f.mul(v258, Enc.f32.bits(3258187776)))} 1331 1332 def sp.a2b1(g0: La, +acc: F32, +zz: U32) -> La: 1333 match g0: 1334 case La{lin1, v386}: 1335 sp.a2b2(ln.at(lin1, u.add(zz, 258)), acc, v386) 1336 1337 def sp.a2b(+acc: F32, lin: Array, +zz: U32) -> La: 1338 sp.a2b1(ln.at(lin, u.add(zz, 386)), acc, zz) 1339 1340 # tap 130 1341 def sp.a2c1(g: La, +acc: F32) -> La: 1342 match g: 1343 case La{lin1, v130}: 1344 La{lin1, f.add(acc, f.mul(v130, Enc.f32.bits(1125253120)))} 1345 1346 def sp.a2c(+acc: F32, lin: Array, +zz: U32) -> La: 1347 sp.a2c1(ln.at(lin, u.add(zz, 130)), acc) 1348 1349 # tap 2 1350 def sp.a2d1(g: La, +acc: F32) -> La: 1351 match g: 1352 case La{lin1, v2}: 1353 La{lin1, f.add(acc, f.mul(v2, Enc.f32.bits(3231711232)))} 1354 1355 def sp.a2d(+acc: F32, lin: Array, +zz: U32) -> La: 1356 sp.a2d1(ln.at(lin, u.add(zz, 2)), acc) 1357 1358 def sp.a2go3(g: La, +zz: U32) -> La: 1359 match g: 1360 case La{lin3, acc3}: 1361 sp.a2d(acc3, lin3, zz) 1362 1363 def sp.a2go2(g: La, +zz: U32) -> La: 1364 match g: 1365 case La{lin2, acc2}: 1366 sp.a2go3(sp.a2c(acc2, lin2, zz), zz) 1367 1368 def sp.a2go1(g: La, +zz: U32) -> La: 1369 match g: 1370 case La{lin1, acc1}: 1371 sp.a2go2(sp.a2b(acc1, lin1, zz), zz) 1372 1373 # second window sum, eight weighted taps 1374 def sp.a2(lin: Array, +zz: U32) -> La: 1375 sp.a2go1(sp.a2a(lin, zz), zz) 1376 1377 # PCM and delay line while pairing synth samples 1378 type Pp is Type: 1379 Pp{pcm: Array, lin: Array} 1380 1381 # one synth pair: two scaled samples 1382 def sp.pair2(g2: La, pcm: Array, +pcmi: U32, +nch: U32) -> Pp: 1383 match g2: 1384 case La{lin2, v2}: 1385 Pp{ln.set(pcm, u.add(pcmi, u.mul(16, nch)), mac.sc(v2)), lin2} 1386 1387 def sp.pair1(g1: La, pcm: Array, +pcmi: U32, +nch: U32, +zz: U32) -> Pp: 1388 match g1: 1389 case La{lin1, v1}: 1390 sp.pair2(sp.a2(lin1, zz), ln.set(pcm, pcmi, mac.sc(v1)), pcmi, nch) 1391 1392 def sp.pair(st: Pp, +pcmi: U32, +nch: U32, +zz: U32) -> Pp: 1393 match st: 1394 case Pp{pcm, lin}: 1395 sp.pair1(sp.a1(lin, zz), pcm, pcmi, nch, zz) 1396 1397 # four synth pairs that open a block 1398 def blk.pairs(st: Pp, +nch: U32, +pcmi: U32, +z0: U32) -> Pp: 1399 sp.pair(sp.pair(sp.pair(sp.pair(st, u.add(pcmi, u.sub(nch, 1)), nch, u.add(z0, 1)), u.add(u.add(pcmi, 1400 u.mul(32, nch)), u.sub(nch, 1)), nch, u.add(z0, 65)), pcmi, nch, z0), u.add(pcmi, u.mul(32, nch)), nch, 1401 u.add(z0, 64)) 1402 1403 # delay line and the PCM written so far 1404 type Sb is Type: 1405 Sb{lin: Array, pcm: Array} 1406 1407 def blk.armed1(got: Pp) -> Sb: 1408 match got: 1409 case Pp{pcm2, lin2}: 1410 Sb{lin2, pcm2} 1411 1412 # pairs read the delay line the preamble just wrote 1413 def blk.armed(lin: Array, pcm: Array, +nch: U32, +tm: U32) -> Sb: 1414 blk.armed1(blk.pairs(Pp{pcm, lin}, nch, u.mul(u.mul(32, nch), tm), u.add(u.mul(tm, 64), 60))) 1415 1416 # polyphase state, the granule Array the rows still read, and the window table 1417 type Bg is Type: 1418 Bg{st: Sb, gr: Array, syn: Array} 1419 1420 # preamble done: the pairs read the delay line, the granule and window stay put 1421 def blk.arm2(got: Lg, pcm: Array, syn: Array, +nch: U32, +tm: U32) -> Bg: 1422 match got: 1423 case Lg{lin, gr}: 1424 Bg{blk.armed(lin, pcm, nch, tm), gr, syn} 1425 1426 # open a block: preamble, then the four pairs 1427 def blk.arm(got: Bg, +nch: U32, +tm: U32) -> Bg: 1428 match got: 1429 case Bg{st, gr, syn}: 1430 match st: 1431 case Sb{lin, pcm}: 1432 blk.arm2(blk.pre(lin, gr, nch, u.add(u.mul(tm, 64), 960), tm), pcm, syn, nch, tm) 1433 1434 # a finished row, with the window table the next row still reads 1435 type Sr is Type: 1436 Sr{st: Sb, syn: Array} 1437 1438 def blk.row1(got: Mw, pcm: Array, +nch: U32, +tm: U32, +ii: U32) -> Sr: 1439 match got: 1440 case Mw{mk, syn}: 1441 match mk: 1442 case Mk{st, lin2}: 1443 Sr{Sb{lin2, mac.put(pcm, st, nch, u.mul(u.mul(32, nch), tm), ii)}, syn} 1444 1445 def blk.row3(got: Sr, gr: Array) -> Bg: 1446 match got: 1447 case Sr{st, syn}: 1448 Bg{st, gr, syn} 1449 1450 # window the row just written 1451 def blk.row( 1452 lin: Array, pcm: Array, syn: Array, +nch: U32, +tm: U32, +ii: U32 1453 ) -> Sr: 1454 blk.row1(mac.k(8n, Mw{Mk{mac.z(), lin}, syn}, u.add(u.mul(tm, 64), 960), ii, 0), pcm, nch, tm, ii) 1455 1456 # window the row, keeping the granule for the rows still to come 1457 def blk.step2( 1458 got: Lg, pcm: Array, syn: Array, +nch: U32, +tm: U32, +ii: U32 1459 ) -> Bg: 1460 match got: 1461 case Lg{lin, gr}: 1462 blk.row3(blk.row(lin, pcm, syn, nch, tm, ii), gr) 1463 1464 # one row of the block, from i = 14 down to 0 1465 def blk.step(got: Bg, +nch: U32, +tm: U32, +ii: U32) -> Bg: 1466 match got: 1467 case Bg{st, gr, syn}: 1468 match st: 1469 case Sb{lin, pcm}: 1470 blk.step2(blk.i(lin, gr, nch, u.add(u.mul(tm, 64), 960), tm, ii), pcm, syn, nch, tm, ii) 1471 1472 # fifteen rows 1473 def blk.i.go(hop: Nat, got: Bg, +nch: U32, +tm: U32, +ii: U32) -> Bg: 1474 match hop got: 1475 case 0n Bg{st, gr, syn}: 1476 Bg{st, gr, syn} 1477 case 1n+p Bg{st, gr, syn}: 1478 blk.i.go(p, blk.step(Bg{st, gr, syn}, nch, tm, ii), nch, tm, u.sub(ii, 1)) 1479 1480 # one time block 1481 def blk.one(got: Bg, +nch: U32, +tm: U32) -> Bg: 1482 blk.i.go(15n, blk.arm(got, nch, tm), nch, tm, 14) 1483 1484 # nine time blocks, time = 0, 2, ..., 16 1485 def blk.go(hop: Nat, got: Bg, +nch: U32, +tm: U32) -> Bg: 1486 match hop got: 1487 case 0n Bg{st, gr, syn}: 1488 Bg{st, gr, syn} 1489 case 1n+p Bg{st, gr, syn}: 1490 blk.go(p, blk.one(Bg{st, gr, syn}, nch, tm), nch, u.add(tm, 2)) 1491 1492 # one even delay sample and the odd slot kept from the carried tail. 1493 # hop is the pairs still to come after this one. The sample was read at ii. 1494 def qmf.ev(hop: Nat, old: List<&2, F32>, got: La, +ii: U32, acc: List<&2, F32>) -> List<&2, F32>: 1495 match hop old got: 1496 case 0n +_e <> +odd <> _tl La{lin, +cur}: 1497 match lin: 1498 case _lin: 1499 List.reverse(&2, F32, odd <> (cur <> acc)) 1500 case 1n+p +_e <> +odd <> tl La{lin, +cur}: 1501 qmf.ev(p, tl, ln.at(lin, u.add(ii, 2)), u.add(ii, 2), odd <> (cur <> acc)) 1502 case _ _ La{lin, _v}: 1503 match lin: 1504 case _lin: 1505 List.reverse(&2, F32, acc) 1506 1507 # stereo tail: 960 delay-Array samples in one pull. The old list is dropped. 1508 def qmf.st(+old: List<&2, F32>, lin: Array) -> List<&2, F32>: 1509 match old: 1510 case _old: 1511 ln.pull(959n, ln.at(lin, 1152), 1152, []) 1512 1513 # mono keeps odd slots; stereo replaces the whole tail from the delay Array 1514 def qmf.pick(mono: Bool, +qmf: List<&2, F32>, lin: Array) -> List<&2, F32>: 1515 match mono: 1516 case True{}: 1517 qmf.ev(479n, qmf, ln.at(lin, 1152), 1152, []) 1518 case False{}: 1519 qmf.st(qmf, lin) 1520 1521 # save the 15-block tail off the delay Array, one pass, no List.set 1522 def qmf.save(lin: Array, +qmf: List<&2, F32>, +nch: U32) -> List<&2, F32>: 1523 qmf.pick(U32.is_eq(nch, 1), qmf, lin) 1524 1525 # PCM, the overlap to carry, and the polyphase delay 1526 type Pc is Data: 1527 Pc{pcm: List<&2, F32>, ov: List<&2, F32>, qmf: List<&2, F32>} 1528 1529 # zero overlap, 288 samples, one channel 1530 def syn.zov() -> List<&2, F32>: 1531 List.replicate(F32, 288n, 0.0) 1532 1533 # zero polyphase delay 1534 def syn.zqmf() -> List<&2, F32>: 1535 List.replicate(F32, 960n, 0.0) 1536 1537 # antialias, IMDCT, and the sign flip for one channel 1538 def ch.prep( 1539 acc: Array, +ov: List<&2, F32>, +aa: List<&2, F32>, +tw: List<&2, F32>, +win: List<&2, F32>, 1540 +base: U32 1541 ) -> Im: 1542 im.sign(im.go(32n, Im{aa.run(acc, aa, base), ov}, tw, win, 0, base), base) 1543 1544 # append the second channel's overlap. The spectrum Array already holds both. 1545 def syn.st2(+ova: List<&2, F32>, bb: Im) -> Im: 1546 match bb: 1547 case Im{buf, ovb}: 1548 Im{buf, List.append(&2, F32, ova, ovb)} 1549 1550 # join two channel states. The right channel starts at bin 576. 1551 def syn.st( 1552 aa: Im, +ovb: List<&2, F32>, +cs: List<&2, F32>, +tw: List<&2, F32>, +win: List<&2, F32> 1553 ) -> Im: 1554 match aa: 1555 case Im{buf, ova}: 1556 syn.st2(ova, ch.prep(buf, ovb, cs, tw, win, 576)) 1557 1558 # prepare one or two channels 1559 def syn.ch( 1560 mono: Bool, acc: Array, +ov: List<&2, F32>, +aa: List<&2, F32>, +tw: List<&2, F32>, 1561 +win: List<&2, F32> 1562 ) -> Im: 1563 match mono: 1564 case True{}: 1565 ch.prep(acc, ov, aa, tw, win, 0) 1566 case False{}: 1567 syn.st(ch.prep(acc, ls.slice(ov, 0, 288n), aa, tw, win, 0), ls.slice(ov, 288, 288n), aa, tw, win) 1568 1569 # tables shared by a granule. 2048 slots cover mono 576 and stereo 1152. 1570 def syn.ready(+spec: List<&2, F32>, +ov: List<&2, F32>, +nch: U32) -> Im: 1571 syn.ch(U32.is_eq(nch, 1), ln.fill(spec, Array.new(F32, 11n, 0.0), 0), ov, 1572 Enc.f.of(Tab.tab.aa()), Enc.f.of(Tab.tab.tw()), Enc.f.of(Tab.tab.winl())) 1573 1574 # second channel starts at bin 576 1575 def sy.dct2(mono: Bool, acc: Array, +sec: List<&2, F32>) -> Array: 1576 match mono: 1577 case True{}: 1578 dc.run(18n, acc, sec, 0) 1579 case False{}: 1580 dc.run(18n, dc.run(18n, acc, sec, 0), sec, 576) 1581 1582 # DCT-II of each channel. The spectrum Array is the one IMDCT just wrote. 1583 def sy.dct(mono: Bool, acc: Array, +sec: List<&2, F32>) -> Array: 1584 sy.dct2(mono, acc, sec) 1585 1586 # delay line: the carried tail, then zeros (4096-slot Array starts at 0.0) 1587 def sy.lin(+qmf: List<&2, F32>) -> Array: 1588 ln.fill(qmf, Array.new(F32, 12n, 0.0), 0) 1589 1590 # empty PCM for one granule (2048-slot Array covers mono 576 and stereo 1152) 1591 def sy.pcm() -> Array: 1592 Array.new(F32, 11n, 0.0) 1593 1594 # PCM Array back to a list of length 576*nch 1595 def sy.pcm.list(+nch: U32, pcm: Array) -> List<&2, F32>: 1596 ln.list(pcm, U32.to_nat(u.sub(u.mul(576, nch), 1))) 1597 1598 # the granule Array is finished once the nine blocks have read it 1599 def syn.drop(gr: Array, st: Sb, +ov: List<&2, F32>, +qmf: List<&2, F32>, +nch: U32) -> Pc: 1600 match gr: 1601 case _gr: 1602 match st: 1603 case Sb{lin, pcm}: 1604 Pc{sy.pcm.list(nch, pcm), ov, qmf.save(lin, qmf, nch)} 1605 1606 # run the polyphase and keep the overlap from the IMDCT 1607 def syn.out(got: Bg, +ov: List<&2, F32>, +qmf: List<&2, F32>, +nch: U32) -> Pc: 1608 match got: 1609 case Bg{st, gr, syn}: 1610 match syn: 1611 case _syn: 1612 syn.drop(gr, st, ov, qmf, nch) 1613 1614 # DCT-II then nine polyphase blocks. The spectrum Array is what the polyphase reads. 1615 def syn.pcm(buf: Array, +ov: List<&2, F32>, +qmf: List<&2, F32>, +nch: U32) -> Pc: 1616 syn.out(blk.go(9n, Bg{Sb{sy.lin(qmf), sy.pcm()}, sy.dct(U32.is_eq(nch, 1), buf, 1617 Enc.f.of(Tab.tab.sec())), sw.tab()}, nch, 0), ov, qmf, nch) 1618 1619 # synthesis of a prepared granule 1620 def syn.finish(st: Im, +qmf: List<&2, F32>, +nch: U32) -> Pc: 1621 match st: 1622 case Im{buf, ov}: 1623 syn.pcm(buf, ov, qmf, nch) 1624 1625 # one granule to PCM. spec is 576 samples per channel. ov is 288 per channel. 1626 def syn.gran(+spec: List<&2, F32>, +ov: List<&2, F32>, +qmf: List<&2, F32>, +nch: U32) -> Pc: 1627 syn.finish(syn.ready(spec, ov, nch), qmf, nch) 1628 1629 # IMDCT only, 32 bands, no antialias. Used to check the unit impulse. 1630 def syn.im(+buf: List<&2, F32>, +ov: List<&2, F32>) -> Im: 1631 im.go(32n, Im{ln.fill(buf, Array.new(F32, 11n, 0.0), 0), ov}, Enc.f.of(Tab.tab.tw()), 1632 Enc.f.of(Tab.tab.winl()), 0, 0) 1633 1634 # one PCM sample of a granule, as a binary32 word 1635 def syn.nth(st: Pc, +ii: U32) -> U32: 1636 match st: 1637 case Pc{pcm, _ov, _qmf}: 1638 Enc.f32.word(f.at(pcm, ii)) 1639 1640 # drop the spectrum Array once sample 0 has been read 1641 def syn.word1(got: Dx) -> U32: 1642 match got: 1643 case Dx{acc, v}: 1644 match acc: 1645 case _acc: 1646 Enc.f32.word(v) 1647 1648 # first sample of an IMDCT buffer, as a binary32 word 1649 def syn.word(st: Im) -> U32: 1650 match st: 1651 case Im{buf, _ov}: 1652 syn.word1(dx.at(buf, 0)) 1653 1654 # PCM word ii of one granule whose spectrum is a unit impulse at bin 0. 1655 def syn.probe(+ii: U32) -> U32: 1656 syn.nth(syn.gran(f.set(List.replicate(F32, 576n, 0.0), 0, Enc.f32.bits(1065353216)), syn.zov(), 1657 syn.zqmf(), 1), ii) 1658 1659 # unit impulse at bin 0. The first sample is the float32 word 1022453915. 1660 def syn.impulse() -> U32: 1661 syn.word(syn.im(f.set(List.replicate(F32, 576n, 0.0), 0, Enc.f32.bits(1065353216)), syn.zov()))