About Project:
This project uses Fourier synthesis to visualize complex waveforms by combining simple sine waves. The code calculates the Fourier coefficients for each waveform type and animates their construction in real-time. Users can see and hear how different sine wave combinations create various complex waveforms, enhancing their understanding of Fourier series and wave synthesis.
Overview:
This week's sketch is a prototype for visualizing waveforms through Fourier analysis. The Fourier transform is a mathematical method that decomposes functions or signals into their basic frequencies. It helps us understand complex waves by breaking them down into simpler components.
Ironically, my personal experience inspired this sketch. In high school, I struggled with the wave chapter in physics. Textbook diagrams made it hard to grasp the essence and context of waves. I didn't even understand what I was looking at; I just managed to pass the test by memorizing formulas without understanding the material. Recently, I found "Science & Music" by Sir James Hopwood Jeans on my studio's bookshelf. Reading it again after many years reminded me of those challenges.
This sketch aims to create a tool that could have helped my younger self and anyone facing similar difficulties. By offering an interactive, visual approach to waves and Fourier analysis, it may make these fundamental physics and math concepts more accessible. While my initial goal for this sketch is to improve my own understanding, it might also help other students with similar challenges. Users can adjust wave parameters and see changes in real-time, making it simpler to understand the relationship between abstract math and wave behavior. (For more details)
By the way, I should mention that I am not a programmer or mathematician. I undertook this project as a nighttime study, hobby, and form of meditation and art therapy. Feel free to correct me or provide feedback.
User Guide:
Desktop Users
- Waveform Selection — Click on the buttons to select the waveform type. Alternatively, use keyboard shortcuts:
key 1 = Sine Wave
key 2 = Square Wave
key 3 = Triangle Wave
key 4 = Sawtooth Wave.
- Sound Modulation — Click and drag the mouse vertically on the canvas to change the frequency of the waveform, and horizontally to adjust the harmonics of the waveform.
Mobile Users
- Waveform Selection — Tap on the buttons labeled "Sine", "Square", "Triangle", or "Sawtooth" to select the waveform type.
- Sound Modulation —Swipe vertically on the canvas to change the frequency of the waveform, and horizontally to adjust the harmonics of the waveform.
*Please turn on your volume.
This work is licensed under CC BY-NC-SA 4.0
สมัยเรียนมัธยมผมเคยคิดว่าตัวเองชอบฟิสิกส์ เพราะในมุมของเด็กที่เรียนไม่ทันเพื่อนในห้อง ฟิสิกส์เป็นหนึ่งในวิชาที่อ่านเองได้ สูตรก็มีให้ เนื้อหาก็เป็นเรื่องรอบตัวที่พอจะคิดตามได้ เป็นวิชาว่าด้วยเรื่องกายภาพที่เราพอจะจินตนาการตามได้ว่าเกิดอะไรขึ้นบ้าง มีความเป็นรูปธรรมกว่าวิชาคณิตศาสตร์
แต่ก็มีบางบทเรียนเช่นเรื่องคลื่น ที่ผมอ่านแล้วไม่เข้าใจ พอจะทำข้อสอบได้บ้างจากการใช้สูตรแก้โจทย์หาคำตอบแบบไม่ได้เข้าใจ จนเวลาผ่านไปสักพัก ผมเพิ่งจินตนาการตามได้ว่าบทเรียนเรื่องคลื่นที่เรียนไปนั้น คือการทำความเข้าใจรูปแบบการเคลื่อนที่ของพลังงานผ่านสื่อกลางชนิดต่าง ๆ
งานสเก็ตช์ชิ้นนี้นี้เป็นต้นแบบสำหรับการแสดงผลรูปคลื่นผ่านการวิเคราะห์ฟูริเยร์ วิธีการทางคณิตศาสตร์ที่สามารถแยกแยะฟังก์ชันหรือสัญญาณออกมาเป็นความถี่พื้นฐาน ช่วยให้เราเข้าใจคลื่นที่ซับซ้อนได้ง่ายขึ้น โดยแยกส่วนประกอบของมันออกมาครับ ผมทำเสร็จแล้วลองเล่นเองก็แปลกใจเองเหมือนกันว่าคลื่นที่ดูซับซ้อน เช่น คลื่นรูปสี่เหลี่ยมจตุรัส, คลื่นรูปสามเหลี่ยม, หรือ คลื่นรูปฟันเลื่อย สามารถสร้างจากคลื่นซายน์มาประกอบกันต่อเนื่องแบบนี้ได้ด้วย (รายละเอียดเพิ่มเติม)
สเก็ตช์นี้เกิดจากความสงสัยของผมเอง ก็เลยลองทำขึ้นมาเพื่อหาวิธีอธิบายตัวเองในอดีตว่าถ้าต้องย้อนกลับไปอธิบายตัวเองในวันนั้นจะอธิบายอย่างไร ก็อาจจะยังอธิบายได้ไม่ดีนัก เพราะไม่ได้กระจ่างขนาดสามารถเขียนออกมาให้เรียบง่ายได้ครับ แต่อย่างน้อยก็น่าจะทำให้เห็นภาพได้ง่ายขึ้นบ้าง
ขออธิบายเพิ่มเติมว่าผมไม่ใช่โปรแกรมเมอร์หรือนักคณิตศาสตร์ ผมทำโปรเจกต์นี้เพื่อเป็นการศึกษาภาคค่ำในเรื่องที่ผมสนใจ โดยรวบการเรียนการทดลองลักษณะนี้ไว้กับการทำงานศิลปะบำบัด ทำสมาธิไปด้วยในเวลาเดียวกันครับ
ขอบคุณครับ
2024.07.07
*This program was made using p5.js, a JavaScript library for creative coding, and the Web Audio API, a tool for audio processing in web applications.
Appendix A: Key Aspects
This project provides a real-time visualization and interactive experience of Fourier synthesis, illustrating how complex waveforms—such as sine, square, triangle, and sawtooth waves—can be constructed by adding together simple sine waves. Additionally, by combining visual elements with sound, the project aims to make the principles of the Fourier series easier to understand. I hope this can help audiences see how different complex waveforms are formed through the combination of basic sine waves and how they might perceive the beauty of complexity created from simplicity.
Fourier Coefficients and Waveform Construction:
Fourier synthesis involves creating complex waveforms by adding multiple sine waves with different frequencies, amplitudes, and phases.
Complex waveforms such as square, triangle, and sawtooth waves are synthesized by combining sine waves (harmonics) with specific frequencies and amplitudes. Each type of waveform has a unique harmonic structure.
Sine Wave:
-
-
: The waveform function at time
: Amplitude of the wave
: Fundamental frequency of the wave
: Time variable
-
Code Implementation:
if (waveform === 'sine') {
fourierX.push({ freq: 1, amp: A, phase: 0 });
}
A sine wave is the simplest waveform, characterized by a single frequency and amplitude. It serves as the fundamental building block for more complex waveforms.
Square Wave:
-
-
: The waveform function at time
: Amplitude of the wave
: Fundamental frequency of the wave
: Time variable
: Harmonic number
-
Code Implementation:
if (waveform === 'square') {
for (let i = 0; i < N; i++) {
let k = 2 * i + 1;
let amplitude = (4 * A) / (k * PI);
fourierX.push({ freq: k, amp: amplitude, phase: 0 });
}
}
A square wave is constructed by summing only the odd harmonics (1st, 3rd, 5th, etc.). Each harmonic has an amplitude inversely proportional to its frequency, resulting in a waveform with sharp transitions between high and low values. The formula shows that the amplitude of each harmonic is , where
is the harmonic index.
Triangle Wave:
-
-
: The waveform function at time
: Amplitude of the wave
: Fundamental frequency of the wave
: Time variable
: Harmonic number
-
Code Implementation:
if (waveform === 'triangle') {
for (let i = 0; i < N; i++) {
let k = 2 * i + 1;
let amplitude = (8 * A) / ((k * k) * PI * PI);
if (i % 2 !== 0) {
amplitude = -amplitude;
}
fourierX.push({ freq: k, amp: amplitude, phase: 0 });
}
}
A triangle wave is created using only the odd harmonics. Their amplitudes decrease more rapidly (proportional to the square of the harmonic number) and alternate in sign. This produces a waveform with a linear rise and fall, resembling a triangle. The formula indicates that the amplitude of each harmonic is with alternating signs due to
.
Sawtooth Wave:
-
-
: The waveform function at time
: Amplitude of the wave
: Fundamental frequency of the wave
: Time variable
: Harmonic number
-
Code Implementation:
if (waveform === 'sawtooth') {
for (let i = 0; i < N; i++) {
let k = i + 1;
let amplitude = (2 * A) / (k * PI);
fourierX.push({ freq: k, amp: amplitude, phase: 0 });
}
}
A sawtooth wave includes all harmonics (1st, 2nd, 3rd, etc.) with amplitudes decreasing as . This results in a waveform that ramps linearly upwards and then drops sharply, creating its characteristic linear rise and sharp drop.
Appendix B: Sample Usage for Visualization
In this project the computeFourierCoefficients
function calculates the coefficients for the selected waveform. This function determines the amplitude and frequency components necessary to approximate the selected waveform using Fourier series.
function computeFourierCoefficients() {
fourierX = [];
let A = 1; // Set amplitude to 1 for simplicity
if (waveform === 'sine') {
fourierX.push({ freq: 1, amp: A, phase: 0 });
} else if (waveform === 'square') {
for (let k = 0; k < N; k++) {
let n = 2 * k + 1;
let amplitude = (4 * A) / (n * Math.PI);
fourierX.push({ freq: n, amp: amplitude, phase: 0 });
}
} else if (waveform === 'triangle') {
for (let k = 0; k < N; k++) {
let n = 2 * k + 1;
let amplitude = (8 * A) / ((n * n) * Math.PI * Math.PI);
if (k % 2 !== 0) {
amplitude = -amplitude;
}
fourierX.push({ freq: n, amp: amplitude, phase: 0 });
}
} else if (waveform === 'sawtooth') {
for (let k = 0; k < N; k++) {
let n = k + 1;
let amplitude = (2 * A) / (n * Math.PI);
fourierX.push({ freq: n, amp: amplitude, phase: 0 });
}
}
}
Parameters and Variables:
fourierX
: An array to store the calculated Fourier coefficients.A
: The amplitude of the waveform, set to 1 for simplicity.waveform
: A string that specifies the selected waveform type ('sine'
,'square'
,'triangle'
, or'sawtooth'
).N
: The number of harmonics to include in the Fourier series.k
: An integer index used in the loop to calculate the harmonics.n
: The harmonic number, which depends on the waveform type:- For square and triangle waves,
n
is calculated as2 * k + 1
(odd harmonics). - For sawtooth waves,
n
is calculated ask + 1
(all harmonics).
- For square and triangle waves,
amplitude
: The amplitude of the nth harmonic, calculated based on the waveform type and the harmonic numbern
.freq
: The frequency of the nth harmonic, stored in thefourierX
array.phase
: The phase of the nth harmonic, set to 0 for simplicity.
This function calculates the Fourier coefficients for different waveform types. By adding up the necessary harmonics and storing their frequency, amplitude, and phase, the coefficients are then used to create the visual and sound representation of the waveform in this sketch.