# ================================================================================ # Timing Generator # Use to manually create a timing array for synchronizing LED brightness to audio dialogue. # ================================================================================ # Release Version: 2025.1.0 # Initial code generated by Claude Sonnet 4 on 2025-08-10 # ================================================================================ import time import keyboard import threading # Configuration output_filename = "test.tim" # Output timing file max_brightness = 255 # Peak brightness for syllables baseline_brightness = 50 # Baseline brightness between syllables class TimingRecorder: def __init__(self): self.events = [] self.start_time = None self.recording = False def countdown_timer(self): """Added by Claude: 5-second countdown timer that prints every 0.1 seconds""" print("\n🕐 Starting 5-second countdown...") for i in range(50, 0, -1): # Added by Claude: Count from 50 to 1 (5.0 to 0.1 seconds) remaining_time = i / 10.0 # Added by Claude: Convert to decimal seconds print(f"\r⏳ {remaining_time:.1f} seconds remaining...", end='', flush=True) # Added by Claude: Print countdown with carriage return time.sleep(0.1) # Added by Claude: Wait 0.1 seconds between updates print("\n🎬 GO! Start tapping for syllables!\n") # Added by Claude: Signal that countdown is complete def start_recording(self): """Start timing recording""" print("=== Audio Timing Recorder ===") print("Instructions:") print("1. Press ENTER to start recording") print("2. Play your audio file") print("3. Press SPACEBAR, N, or M on each syllable/word") # Modified by Claude: Updated instructions for new trigger keys print("4. Press ESC when done") print() input("Press ENTER to start recording...") print(f"\n🔴 RECORDING STARTED") # Added by Claude: Call the countdown timer function BEFORE setting start_time self.countdown_timer() # Fixed by Claude: Set start_time AFTER countdown to prevent 5-second offset self.start_time = time.time() self.recording = True print("Play your audio now!") print("Tap SPACEBAR, N, or M for each syllable") # Modified by Claude: Updated instruction for new trigger keys print("Press ESC to stop\n") # Add baseline event at start self.events.append((0, baseline_brightness)) def add_event(self): """Add timing event when spacebar is pressed""" if not self.recording: return current_time = time.time() elapsed_ms = int((current_time - self.start_time) * 1000) # Add peak brightness event self.events.append((elapsed_ms, max_brightness)) print(f"⚡ Syllable at {elapsed_ms}ms") # Schedule baseline event 200ms later (adjust this timing as needed) fade_delay = 200 self.events.append((elapsed_ms + fade_delay, baseline_brightness)) def stop_recording(self): """Stop recording and save file""" if not self.recording: return self.recording = False print(f"\n🟢 RECORDING STOPPED") # Sort events by timestamp self.events.sort() # Save to file with open(output_filename, 'w') as f: for timestamp, brightness in self.events: f.write(f"{timestamp},{brightness}\n") print(f"📁 Saved {len(self.events)} events to {output_filename}") self.print_summary() def print_summary(self): """Print recording summary""" if not self.events: return duration = self.events[-1][0] / 1000.0 syllable_count = len([e for e in self.events if e[1] == max_brightness]) print(f"\nRecording Summary:") print(f"Duration: {duration:.1f} seconds") print(f"Syllables: {syllable_count}") print(f"Events: {len(self.events)}") print(f"\nFile ready for ESP32!") def main(): recorder = TimingRecorder() # Start recording recorder.start_recording() try: while recorder.recording: # Wait for key presses event = keyboard.read_event() if event.event_type == keyboard.KEY_DOWN: if event.name in ['space', 'n', 'm']: # Modified by Claude: Added 'n' and 'm' as trigger keys along with spacebar recorder.add_event() elif event.name == 'esc': recorder.stop_recording() break except KeyboardInterrupt: recorder.stop_recording() if __name__ == "__main__": main()