Skip to content

Commit 4e1d8f5

Browse files
authored
fix: BROS-389: Fix waveforms rendering for multi channels case (#8415)
1 parent 019176d commit 4e1d8f5

File tree

1 file changed

+56
-38
lines changed

1 file changed

+56
-38
lines changed

web/libs/editor/src/lib/AudioUltra/Visual/Visualizer.ts

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ export class Visualizer extends Events<VisualizerEvents> {
117117
private renderers: Renderer[] = [];
118118
private rateLimitedTransfer: RateLimitedRenderer;
119119
private interactionManager!: InteractionManager;
120+
private initialSpectrogramHeight: number;
121+
private initialWaveformHeight: number;
120122

121123
constructor(options: VisualizerOptions, waveform: Waveform) {
122124
super();
@@ -131,7 +133,10 @@ export class Visualizer extends Events<VisualizerEvents> {
131133
this.autoCenter = options.autoCenter ?? this.autoCenter;
132134
this.splitChannels = options.splitChannels ?? this.splitChannels;
133135
this.waveformHeight = options.waveformHeight ?? options.height ?? options.waveHeight ?? 32;
134-
this.spectrogramHeight = options.spectrogramHeight ?? options.height ?? 32;
136+
this.spectrogramHeight = options.spectrogramHeight ?? options.height ?? options.waveHeight ?? 32;
137+
// Save initial height for computing adaptive max height during resize
138+
this.initialWaveformHeight = this.waveformHeight;
139+
this.initialSpectrogramHeight = this.spectrogramHeight;
135140
this.timelineHeight = options.timelineHeight ?? options.timeline?.height ?? 20;
136141
this.timelinePlacement = options?.timeline?.placement ?? this.timelinePlacement;
137142
this.gridColor = options.gridColor ? rgba(options.gridColor) : this.gridColor;
@@ -465,14 +470,14 @@ export class Visualizer extends Events<VisualizerEvents> {
465470
}
466471

467472
drawRequestId: number | null = null;
468-
drawRequestDry = false;
473+
drawRequestDry = true;
469474
draw(dry = false) {
470475
if (!isSyncedBuffering) {
471476
this._draw(dry);
472477
return;
473478
}
474479
if (this.drawRequestId) {
475-
this.drawRequestDry = this.drawRequestDry || dry;
480+
this.drawRequestDry = this.drawRequestDry && dry;
476481
} else {
477482
this.drawRequestDry = dry;
478483
this.drawRequestId = requestAnimationFrame(() => {
@@ -580,14 +585,14 @@ export class Visualizer extends Events<VisualizerEvents> {
580585
return this.container.clientWidth;
581586
}
582587

583-
get computedWaveformHeight() {
588+
get waveformLayerHeight() {
584589
if (this.splitChannels && this.audio?.channelCount) {
585590
return this.waveformHeight * this.audio.channelCount;
586591
}
587592
return this.waveformHeight;
588593
}
589594

590-
get computedSpectrogramHeight() {
595+
get spectrogramLayerHeight() {
591596
if (this.splitChannels && this.audio?.channelCount) {
592597
return this.spectrogramHeight * this.audio.channelCount;
593598
}
@@ -606,8 +611,8 @@ export class Visualizer extends Events<VisualizerEvents> {
606611

607612
// If the timeline layer doesn't exist yet, assume it's visible and use timelineHeight
608613
height += timelineLayer === undefined ? this.timelineHeight : timelineLayer.isVisible ? this.timelineHeight : 0;
609-
height += waveformLayer?.isVisible ? this.computedWaveformHeight : 0;
610-
height += spectrogramLayer?.isVisible ? this.computedSpectrogramHeight : 0; // Use computedSpectrogramHeight!
614+
height += waveformLayer?.isVisible ? this.waveformLayerHeight : 0;
615+
height += spectrogramLayer?.isVisible ? this.spectrogramLayerHeight : 0;
611616

612617
return height;
613618
}
@@ -651,13 +656,19 @@ export class Visualizer extends Events<VisualizerEvents> {
651656
this.wrapper.style.height = "100%";
652657

653658
const mainLayer = this.createLayer({ name: "main" });
654-
this.createLayer({ name: "background", offscreen: true, zIndex: 0, isVisible: false, height: this.waveformHeight });
655-
this.createLayer({ name: "waveform", offscreen: true, zIndex: 100, height: this.waveformHeight });
659+
this.createLayer({
660+
name: "background",
661+
offscreen: true,
662+
zIndex: 0,
663+
isVisible: false,
664+
height: this.waveformLayerHeight,
665+
});
666+
this.createLayer({ name: "waveform", offscreen: true, zIndex: 100, height: this.waveformLayerHeight });
656667
this.createLayer({
657668
name: "waveform-resize",
658669
offscreen: true,
659670
zIndex: 200,
660-
height: this.waveformHeight,
671+
height: this.waveformLayerHeight,
661672
compositeOperation: "difference", // Use blend mode for better visibility
662673
});
663674

@@ -668,14 +679,14 @@ export class Visualizer extends Events<VisualizerEvents> {
668679
offscreen: true,
669680
zIndex: 100,
670681
isVisible: true,
671-
height: this.spectrogramHeight,
682+
height: this.spectrogramLayerHeight,
672683
});
673684
this.createLayer({
674685
name: "spectrogram-resize",
675686
offscreen: true,
676687
zIndex: 200,
677688
isVisible: true,
678-
height: this.spectrogramHeight,
689+
height: this.spectrogramLayerHeight,
679690
compositeOperation: "difference", // Use blend mode for better visibility
680691
});
681692
this.createLayer({ name: "progress", offscreen: true, zIndex: 1020, isVisible: true, height: 0 });
@@ -684,7 +695,7 @@ export class Visualizer extends Events<VisualizerEvents> {
684695
offscreen: true,
685696
zIndex: 1100,
686697
isVisible: true,
687-
height: this.spectrogramHeight,
698+
height: this.spectrogramLayerHeight,
688699
});
689700
}
690701

@@ -1100,15 +1111,15 @@ export class Visualizer extends Events<VisualizerEvents> {
11001111
if (layer.name !== "main") {
11011112
layer.pixelRatio = this.pixelRatio;
11021113
layer.width = this.width;
1103-
// Update height for layers that should match the waveform height
1114+
// Update height for layers according to their type
11041115
if (layer.name === "waveform") {
1105-
layer.height = this.waveformHeight;
1116+
layer.height = this.waveformLayerHeight;
11061117
} else if (layer.name === "waveform-resize") {
1107-
layer.height = this.waveformHeight;
1118+
layer.height = this.waveformLayerHeight;
11081119
} else if (layer.name === "spectrogram" || layer.name === "spectrogram-grid") {
1109-
layer.height = this.spectrogramHeight;
1120+
layer.height = this.spectrogramLayerHeight;
11101121
} else if (layer.name === "spectrogram-resize") {
1111-
layer.height = this.spectrogramHeight;
1122+
layer.height = this.spectrogramLayerHeight;
11121123
}
11131124
// Update regions layer height to match the full visualizer height
11141125
if (layer.name === "regions") {
@@ -1243,13 +1254,6 @@ export class Visualizer extends Events<VisualizerEvents> {
12431254
const spectrogramLayer = this.getLayer("spectrogram");
12441255
if (!spectrogramLayer?.isVisible) return 0;
12451256

1246-
const channelCount = this.audio?.channelCount ?? 1;
1247-
1248-
if (this.splitChannels) {
1249-
// Each channel gets an equal split of the spectrogram area
1250-
return this.spectrogramHeight / channelCount;
1251-
}
1252-
// Spectrogram uses the full height when not split
12531257
return this.spectrogramHeight;
12541258
}
12551259

@@ -1291,7 +1295,7 @@ export class Visualizer extends Events<VisualizerEvents> {
12911295
if (componentName === "spectrogram") {
12921296
// Spectrogram comes after waveform in the vertical stack
12931297
if (waveformLayer?.isVisible) {
1294-
offsetY += this.computedWaveformHeight;
1298+
offsetY += this.waveformLayerHeight;
12951299
}
12961300
}
12971301

@@ -1300,9 +1304,9 @@ export class Visualizer extends Events<VisualizerEvents> {
13001304
let height = 0;
13011305

13021306
if (componentName === "waveform") {
1303-
height = this.computedWaveformHeight;
1307+
height = this.waveformLayerHeight;
13041308
} else if (componentName === "spectrogram") {
1305-
height = this.computedSpectrogramHeight;
1309+
height = this.spectrogramLayerHeight;
13061310
}
13071311

13081312
return {
@@ -1317,40 +1321,54 @@ export class Visualizer extends Events<VisualizerEvents> {
13171321
* Handle height changes from ResizeRenderer
13181322
*/
13191323
private handleHeightChange = (componentName: string, newHeight: number): void => {
1324+
let initialHeight = 0;
1325+
if (componentName === "waveform") {
1326+
initialHeight = this.initialWaveformHeight * ((this.splitChannels && this.audio?.channelCount) || 1);
1327+
} else if (componentName === "spectrogram") {
1328+
initialHeight = this.initialSpectrogramHeight * ((this.splitChannels && this.audio?.channelCount) || 1);
1329+
}
13201330
const minHeight = 50;
1321-
const maxHeight = 500;
1331+
const maxHeight = Math.max(500, initialHeight);
13221332
const clampedHeight = Math.max(minHeight, Math.min(maxHeight, newHeight));
13231333

13241334
if (componentName === "waveform") {
1325-
this.waveformHeight = clampedHeight;
1335+
if (this.splitChannels && this.audio?.channelCount) {
1336+
this.waveformHeight = clampedHeight / this.audio.channelCount;
1337+
} else {
1338+
this.waveformHeight = clampedHeight;
1339+
}
13261340
// Update the waveform-related layers
13271341
const waveformLayer = this.getLayer("waveform");
13281342
const waveformResizeLayer = this.getLayer("waveform-resize");
13291343
const backgroundLayer = this.getLayer("background");
13301344

1331-
if (waveformLayer) waveformLayer.height = clampedHeight;
1332-
if (waveformResizeLayer) waveformResizeLayer.height = clampedHeight;
1333-
if (backgroundLayer) backgroundLayer.height = clampedHeight;
1345+
if (waveformLayer) waveformLayer.height = this.waveformLayerHeight;
1346+
if (waveformResizeLayer) waveformResizeLayer.height = this.waveformLayerHeight;
1347+
if (backgroundLayer) backgroundLayer.height = this.waveformLayerHeight;
13341348

13351349
// Update WaveformRenderer configuration
13361350
if (this.waveformRenderer) {
13371351
// For height changes, we only need to update the waveHeight config
13381352
// without triggering expensive redraws
1339-
this.waveformRenderer.config.waveHeight = clampedHeight;
1353+
this.waveformRenderer.config.waveHeight = this.waveformHeight;
13401354

13411355
// Don't call resetRenderState - it forces expensive redraw
13421356
// The waveform data doesn't change, just the rendering height
13431357
}
13441358
} else if (componentName === "spectrogram") {
1345-
this.spectrogramHeight = clampedHeight;
1359+
if (this.splitChannels && this.audio?.channelCount) {
1360+
this.spectrogramHeight = clampedHeight / this.audio.channelCount;
1361+
} else {
1362+
this.spectrogramHeight = clampedHeight;
1363+
}
13461364
// Update the spectrogram-related layers
13471365
const spectrogramLayer = this.getLayer("spectrogram");
13481366
const spectrogramResizeLayer = this.getLayer("spectrogram-resize");
13491367
const spectrogramGridLayer = this.getLayer("spectrogram-grid");
13501368

1351-
if (spectrogramLayer) spectrogramLayer.height = clampedHeight;
1352-
if (spectrogramResizeLayer) spectrogramResizeLayer.height = clampedHeight;
1353-
if (spectrogramGridLayer) spectrogramGridLayer.height = clampedHeight;
1369+
if (spectrogramLayer) spectrogramLayer.height = this.spectrogramLayerHeight;
1370+
if (spectrogramResizeLayer) spectrogramResizeLayer.height = this.spectrogramLayerHeight;
1371+
if (spectrogramGridLayer) spectrogramGridLayer.height = this.spectrogramLayerHeight;
13541372

13551373
// Update SpectrogramRenderer configuration
13561374
if (this.spectrogramRenderer) {

0 commit comments

Comments
 (0)