Spaces:
Running
Running
| // Basic Web Audio API Sound Manager | |
| function _class_call_check(instance, Constructor) { | |
| if (!(instance instanceof Constructor)) { | |
| throw new TypeError("Cannot call a class as a function"); | |
| } | |
| } | |
| function _defineProperties(target, props) { | |
| for(var i = 0; i < props.length; i++){ | |
| var descriptor = props[i]; | |
| descriptor.enumerable = descriptor.enumerable || false; | |
| descriptor.configurable = true; | |
| if ("value" in descriptor) descriptor.writable = true; | |
| Object.defineProperty(target, descriptor.key, descriptor); | |
| } | |
| } | |
| function _create_class(Constructor, protoProps, staticProps) { | |
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); | |
| if (staticProps) _defineProperties(Constructor, staticProps); | |
| return Constructor; | |
| } | |
| export var AudioManager = /*#__PURE__*/ function() { | |
| "use strict"; | |
| function AudioManager() { | |
| _class_call_check(this, AudioManager); | |
| // Use '||' for broader browser compatibility, though 'webkit' is largely legacy | |
| var AudioContext = window.AudioContext || window.webkitAudioContext; | |
| this.audioCtx = null; | |
| this.isInitialized = false; | |
| this.lastClickTime = 0; | |
| this.clickInterval = 200; // Milliseconds between clicks for rhythm | |
| if (AudioContext) { | |
| try { | |
| this.audioCtx = new AudioContext(); | |
| this.isInitialized = true; | |
| console.log("AudioContext created successfully."); | |
| } catch (e) { | |
| console.error("Error creating AudioContext:", e); | |
| } | |
| } else { | |
| console.warn("Web Audio API is not supported in this browser."); | |
| } | |
| } | |
| _create_class(AudioManager, [ | |
| { | |
| // Resume audio context after user interaction (required by many browsers) | |
| key: "resumeContext", | |
| value: function resumeContext() { | |
| if (this.audioCtx && this.audioCtx.state === 'suspended') { | |
| this.audioCtx.resume().then(function() { | |
| console.log("AudioContext resumed successfully."); | |
| }).catch(function(e) { | |
| return console.error("Error resuming AudioContext:", e); | |
| }); | |
| } | |
| } | |
| }, | |
| { | |
| key: "playInteractionClickSound", | |
| value: function playInteractionClickSound() { | |
| if (!this.isInitialized || !this.audioCtx || this.audioCtx.state !== 'running') return; | |
| var internalCurrentTime = this.audioCtx.currentTime; | |
| // Check if enough time has passed since the last click | |
| if (internalCurrentTime - this.lastClickTime < this.clickInterval / 1000) { | |
| return; // Too soon for the next click | |
| } | |
| this.lastClickTime = internalCurrentTime; | |
| var oscillator = this.audioCtx.createOscillator(); | |
| var gainNode = this.audioCtx.createGain(); | |
| oscillator.connect(gainNode); | |
| gainNode.connect(this.audioCtx.destination); | |
| oscillator.type = 'sine'; // Softer waveform for a 'tic' | |
| oscillator.frequency.setValueAtTime(1200, this.audioCtx.currentTime); // Lowered base pitch | |
| // A very quick pitch drop can make it sound more 'clicky' | |
| oscillator.frequency.exponentialRampToValueAtTime(600, this.audioCtx.currentTime + 0.01); // Lowered pitch drop target | |
| var clickVolume = 0.08; // Increased volume slightly | |
| gainNode.gain.setValueAtTime(0, this.audioCtx.currentTime); // Start silent for a clean attack | |
| gainNode.gain.linearRampToValueAtTime(clickVolume, this.audioCtx.currentTime + 0.003); // Very fast attack | |
| gainNode.gain.exponentialRampToValueAtTime(0.0001, this.audioCtx.currentTime + 0.005); // Keep decay short for 'tic' | |
| oscillator.start(this.audioCtx.currentTime); | |
| oscillator.stop(this.audioCtx.currentTime + 0.005); // Match decay duration | |
| } | |
| } | |
| ]); | |
| return AudioManager; | |
| }(); | |