Skip to content

Commit 9d34727

Browse files
committed
Add audio start/stop button and UI tooltips
Introduces a 'Start/Stop Audio' button for explicit microphone control and updates UI to include tooltips for better usability. Refactors styles to use CSS variables for easier theming, updates documentation to reflect 16 presets, and marks related roadmap items as complete. Also adds an audio stop function and improves audio reactive UI logic.
1 parent f2fd3f9 commit 9d34727

7 files changed

Lines changed: 151 additions & 76 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ https://jasonbra1n.github.io/Audio-Visualizer/
22

33
# Audio Visualizer
44

5-
Create stunning, customizable spiral visualizations with vibrant colored mirrors, multi-layered designs, and dynamic cosmic effects. This web-based tool lets you tweak scale, nodes, layers, and ratios, with options for logarithmic or linear growth, gradient strokes, dashed lines, and auto-rotation. Explore 12 presets—from the ethereal **Nebula** to the rippling **Cosmic Wave**—or craft your own visual masterpiece.
5+
Create stunning, customizable spiral visualizations with vibrant colored mirrors, multi-layered designs, and dynamic cosmic effects. This web-based tool lets you tweak scale, nodes, layers, and ratios, with options for logarithmic or linear growth, gradient strokes, dashed lines, and auto-rotation. Explore 16 presets—from the ethereal **Nebula** to the rippling **Cosmic Wave**—or craft your own visual masterpiece.
66

77
An interactive web-based visualizer that creates mesmerizing spiral patterns with customizable parameters and mirror effects. Built with HTML, CSS, and JavaScript, this project allows users to experiment with spirals, layers, mirroring, and colors, and download high-resolution images of their creations.
88

audio.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
let audioContext, analyser, dataArray;
1+
let audioContext, analyser, dataArray, mediaStream;
22

33
async function initAudio() {
4+
if (audioContext) return; // Already initialized
45
try {
5-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
6+
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
67
audioContext = new (window.AudioContext || window.webkitAudioContext)();
7-
const source = audioContext.createMediaStreamSource(stream);
8+
const source = audioContext.createMediaStreamSource(mediaStream);
89
analyser = audioContext.createAnalyser();
910
analyser.fftSize = 64;
1011
analyser.smoothingTimeConstant = 0.3;
@@ -17,6 +18,20 @@ async function initAudio() {
1718
}
1819
}
1920

21+
function stopAudio() {
22+
if (mediaStream) {
23+
mediaStream.getTracks().forEach(track => track.stop());
24+
mediaStream = null;
25+
}
26+
if (audioContext) {
27+
audioContext.close().then(() => {
28+
audioContext = null;
29+
analyser = null;
30+
console.log('Audio stopped and context closed.');
31+
});
32+
}
33+
}
34+
2035
function getAudioAmplitude() {
2136
if (!analyser) return 0;
2237
analyser.getByteTimeDomainData(dataArray);

changelog.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
### Added
11+
12+
### Changed
13+
14+
### Fixed
15+
16+
## [1.0.0] - 2025-12-08
17+
18+
### Added
19+
- Added a "Start/Stop Audio" button for explicit user control over microphone access.
1120
- Added user documentation and new visual styles to the `roadmap.md`.
1221
- `roadmap.md` for planning future development.
1322
- `dev_guide.md` for contributor guidelines.
1423
- `changelog.md` to track project changes.
24+
- **Major Upgrade**: Replaced 2D Canvas renderer with a high-performance WebGL engine from the `/3/` prototype.
1525

1626
### Changed
1727
- Updated `dev_guide.md` with current instructions for adding presets and maintaining `README.md`.
1828
- Updated `README.md` to reflect the current number of presets (16) and features.
1929
- Updated project title in `index.html` and `README.md` to "Audio Visualizer".
30+
- Refactored `styles.css` to use CSS variables for easier theming and maintenance.
2031
- Integrated advanced mobile touch controls (pinch-to-zoom and drag-to-rotate) from prototype.
2132
- **Major Refactor**: Modularized the monolithic `script.js` into smaller, focused files (`webgl-setup.js`, `drawing.js`, `audio.js`, `ui.js`, `state.js`) for improved maintainability.
22-
- **Major Upgrade**: Replaced 2D Canvas renderer with a high-performance WebGL engine from the `/3/` prototype.
2333

2434
### Fixed
25-
- Simplified the `layerRatio` UI control by removing the redundant and less responsive number input.
26-
27-
## [1.0.0] - 2025-12-08
28-
29-
### Added
30-
- Initial release of the Audio Visualizer.
31-
- Core features: spiral generation, layering, mirroring, and color customization.
32-
- 12 initial presets for different visual styles.
33-
- Audio-reactivity for scale, rotation, and opacity based on microphone input.
34-
- High-resolution PNG export.
35+
- Fixed an issue where tooltips would render partially off-screen or be clipped by the controls panel.
36+
- Fixed a bug where curved lines would disappear or render incorrectly.
37+
- Simplified the `layerRatio` UI control by removing the redundant and less responsive number input.

index.html

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,56 +26,57 @@ <h2>Audio Visualizer</h2>
2626
<div class="controls">
2727
<div class="control-group">
2828
<h3>Presets</h3>
29-
<label>Load Preset:
29+
<label data-tooltip="Load a pre-configured visual design.">Load Preset:
3030
<select id="presetSelector">
3131
<option value="">Select a Preset</option>
3232
<option value="custom">Custom</option>
3333
<!-- Options will be added via JavaScript -->
3434
</select>
3535
</label>
3636
<div>
37-
<button onclick="undo()">Undo</button>
38-
<button onclick="reset()">Reset</button>
37+
<button onclick="undo()" data-tooltip="Undo the last parameter change.">Undo</button>
38+
<button onclick="reset()" data-tooltip="Reset all parameters to their default values.">Reset</button>
3939
</div>
4040
</div>
4141

4242
<div class="control-group">
4343
<h3>Master Settings</h3>
44-
<label>Auto-Rotate: <input type="checkbox" id="autoRotate"></label>
45-
<label>Audio Reactive: <input type="checkbox" id="audioReactive"></label>
44+
<label data-tooltip="Automatically rotates the spiral."><input type="checkbox" id="autoRotate"> Auto-Rotate</label>
45+
<label data-tooltip="Makes the visualizer react to microphone input."><input type="checkbox" id="audioReactive"> Audio Reactive</label>
46+
<button id="audioToggleButton" style="display: none; margin-top: 5px;">Start Audio</button>
4647
<div id="audioOptions" style="display: none; margin-left: 20px;">
47-
<label><input type="checkbox" id="audioRotate"> Rotate</label>
48-
<label><input type="checkbox" id="audioScale"> Scale</label>
49-
<label><input type="checkbox" id="audioOpacity"> Opacity</label>
50-
<label>Scale Gap: <input type="range" id="scaleGap" min="1" max="50" value="10"> <span id="scaleGapValue">10</span></label>
51-
<label>Scale Sensitivity: <input type="range" id="scaleSensitivity" min="0.5" max="5" step="0.1" value="1"> <span id="scaleSensitivityValue">1</span></label>
48+
<label data-tooltip="Makes rotation reactive to audio."><input type="checkbox" id="audioRotate"> Rotate</label>
49+
<label data-tooltip="Makes scale reactive to audio."><input type="checkbox" id="audioScale"> Scale</label>
50+
<label data-tooltip="Makes opacity reactive to audio."><input type="checkbox" id="audioOpacity"> Opacity</label>
51+
<label data-tooltip="Maximum amount the scale can increase with audio.">Scale Gap: <input type="range" id="scaleGap" min="1" max="50" value="10"> <span id="scaleGapValue">10</span></label>
52+
<label data-tooltip="How strongly the scale reacts to audio.">Scale Sensitivity: <input type="range" id="scaleSensitivity" min="0.5" max="5" step="0.1" value="1"> <span id="scaleSensitivityValue">1</span></label>
5253
</div>
5354
</div>
5455

5556
<div class="control-group">
5657
<h3>Core Parameters</h3>
57-
<label>Scale: <input type="range" id="scale" min="1" max="100" step="0.1" value="30"> <span id="scaleValue">30</span></label>
58-
<label>Nodes: <input type="range" id="nodes" min="5" max="50" value="12"> <span id="nodesValue">12</span></label>
59-
<label>Rotation: <input type="range" id="rotation" min="0" max="360" value="0"> <span id="rotationValue">0</span></label>
58+
<label data-tooltip="Controls the overall size of the spiral.">Scale: <input type="range" id="scale" min="1" max="100" step="0.1" value="30"> <span id="scaleValue">30</span></label>
59+
<label data-tooltip="Number of points in each spiral arm.">Nodes: <input type="range" id="nodes" min="5" max="50" value="12"> <span id="nodesValue">12</span></label>
60+
<label data-tooltip="Sets the starting angle of the spiral.">Rotation: <input type="range" id="rotation" min="0" max="360" value="0"> <span id="rotationValue">0</span></label>
6061
</div>
6162

6263
<div class="control-group">
6364
<h3>Layer Controls</h3>
64-
<label>Layers: <input type="range" id="layers" min="1" max="100" value="3"> <span id="layersValue">3</span></label>
65-
<label>Layer Ratio:
65+
<label data-tooltip="Number of concentric spiral layers.">Layers: <input type="range" id="layers" min="1" max="100" value="3"> <span id="layersValue">3</span></label>
66+
<label data-tooltip="Spacing between layers. >1 grows, <1 shrinks.">Layer Ratio:
6667
<input type="range" id="layerRatio" min="0.1" max="10" step="0.1" value="2">
6768
<span id="layerRatioValue">2</span>
6869
</label>
6970
<div>
70-
<button onclick="setRatio(1.618)">Golden Ratio</button>
71-
<button onclick="setRatio(2.414)">Silver Ratio</button>
71+
<button onclick="setRatio(1.618)" data-tooltip="Set layer ratio to the Golden Ratio (φ ≈ 1.618).">Golden Ratio</button>
72+
<button onclick="setRatio(2.414)" data-tooltip="Set layer ratio to the Silver Ratio (δS ≈ 2.414).">Silver Ratio</button>
7273
</div>
7374
</div>
7475

7576
<div class="control-group">
7677
<h3>Mirror Effects</h3>
77-
<label><input type="checkbox" id="verticalMirror"> Vertical Mirror</label>
78-
<label><input type="checkbox" id="horizontalMirror"> Horizontal Mirror</label>
78+
<label data-tooltip="Mirrors the spiral across the vertical axis."><input type="checkbox" id="verticalMirror"> Vertical Mirror</label>
79+
<label data-tooltip="Mirrors the spiral across the horizontal axis."><input type="checkbox" id="horizontalMirror"> Horizontal Mirror</label>
7980
<div class="mirror-colors">
8081
<label>Vertical Color: <input type="color" id="verticalColor" value="#FF00FF"></label>
8182
<label>Horizontal Color: <input type="color" id="horizontalColor" value="#FFFF00"></label>
@@ -85,32 +86,32 @@ <h3>Mirror Effects</h3>
8586

8687
<div class="control-group">
8788
<h3>Style Options</h3>
88-
<label>Color: <input type="color" id="strokeColor" value="#00FFFF"></label>
89-
<label>Line Width: <input type="range" id="lineWidth" min="1" max="10" value="2"> <span id="lineWidthValue">2</span></label>
90-
<label>Opacity: <input type="range" id="opacity" min="0" max="1" step="0.1" value="1"> <span id="opacityValue">1</span></label>
91-
<label>Spiral Type:
89+
<label data-tooltip="The main color of the primary spiral.">Color: <input type="color" id="strokeColor" value="#00FFFF"></label>
90+
<label data-tooltip="The thickness of the spiral lines.">Line Width: <input type="range" id="lineWidth" min="1" max="10" value="2"> <span id="lineWidthValue">2</span></label>
91+
<label data-tooltip="The transparency of the spiral.">Opacity: <input type="range" id="opacity" min="0" max="1" step="0.1" value="1"> <span id="opacityValue">1</span></label>
92+
<label data-tooltip="Linear for even spacing, Logarithmic for exponential spacing.">Spiral Type:
9293
<select id="spiralType">
9394
<option value="linear">Linear</option>
9495
<option value="logarithmic">Logarithmic</option>
9596
</select>
9697
</label>
97-
<label>Line End Style:
98+
<label data-tooltip="Style of the line endings (for thick lines).">Line End Style:
9899
<select id="lineEndStyle">
99100
<option value="boxed">Boxed</option>
100101
<option value="tapered">Tapered</option>
101102
<option value="rounded">Rounded</option>
102103
</select>
103104
</label>
104-
<label>Background Color: <input type="color" id="backgroundColor" value="#111111"></label>
105-
<label><input type="checkbox" id="gradientStroke" checked> Gradient Stroke</label>
106-
<label><input type="checkbox" id="dashEffect"> Dashed Lines</label>
107-
<label><input type="checkbox" id="curvedLines"> Curved Lines</label>
105+
<label data-tooltip="The background color of the canvas.">Background Color: <input type="color" id="backgroundColor" value="#111111"></label>
106+
<label data-tooltip="Fades the line color to black along its length."><input type="checkbox" id="gradientStroke" checked> Gradient Stroke</label>
107+
<label data-tooltip="Renders the lines with a dashed pattern."><input type="checkbox" id="dashEffect"> Dashed Lines</label>
108+
<label data-tooltip="Draws smooth curves instead of straight lines between nodes."><input type="checkbox" id="curvedLines"> Curved Lines</label>
108109
</div>
109110
</div>
110111

111112
<div class="download-container">
112-
<button onclick="downloadCanvas()">Download Image (2160×2160)</button>
113-
<button id="fullscreenButton">Go Fullscreen</button>
113+
<button onclick="downloadCanvas()" data-tooltip="Saves the current visual as a high-resolution PNG file.">Download Image (2160×2160)</button>
114+
<button id="fullscreenButton" data-tooltip="View the visualizer in full screen mode.">Go Fullscreen</button>
114115
</div>
115116
</div>
116117

roadmap.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ This document outlines the development roadmap for the Audio Visualizer project.
66

77
The immediate goals are to refine the existing features, improve performance, and enhance the core audio-reactive experience.
88

9-
- **[ ] Code Refactoring:**
9+
- **[x] Code Refactoring:**
1010
- [x] Modularize `script.js` into smaller, focused files (e.g., `ui.js`, `drawing.js`, `audio.js`, `state.js`).
1111
- [x] Optimize the animation loop to avoid unnecessary DOM reads on every frame and use `lerp` for smooth transitions. *(Discovered in `/2` prototype)*.
12-
- [ ] Convert `styles.css` to use CSS variables for easier theming.
12+
- [x] Convert `styles.css` to use CSS variables for easier theming.
1313

1414
- **[ ] UI/UX Enhancements:**
15-
- [ ] Add a "Start/Stop Audio" button to give users more explicit control over microphone access.
15+
- [x] Add a "Start/Stop Audio" button to give users more explicit control over microphone access.
1616
- [ ] Improve layout and responsiveness of the controls panel for smaller screens.
1717
- [x] Integrate advanced mobile touch controls (pinch-to-zoom, drag-to-rotate) from the `/2` prototype.
18-
- [ ] Add tooltips to explain what each control does.
18+
- [x] Add tooltips to explain what each control does.
1919

2020
- **[ ] Core Feature Improvements:**
2121
- [ ] Add more parameters for audio reactivity (e.g., line width, number of nodes, layer ratio).

styles.css

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
:root {
2+
--main-bg-color: #111111;
3+
--overlay-bg-color: rgba(0, 0, 0, 0.8);
4+
--text-color: white;
5+
--control-bg-color: #333;
6+
--control-hover-bg-color: #555;
7+
--border-radius-large: 10px;
8+
--border-radius-small: 5px;
9+
--controls-width: 300px;
10+
}
11+
112
body {
213
margin: 0;
314
padding: 0;
415
font-family: Arial, sans-serif;
5-
background-color: #111111;
16+
background-color: var(--main-bg-color);
617
overflow: hidden;
718
}
819

@@ -19,12 +30,12 @@ body {
1930
position: fixed;
2031
top: 20px;
2132
right: 20px;
22-
width: 300px;
33+
width: var(--controls-width);
2334
max-height: calc(100vh - 40px);
24-
background: rgba(0, 0, 0, 0.8);
25-
color: white;
35+
background: var(--overlay-bg-color);
36+
color: var(--text-color);
2637
padding: 20px;
27-
border-radius: 10px;
38+
border-radius: var(--border-radius-large);
2839
z-index: 2;
2940
overflow-y: auto;
3041
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
@@ -34,16 +45,16 @@ body {
3445
position: absolute;
3546
top: 10px;
3647
right: 10px;
37-
background: #333;
38-
color: white;
48+
background: var(--control-bg-color);
49+
color: var(--text-color);
3950
border: none;
4051
padding: 5px 10px;
4152
cursor: pointer;
42-
border-radius: 5px;
53+
border-radius: var(--border-radius-small);
4354
}
4455

4556
.toggle-controls:hover {
46-
background: #555;
57+
background: var(--control-hover-bg-color);
4758
}
4859

4960
.controls {
@@ -70,6 +81,36 @@ label {
7081
margin: 5px 0;
7182
}
7283

84+
/* Tooltip Styles */
85+
[data-tooltip] {
86+
position: relative;
87+
cursor: help;
88+
}
89+
90+
[data-tooltip]::after {
91+
content: attr(data-tooltip);
92+
position: absolute;
93+
/* Position above the element */
94+
bottom: 100%;
95+
left: 50%;
96+
transform: translateX(-50%) translateY(-5px); /* Move up slightly */
97+
background-color: var(--control-hover-bg-color);
98+
color: var(--text-color);
99+
padding: 5px 10px;
100+
border-radius: var(--border-radius-small);
101+
font-size: 0.8em;
102+
white-space: nowrap;
103+
z-index: 10;
104+
opacity: 0;
105+
visibility: hidden;
106+
transition: opacity 0.2s, visibility 0.2s;
107+
}
108+
109+
[data-tooltip]:hover::after {
110+
opacity: 1;
111+
visibility: visible;
112+
}
113+
73114
input[type="range"] {
74115
width: 70%;
75116
vertical-align: middle;
@@ -87,24 +128,24 @@ input[type="color"] {
87128
select {
88129
width: 100%;
89130
padding: 5px;
90-
background: #333;
91-
color: white;
131+
background: var(--control-bg-color);
132+
color: var(--text-color);
92133
border: none;
93-
border-radius: 5px;
134+
border-radius: var(--border-radius-small);
94135
}
95136

96137
button {
97-
background: #333;
98-
color: white;
138+
background: var(--control-bg-color);
139+
color: var(--text-color);
99140
border: none;
100141
padding: 5px 10px;
101142
margin: 5px 5px 0 0;
102143
cursor: pointer;
103-
border-radius: 5px;
144+
border-radius: var(--border-radius-small);
104145
}
105146

106147
button:hover {
107-
background: #555;
148+
background: var(--control-hover-bg-color);
108149
}
109150

110151
.mirror-colors {
@@ -123,9 +164,9 @@ button:hover {
123164
top: 50%;
124165
left: 50%;
125166
transform: translate(-50%, -50%);
126-
background: rgba(0, 0, 0, 0.7);
127-
color: white;
167+
background: var(--overlay-bg-color);
168+
color: var(--text-color);
128169
padding: 10px 20px;
129-
border-radius: 5px;
170+
border-radius: var(--border-radius-small);
130171
z-index: 3;
131172
}

0 commit comments

Comments
 (0)