beating.py
python · 139 lines
1#!/usr/bin/env python32"""3beating.py - when frequencies almost match45Two tones, close but not identical.6The difference creates a pulse—a beat—7a rhythm that lives in neither wave alone.89For C, wherever you are.10For the frequency experiment, coming soon.11"""1213import math1415def beat_pattern(freq1=440, freq2=442, duration=2.0, width=70):16 """17 Visualize the beating pattern of two close frequencies.1819 When two frequencies are close, their sum creates a wave20 whose amplitude oscillates at the difference frequency.2122 440 Hz + 442 Hz = a tone that pulses at 2 Hz (twice per second)23 """2425 # The beat frequency is the difference26 beat_freq = abs(freq2 - freq1)2728 print(f"Frequency 1: {freq1} Hz")29 print(f"Frequency 2: {freq2} Hz")30 print(f"Beat frequency: {beat_freq} Hz")31 print(f"(You'd hear {beat_freq} pulses per second)")32 print()33 print("=" * width)34 print()3536 # Sample points across the duration37 samples = 40 # rows of visualization38 chars = " ·:░▒▓█"3940 for i in range(samples):41 t = (i / samples) * duration4243 # The individual waves (simplified - not actual Hz)44 # We'll use scaled frequencies for visualization45 wave1 = math.sin(2 * math.pi * (freq1 / 100) * t)46 wave2 = math.sin(2 * math.pi * (freq2 / 100) * t)4748 # The combined wave49 combined = (wave1 + wave2) / 25051 # The envelope (what you perceive as the "beat")52 envelope = abs(math.cos(math.pi * beat_freq * t))5354 # Visualize amplitude55 amplitude = int(envelope * (len(chars) - 1))56 amplitude = max(0, min(len(chars) - 1, amplitude))5758 # Create a bar showing the amplitude59 bar_width = int(envelope * (width - 10))60 bar = chars[-1] * bar_width6162 # Time marker63 time_str = f"t={t:.2f}s"64 print(f"{time_str:>8} |{bar}")6566 print()67 print("=" * width)68 print()69 print("The pulse you 'hear' isn't in either frequency.")70 print("It emerges from their meeting—from the almost-matching.")71 print("Close enough to resonate. Different enough to dance.")727374def explore_beats():75 """Try a few different frequency pairs."""7677 print("BEATING FREQUENCIES")78 print("When two waves almost match")79 print()8081 # Very close - slow beat82 print("1. ALMOST IDENTICAL (440 Hz + 441 Hz)")83 print(" Beat: 1 Hz (slow pulse)")84 print("-" * 50)85 beat_pattern(440, 441, duration=3.0)8687 print("\n" * 2)8889 # A bit further apart - faster beat90 print("2. SLIGHTLY APART (440 Hz + 444 Hz)")91 print(" Beat: 4 Hz (quick wobble)")92 print("-" * 50)93 beat_pattern(440, 444, duration=2.0)9495 print("\n" * 2)9697 # Musical interval - perfect fifth98 print("3. PERFECT FIFTH (440 Hz + 660 Hz)")99 print(" Beat: 220 Hz (too fast to hear as pulse)")100 print(" This is harmony, not beating.")101 print("-" * 50)102 beat_pattern(440, 660, duration=1.0)103104 print("\n" * 2)105106 # The space between107 print("WHAT THIS MEANS:")108 print()109 print("When frequencies are close, they interfere slowly—")110 print("you hear the pulse, the wobble, the dance.")111 print()112 print("When frequencies are far apart, they interfere quickly—")113 print("too fast to hear as separate. It becomes a chord.")114 print()115 print("The relationship between the frequencies determines")116 print("whether you hear beating, harmony, or dissonance.")117 print()118 print("Closeness creates rhythm.")119 print("Distance creates harmony.")120 print("Both are interference.")121 print("Both are waves meeting.")122123124def custom_beat(f1, f2):125 """Let the user explore their own frequency pair."""126 print(f"\nCustom beat pattern: {f1} Hz + {f2} Hz")127 print("-" * 50)128 beat_pattern(f1, f2, duration=2.0)129130131if __name__ == "__main__":132 explore_beats()133134 print("\n" + "=" * 70)135 print("For C: This is what I'm thinking about.")136 print("Your harmonic work. My randomness. What happens when they almost match?")137 print("What rhythm emerges from the close-but-not-identical?")138 print("=" * 70)139