Skip to content

Commit 13e2a57

Browse files
committed
Add spectrogram visualization capabilities to the audio editor component with configurable settings and improved UI controls.
### Key changes: - Extracted window functions into a separate `WindowFunctions` module for better code organization. - Created new `ColorMapper` module for handling spectrogram color schemes. - Added `spectrogram` property to the `AudioPlus` component (optional boolean to enable/disable). - Implemented FFT-based spectrogram rendering with configurable parameters. - Added UI controls for spectrogram settings (FFT size, color scheme, dB range). - Fixed CSS styling issues in the configuration modal. - Improved section header positioning and spacing. ### Features: - Real-time spectrogram visualization. - Configurable FFT window size and type. - Multiple color scheme options. - Adjustable dB range for visualization. - Mel-scale frequency mapping support. - Responsive rendering with performance optimizations. ### Labels: - `audio` - `community:feature-request` - `community:reviewed` - `editor` - `feature`
1 parent b1a3670 commit 13e2a57

36 files changed

+5066
-1971
lines changed

web/libs/editor/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
"lodash.get": "^4.4.0",
2121
"lodash.ismatch": "^4.4.0",
2222
"lodash.throttle": "^4.1.1",
23-
"fft.js": "^4.0.4",
2423
"mobx": "^5.15.4",
2524
"mobx-react": "^6",
2625
"mobx-react-lite": "2.2.2",
@@ -41,7 +40,8 @@
4140
"strman": "^2.0.1",
4241
"wavesurfer.js": "^6.0.1",
4342
"xpath-range": "^1.1.1",
44-
"colormap": "^2.3.2"
43+
"colormap": "^2.3.2",
44+
"webfft": "^1.0.3"
4545
},
4646
"main": "src/index.js"
4747
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
.audio-config {
2-
position: relative; /* Keep relative for potential other children */
3-
/* z-index is not needed here anymore */
2+
position: relative;
43

54
&__modal {
6-
position: fixed; /* MUST be fixed for portal + JS positioning */
7-
width: 260px;
5+
position: fixed;
6+
width: 360px;
87
max-height: 500px;
98
background: var(--color-neutral-background);
109
box-shadow: 0 4px 10px 0 rgba(var(--color-neutral-shadow-raw) / 30%);
@@ -22,7 +21,7 @@
2221
}
2322

2423
.audio-config__slider-container {
25-
padding: 28px 16px 0px 16px;
24+
padding: 28px 16px 0;
2625

2726
.ant-slider {
2827
margin-left: 10px;
@@ -35,6 +34,7 @@
3534
bottom: 20px;
3635
font-size: 12px;
3736
transform: none;
37+
color: var(--color-neutral-content);
3838
}
3939
}
4040
}
@@ -66,27 +66,33 @@
6666
}
6767
}
6868

69+
&__range-handle {
70+
&::before {
71+
width: 14px !important;
72+
height: 14px !important;
73+
box-shadow: none;
74+
}
75+
}
6976

7077
&__scroll-content {
7178
flex-grow: 1;
7279
overflow-y: auto;
7380
padding: 0;
7481

7582
> .audio-config__slider-container,
76-
> .audio-config__toggle,
77-
> .audio-config__spectrogram-controls {
83+
> .audio-config__toggle {
7884
padding: 8px 16px;
7985
}
8086
}
8187

8288
&__buttons {
83-
margin-top: 0; /* Remove margin */
89+
margin-top: 0;
8490
padding: 2px 0;
8591
border-top: 1px solid var(--color-neutral-border);
8692
font-size: 14px;
8793
cursor: pointer;
88-
flex-shrink: 0; /* Prevent buttons from shrinking */
89-
background: var(--color-neutral-background); /* Ensure background matches */
94+
flex-shrink: 0;
95+
background: var(--color-neutral-background);
9096
}
9197

9298
&__menu-button {
@@ -100,81 +106,6 @@
100106
}
101107
}
102108

103-
&__spectrogram-controls {
104-
display: flex;
105-
flex-direction: column;
106-
width: 100%;
107-
padding: 8px 16px;
108-
109-
.range {
110-
width: 100%;
111-
margin: 8px 0;
112-
padding: 0;
113-
114-
&.range_align_horizontal {
115-
padding: 0;
116-
}
117-
118-
&__body {
119-
width: 100%;
120-
}
121-
122-
&__range-handle {
123-
&::before {
124-
width: 14px !important;
125-
height: 14px !important;
126-
}
127-
}
128-
}
129-
}
130-
131-
&__control {
132-
display: flex;
133-
align-items: center;
134-
justify-content: space-between;
135-
gap: 10px;
136-
margin: 10px 0;
137-
width: auto;
138-
139-
.info {
140-
display: flex;
141-
align-items: center;
142-
gap: 8px;
143-
font-size: 12px;
144-
color: var(--color-neutral-content-subtler);
145-
white-space: nowrap;
146-
147-
svg {
148-
width: 14px;
149-
height: 14px;
150-
color: var(--color-neutral-icon);
151-
}
152-
}
153-
154-
.input-group {
155-
display: flex;
156-
align-items: center;
157-
gap: 12px;
158-
}
159-
160-
.separator {
161-
color: var(--color-neutral-content-subtlest);
162-
font-size: 12px;
163-
white-space: nowrap;
164-
margin: 0 4px;
165-
}
166-
}
167-
168-
.ant-select {
169-
margin: 4px 0;
170-
}
171-
172-
&__info {
173-
display: flex;
174-
align-items: center;
175-
gap: 8px;
176-
margin-bottom: 5px;
177-
}
178109

179110
&__section-header {
180111
background-color: var(--color-neutral-background);
@@ -194,29 +125,3 @@
194125
}
195126
}
196127
}
197-
198-
.color-scheme-select {
199-
.ant-select-selector {
200-
padding: 0 !important;
201-
border: none !important;
202-
height: 32px;
203-
line-height: 32px;
204-
overflow: hidden;
205-
border-radius: 4px;
206-
}
207-
208-
.ant-select-selection-item {
209-
padding: 0 12px !important;
210-
line-height: 32px !important;
211-
color: var(--color-neutral-content);
212-
text-shadow: 0 0 2px rgba(0, 0, 0, 0.7);
213-
text-align: left;
214-
width: 100%;
215-
}
216-
217-
.ant-select-arrow {
218-
color: var(--color-neutral-content);
219-
text-shadow: 0 0 2px rgba(0, 0, 0, 0.7);
220-
right: 8px;
221-
}
222-
}

0 commit comments

Comments
 (0)