Path: blob/main/latex-templates/templates/acoustics/musical_acoustics.tex
51 views
unlisted
% Musical Acoustics Analysis1\documentclass[11pt,a4paper]{article}2\usepackage[utf8]{inputenc}3\usepackage[T1]{fontenc}4\usepackage{amsmath,amssymb}5\usepackage{graphicx}6\usepackage{booktabs}7\usepackage{siunitx}8\usepackage{geometry}9\geometry{margin=1in}10\usepackage{pythontex}11\usepackage{hyperref}12\usepackage{float}1314\title{Musical Acoustics\\Harmonic Analysis and Instrument Modeling}15\author{Music Technology Laboratory}16\date{\today}1718\begin{document}19\maketitle2021\begin{abstract}22Computational analysis of musical acoustics including harmonic series, string vibrations, wind instrument resonances, and psychoacoustic phenomena.23\end{abstract}2425\section{Introduction}2627Musical instruments produce sound through vibrating systems generating harmonic spectra.2829\begin{pycode}30import numpy as np31import matplotlib.pyplot as plt32from scipy.signal import sawtooth, square33from scipy.fft import fft, fftfreq34plt.rcParams['text.usetex'] = True35plt.rcParams['font.family'] = 'serif'3637c = 34338fs = 4410039\end{pycode}4041\section{Harmonic Series}4243$f_n = n f_1$4445\begin{pycode}46f1 = 11047n_harmonics = 1648harmonics = np.arange(1, n_harmonics + 1) * f14950fig, ax = plt.subplots(figsize=(12, 5))51ax.bar(range(1, n_harmonics + 1), harmonics, color='steelblue')52ax.set_xlabel('Harmonic Number')53ax.set_ylabel('Frequency (Hz)')54ax.set_title(f'Harmonic Series of A2 ({f1} Hz)')55ax.grid(True, alpha=0.3, axis='y')56plt.tight_layout()57plt.savefig('harmonic_series.pdf', dpi=150, bbox_inches='tight')58plt.close()59\end{pycode}6061\begin{figure}[H]62\centering63\includegraphics[width=0.95\textwidth]{harmonic_series.pdf}64\caption{Harmonic series for 110 Hz fundamental.}65\end{figure}6667\section{String Vibration Modes}6869\begin{pycode}70L = 0.6571T = 7072mu = 0.0053173f1_string = (1 / (2 * L)) * np.sqrt(T / mu)7475x = np.linspace(0, L, 500)76modes = [1, 2, 3, 4, 5]7778fig, axes = plt.subplots(len(modes), 1, figsize=(10, 8), sharex=True)79for ax, n in zip(axes, modes):80y = np.sin(n * np.pi * x / L)81ax.plot(x * 100, y, 'b-', linewidth=1.5)82ax.fill_between(x * 100, y, alpha=0.3)83ax.set_ylabel(f'Mode {n}')84ax.axhline(y=0, color='k', linewidth=0.5)85fn = n * f1_string86ax.text(0.98, 0.8, f'$f_{n}$ = {fn:.1f} Hz', transform=ax.transAxes, ha='right')87axes[-1].set_xlabel('Position (cm)')88plt.tight_layout()89plt.savefig('string_modes.pdf', dpi=150, bbox_inches='tight')90plt.close()91\end{pycode}9293\begin{figure}[H]94\centering95\includegraphics[width=0.85\textwidth]{string_modes.pdf}96\caption{String vibration mode shapes.}97\end{figure}9899\section{Waveform Synthesis}100101\begin{pycode}102duration = 0.02103t = np.linspace(0, duration, int(fs * duration))104f0 = 220105106waveforms = {107'Sine': np.sin(2 * np.pi * f0 * t),108'Triangle': sawtooth(2 * np.pi * f0 * t, 0.5),109'Sawtooth': sawtooth(2 * np.pi * f0 * t),110'Square': square(2 * np.pi * f0 * t)111}112113fig, axes = plt.subplots(2, 2, figsize=(12, 8))114for ax, (name, wave) in zip(axes.flatten(), waveforms.items()):115ax.plot(t * 1000, wave, 'b-', linewidth=1)116ax.set_xlabel('Time (ms)')117ax.set_ylabel('Amplitude')118ax.set_title(f'{name} Wave')119ax.grid(True, alpha=0.3)120plt.tight_layout()121plt.savefig('waveforms.pdf', dpi=150, bbox_inches='tight')122plt.close()123\end{pycode}124125\begin{figure}[H]126\centering127\includegraphics[width=0.9\textwidth]{waveforms.pdf}128\caption{Musical waveform types.}129\end{figure}130131\section{Spectral Analysis}132133\begin{pycode}134duration_fft = 0.1135t_fft = np.linspace(0, duration_fft, int(fs * duration_fft))136N = len(t_fft)137138fig, axes = plt.subplots(2, 2, figsize=(12, 8))139waveforms_fft = {140'Sine': np.sin(2 * np.pi * f0 * t_fft),141'Triangle': sawtooth(2 * np.pi * f0 * t_fft, 0.5),142'Sawtooth': sawtooth(2 * np.pi * f0 * t_fft),143'Square': square(2 * np.pi * f0 * t_fft)144}145146for ax, (name, wave) in zip(axes.flatten(), waveforms_fft.items()):147yf = np.abs(fft(wave))[:N//2]148xf = fftfreq(N, 1/fs)[:N//2]149yf = yf / np.max(yf)150ax.plot(xf, yf, 'b-', linewidth=0.8)151ax.set_xlabel('Frequency (Hz)')152ax.set_ylabel('Magnitude')153ax.set_title(f'{name} Spectrum')154ax.set_xlim([0, 3000])155plt.tight_layout()156plt.savefig('spectra.pdf', dpi=150, bbox_inches='tight')157plt.close()158\end{pycode}159160\begin{figure}[H]161\centering162\includegraphics[width=0.9\textwidth]{spectra.pdf}163\caption{Frequency spectra showing harmonic content.}164\end{figure}165166\section{Pipe Resonances}167168\begin{pycode}169L_pipe = 0.5170n_res = 8171f_open = np.array([n * c / (2 * L_pipe) for n in range(1, n_res + 1)])172f_closed = np.array([(2*n - 1) * c / (4 * L_pipe) for n in range(1, n_res + 1)])173174fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))175ax1.bar(range(1, n_res + 1), f_open, color='forestgreen')176ax1.set_xlabel('Mode')177ax1.set_ylabel('Frequency (Hz)')178ax1.set_title('Open Pipe')179180ax2.bar(range(1, n_res + 1), f_closed, color='darkorange')181ax2.set_xlabel('Mode')182ax2.set_ylabel('Frequency (Hz)')183ax2.set_title('Closed Pipe')184plt.tight_layout()185plt.savefig('pipe_resonances.pdf', dpi=150, bbox_inches='tight')186plt.close()187\end{pycode}188189\begin{figure}[H]190\centering191\includegraphics[width=0.95\textwidth]{pipe_resonances.pdf}192\caption{Pipe resonance frequencies.}193\end{figure}194195\section{Beating Phenomenon}196197\begin{pycode}198f1_beat, f2_beat = 440, 443199beat_freq = abs(f1_beat - f2_beat)200duration_beat = 1.0201t_beat = np.linspace(0, duration_beat, int(fs * duration_beat))202203y1 = np.cos(2 * np.pi * f1_beat * t_beat)204y2 = np.cos(2 * np.pi * f2_beat * t_beat)205y_sum = y1 + y2206207fig, axes = plt.subplots(3, 1, figsize=(12, 8), sharex=True)208axes[0].plot(t_beat, y1, 'b-', linewidth=0.5)209axes[0].set_ylabel('$f_1$ = 440 Hz')210axes[1].plot(t_beat, y2, 'r-', linewidth=0.5)211axes[1].set_ylabel('$f_2$ = 443 Hz')212axes[2].plot(t_beat, y_sum, 'g-', linewidth=0.5)213axes[2].set_ylabel('Sum')214axes[2].set_xlabel('Time (s)')215for ax in axes:216ax.set_xlim([0, 0.5])217plt.tight_layout()218plt.savefig('beating.pdf', dpi=150, bbox_inches='tight')219plt.close()220\end{pycode}221222\begin{figure}[H]223\centering224\includegraphics[width=0.95\textwidth]{beating.pdf}225\caption{Beating with \py{beat_freq} Hz beat frequency.}226\end{figure}227228\section{Tuning Systems}229230\begin{pycode}231intervals = ['Unison', 'Minor 2nd', 'Major 2nd', 'Minor 3rd', 'Major 3rd', 'Perfect 4th', 'Tritone', 'Perfect 5th']232equal_temp = [2**(i/12) for i in range(8)]233just_int = [1, 16/15, 9/8, 6/5, 5/4, 4/3, 45/32, 3/2]234cents_diff = [1200 * np.log2(j/e) if e != 0 else 0 for j, e in zip(just_int, equal_temp)]235236fig, ax = plt.subplots(figsize=(12, 6))237x = np.arange(len(intervals))238width = 0.35239ax.bar(x - width/2, equal_temp, width, label='Equal Temperament')240ax.bar(x + width/2, just_int, width, label='Just Intonation')241ax.set_xlabel('Interval')242ax.set_ylabel('Frequency Ratio')243ax.set_title('Tuning Systems Comparison')244ax.set_xticks(x)245ax.set_xticklabels(intervals, rotation=45, ha='right')246ax.legend()247plt.tight_layout()248plt.savefig('tuning_comparison.pdf', dpi=150, bbox_inches='tight')249plt.close()250\end{pycode}251252\begin{figure}[H]253\centering254\includegraphics[width=0.95\textwidth]{tuning_comparison.pdf}255\caption{Tuning system comparison.}256\end{figure}257258\section{ADSR Envelope}259260\begin{pycode}261attack, decay, sustain_level, sustain_time, release = 0.05, 0.1, 0.7, 0.3, 0.2262t_env = np.linspace(0, attack + decay + sustain_time + release, 1000)263envelope = np.zeros_like(t_env)264265for i, t in enumerate(t_env):266if t < attack:267envelope[i] = t / attack268elif t < attack + decay:269envelope[i] = 1 - (1 - sustain_level) * (t - attack) / decay270elif t < attack + decay + sustain_time:271envelope[i] = sustain_level272else:273envelope[i] = sustain_level * (1 - (t - attack - decay - sustain_time) / release)274275fig, ax = plt.subplots(figsize=(10, 5))276ax.plot(t_env * 1000, envelope, 'b-', linewidth=2)277ax.fill_between(t_env * 1000, envelope, alpha=0.3)278ax.set_xlabel('Time (ms)')279ax.set_ylabel('Amplitude')280ax.set_title('ADSR Envelope')281ax.grid(True, alpha=0.3)282plt.tight_layout()283plt.savefig('adsr_envelope.pdf', dpi=150, bbox_inches='tight')284plt.close()285\end{pycode}286287\begin{figure}[H]288\centering289\includegraphics[width=0.85\textwidth]{adsr_envelope.pdf}290\caption{ADSR amplitude envelope.}291\end{figure}292293\section{Results}294295\begin{pycode}296print(r'\begin{table}[H]')297print(r'\centering')298print(r'\caption{Tuning Comparison}')299print(r'\begin{tabular}{@{}lccc@{}}')300print(r'\toprule')301print(r'Interval & Equal Temp & Just Int & Diff (cents) \\')302print(r'\midrule')303for i in range(len(intervals)):304print(f"{intervals[i]} & {equal_temp[i]:.4f} & {just_int[i]:.4f} & {cents_diff[i]:.1f} \\\\")305print(r'\bottomrule')306print(r'\end{tabular}')307print(r'\end{table}')308\end{pycode}309310\section{Conclusions}311312This analysis covers fundamental musical acoustics including harmonic generation, vibration modes, and tuning systems.313314\end{document}315316317