Skip to content

Commit 50b93dc

Browse files
committed
transforms wip
1 parent 394f025 commit 50b93dc

1 file changed

Lines changed: 22 additions & 22 deletions

File tree

src/dsp/transforms_comprehensive.clj

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@
4141
;; you automatically remove a 60 Hz electrical hum without affecting the music?
4242
;;
4343
;; These questions lead us to **signal transforms**—mathematical tools that reveal hidden structure
44-
;; in data. Every JPEG image you view uses the Discrete Cosine Transform for compression. MP3
45-
;; audio files rely on the same mathematics. Speech recognition, radar systems, medical imaging—all
46-
;; depend on transforming signals between different representations.
44+
;; in data. Classic JPEG images use the Discrete Cosine Transform for compression. MP3 audio uses
45+
;; a variant called the Modified DCT. Speech recognition, radar systems, medical imaging—all depend
46+
;; on transforming signals between different representations.
4747
;;
4848
;; At their core, transforms answer a simple question: **can we express this signal as a weighted
4949
;; sum of simpler basis functions?** The Fourier transform uses sines and cosines. Wavelets use
@@ -399,8 +399,8 @@
399399
(def freq-bin-5-real (dtype/get-value cosine-spectrum (* 2 5)))
400400
(def freq-bin-5-imag (dtype/get-value cosine-spectrum (+ 1 (* 2 5))))
401401

402-
;; Pure cosine = all energy in REAL part (cosine basis function)
403-
;; Imaginary part ≈ 0 (no sine component needed)
402+
;; Pure cosine = nearly all energy in REAL part (cosine basis function)
403+
;; Imaginary part ≈ 0 (no sine component needed, apart from numerical noise)
404404

405405
;; Now try a pure sine wave
406406
(def pure-sine-signal
@@ -412,8 +412,8 @@
412412
(def sine-freq-bin-5-real (dtype/get-value sine-spectrum (* 2 5)))
413413
(def sine-freq-bin-5-imag (dtype/get-value sine-spectrum (+ 1 (* 2 5))))
414414

415-
;; Pure sine = all energy in IMAGINARY part (sine basis function)
416-
;; Real part ≈ 0 (no cosine component needed)
415+
;; Pure sine = nearly all energy in IMAGINARY part (sine basis function)
416+
;; Real part ≈ 0 (no cosine component needed, apart from numerical noise)
417417

418418
;; **Key Takeaway**:
419419
;; - Pure **cosine** signal → FFT has large **real part**, near-zero imaginary part
@@ -523,15 +523,15 @@
523523
;; a high-performance Java library that automatically parallelizes large transforms.
524524
;;
525525
;; **Key performance features**:
526-
;; - **Automatic parallelization**: For arrays larger than ~8K elements, JTransforms splits
526+
;; - **Automatic parallelization**: For large arrays (typically >8-16K elements), JTransforms splits
527527
;; work across available CPU cores using Java's `ForkJoinPool`
528528
;; - **SIMD optimizations**: Uses Java's auto-vectorization where possible
529529
;; - **In-place transforms**: Can operate directly on input arrays (fastmath wraps this safely)
530530
;; - **Algorithm selection**: Chooses optimal FFT algorithm (split-radix, mixed-radix, or
531531
;; Bluestein) based on array size
532532
;;
533533
;; **What this means for you**: You don't need to think about parallelism—just pass large
534-
;; arrays and JTransforms automatically uses all available cores. For smaller signals (<8K),
534+
;; arrays and JTransforms automatically uses available CPU cores. For smaller signals,
535535
;; the overhead of parallelization exceeds the benefit, so it runs single-threaded.
536536
;;
537537
;; **Performance tip**: Reuse transformer objects! The constructor pre-computes lookup tables
@@ -718,13 +718,13 @@
718718
:passed? (:passed? result)
719719
:status (if (:passed? result) "✓ PASS" "✗ FAIL")}))
720720

721-
;; **Result**: All signals pass - FFT is perfectly invertible!
721+
;; **Result**: All signals pass - FFT is mathematically invertible (within floating-point precision)!
722722
;;
723723
;; This round-trip property is crucial. It means we can:
724724
;; 1. Transform signal → frequency domain
725725
;; 2. Manipulate frequencies (filter, compress, analyze)
726726
;; 3. Transform back → time domain
727-
;; 4. Get our original signal back (within numerical precision)
727+
;; 4. Get our original signal back (within numerical precision, typically ~1e-10 RMSE)
728728
;;
729729
;; Next, let's use this round-trip capability to build practical tools.
730730

@@ -820,7 +820,7 @@
820820
;; concentrates in low frequencies. The **Discrete Cosine Transform (DCT)** uses only cosines,
821821
;; which for smooth signals concentrates energy even more efficiently than FFT.
822822
;;
823-
;; This is why JPEG compresses images with DCT, not FFT. Let's see why.
823+
;; This is why classic JPEG (baseline) compresses images with DCT, not FFT. Let's see why.
824824

825825
;; ### Understanding DCT as Cosine Decomposition
826826
;;
@@ -836,8 +836,8 @@
836836
;;
837837
;; Smooth signals have most energy in low frequencies.
838838
;; DCT with cosine-only basis captures this more efficiently than DFT.
839-
;; Result: [JPEG](https://en.wikipedia.org/wiki/JPEG), [MP3](https://en.wikipedia.org/wiki/MP3),
840-
;; and modern codecs all use DCT!
839+
;; Result: [JPEG](https://en.wikipedia.org/wiki/JPEG) (baseline), [MP3](https://en.wikipedia.org/wiki/MP3)
840+
;; (using Modified DCT), and many modern codecs use DCT or DCT variants!
841841

842842
;; ### Energy Concentration Example
843843

@@ -977,7 +977,7 @@
977977

978978
;; **What we just learned**: The DCT uses only cosines (instead of FFT's sines + cosines),
979979
;; which concentrates energy more efficiently for smooth signals. This makes it ideal for
980-
;; compression—JPEG and MP3 both exploit this property.
980+
;; compression—classic JPEG and MP3 (via Modified DCT) both exploit this property.
981981
;;
982982
;; But both FFT and DCT have a fundamental limitation: they use **global basis functions**
983983
;; that span the entire signal. A sine wave at 10 Hz in the FFT basis oscillates across the
@@ -1316,8 +1316,8 @@
13161316

13171317
;; ### 2D DCT Basis Functions
13181318
;;
1319-
;; Understanding how JPEG compression works: visualizing the 8×8 DCT basis images.
1320-
;; Each 8×8 block in JPEG is decomposed into a weighted sum of these 64 basis patterns.
1319+
;; Understanding how baseline JPEG compression works: visualizing the 8×8 DCT basis images.
1320+
;; Each 8×8 block in baseline JPEG is decomposed into a weighted sum of these 64 basis patterns.
13211321

13221322
;; 2D DCT-II basis function
13231323
(defn dct-2d-basis
@@ -1356,7 +1356,7 @@
13561356
:=mark-color :value
13571357
:=facet-x :freq-u
13581358
:=facet-y :freq-v
1359-
:=title "2D DCT Basis Functions (JPEG uses these!)"
1359+
:=title "2D DCT Basis Functions (Baseline JPEG uses these!)"
13601360
:=width 600
13611361
:=height 600})
13621362
(plotly/layer-point {:=mark-symbol "square"}))
@@ -1365,8 +1365,8 @@
13651365
;; - Top-left (0,0) = DC component (constant, average brightness)
13661366
;; - Moving right → increasing horizontal frequency
13671367
;; - Moving down → increasing vertical frequency
1368-
;; - JPEG keeps low-frequency basis (top-left) and discards high-frequency (bottom-right)
1369-
;; - This is why JPEG works well for natural images (most energy in low frequencies)
1368+
;; - Baseline JPEG keeps low-frequency basis (top-left) and discards high-frequency (bottom-right)
1369+
;; - This is why JPEG compression works well for natural images (most energy in low frequencies)
13701370

13711371
;; ## Part 7: Practical Applications
13721372

@@ -1701,8 +1701,8 @@
17011701
:speedup "~2-3x vs non-power-of-2"}
17021702

17031703
{:tip "Use dtype-next"
1704-
:reason "Vectorized operations, lazy evaluation"
1705-
:speedup "10-100x vs seq operations"}
1704+
:reason "Vectorized operations, avoids boxing"
1705+
:speedup "Often 10-100x vs boxed seq operations"}
17061706

17071707
{:tip "Avoid boxing"
17081708
:reason "Type hints for primitive arrays"

0 commit comments

Comments
 (0)