1+ // Init AudioContext (lazy initialization)
2+ let audioContext = null ;
3+
4+ function initAudioContext ( ) {
5+ if ( ! audioContext ) {
6+ audioContext = new ( window . AudioContext || window . webkitAudioContext ) ( ) ;
7+ }
8+ // Resume context if suspended (required by some browsers)
9+ if ( audioContext . state === 'suspended' ) {
10+ audioContext . resume ( ) ;
11+ }
12+ return audioContext ;
13+ }
14+
15+ const baseFreq = 196 ; // G3 as base frequency
16+ const letters = 'abcdefghijklmnopqrstuvwxyz' ;
17+ const durationPerLetter = 0.2 ; // seconds
18+ const durationPerSpace = 1.0 ; // seconds
19+
20+ function playTone ( frequency , duration = durationPerLetter ) {
21+ const ctx = initAudioContext ( ) ;
22+ const oscillator = ctx . createOscillator ( ) ;
23+ const gainNode = ctx . createGain ( ) ;
24+
25+ oscillator . connect ( gainNode ) ;
26+ gainNode . connect ( ctx . destination ) ;
27+
28+ oscillator . type = 'square' ; // square wave
29+ oscillator . frequency . value = frequency ;
30+
31+ gainNode . gain . setValueAtTime ( 0.3 , ctx . currentTime ) ;
32+ gainNode . gain . exponentialRampToValueAtTime ( 0.01 , ctx . currentTime + duration ) ;
33+
34+ oscillator . start ( ctx . currentTime ) ;
35+ oscillator . stop ( ctx . currentTime + duration ) ;
36+ }
37+
38+ function playSilence ( duration = durationPerSpace ) {
39+ // Wait without playing sound
40+ return new Promise ( resolve => setTimeout ( resolve , duration * 1000 ) ) ;
41+ }
42+
43+ async function playText ( ) {
44+ const text = document . getElementById ( "textInput" ) . value ;
45+ console . log ( "Playing text as sound:" , text ) ;
46+
47+ const durationPerLetter = parseFloat ( document . getElementById ( "duration" ) . value ) ;
48+ const durationPerSpace = parseFloat ( document . getElementById ( "spaceSilence" ) . value ) ;
49+ const baseFreq = parseFloat ( document . getElementById ( "baseFreq" ) . value ) ;
50+
51+ for ( const ch of text ) {
52+ if ( ch === ' ' ) {
53+ await playSilence ( durationPerSpace ) ;
54+ } else if ( letters . includes ( ch . toLowerCase ( ) ) ) {
55+ const idx = letters . indexOf ( ch . toLowerCase ( ) ) ;
56+ const freq = baseFreq * Math . pow ( 2 , idx / 12 ) ;
57+ playTone ( freq , durationPerLetter ) ;
58+ await playSilence ( 0.05 ) ;
59+ }
60+ }
61+ }
0 commit comments