From 6e31f691189e9ce34e63d4bc2dde6e79ae7fe263 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 May 2024 15:56:33 +0100 Subject: [PATCH] Reuse single PlaybackWorker between Playback instances (#12520) * Terminate playback worker on destroy Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Reuse single PlaybackWorker between all Playbacks Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * ... Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/PlaybackEncoder.ts | 34 ++++++++++++++++++++++++++++++++++ src/audio/Playback.ts | 14 ++++---------- 2 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/PlaybackEncoder.ts diff --git a/src/PlaybackEncoder.ts b/src/PlaybackEncoder.ts new file mode 100644 index 0000000000..a08292e01f --- /dev/null +++ b/src/PlaybackEncoder.ts @@ -0,0 +1,34 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// @ts-ignore - `.ts` is needed here to make TS happy +import { Request, Response } from "./workers/playback.worker"; +import { WorkerManager } from "./WorkerManager"; +import playbackWorkerFactory from "./workers/playbackWorkerFactory"; + +export class PlaybackEncoder { + private static internalInstance = new PlaybackEncoder(); + + public static get instance(): PlaybackEncoder { + return PlaybackEncoder.internalInstance; + } + + private readonly worker = new WorkerManager(playbackWorkerFactory()); + + public getPlaybackWaveform(input: Float32Array): Promise { + return this.worker.call({ data: Array.from(input) }).then((resp) => resp.waveform); + } +} diff --git a/src/audio/Playback.ts b/src/audio/Playback.ts index dc2619d692..957d541732 100644 --- a/src/audio/Playback.ts +++ b/src/audio/Playback.ts @@ -19,17 +19,14 @@ import { SimpleObservable } from "matrix-widget-api"; import { logger } from "matrix-js-sdk/src/logger"; import { defer } from "matrix-js-sdk/src/utils"; -// @ts-ignore - `.ts` is needed here to make TS happy -import { Request, Response } from "../workers/playback.worker.ts"; import { UPDATE_EVENT } from "../stores/AsyncStore"; import { arrayFastResample } from "../utils/arrays"; import { IDestroyable } from "../utils/IDestroyable"; import { PlaybackClock } from "./PlaybackClock"; import { createAudioContext, decodeOgg } from "./compat"; import { clamp } from "../utils/numbers"; -import { WorkerManager } from "../WorkerManager"; import { DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES } from "./consts"; -import playbackWorkerFactory from "../workers/playbackWorkerFactory"; +import { PlaybackEncoder } from "../PlaybackEncoder"; export enum PlaybackState { Decoding = "decoding", @@ -64,7 +61,6 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte private waveformObservable = new SimpleObservable(); private readonly clock: PlaybackClock; private readonly fileSize: number; - private readonly worker = new WorkerManager(playbackWorkerFactory()); /** * Creates a new playback instance from a buffer. @@ -209,7 +205,9 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte // Update the waveform to the real waveform once we have channel data to use. We don't // exactly trust the user-provided waveform to be accurate... - this.resampledWaveform = await this.makePlaybackWaveform(this.audioBuf.getChannelData(0)); + this.resampledWaveform = await PlaybackEncoder.instance.getPlaybackWaveform( + this.audioBuf.getChannelData(0), + ); } this.waveformObservable.update(this.resampledWaveform); @@ -222,10 +220,6 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte this.emit(PlaybackState.Stopped); // signal that we're not decoding anymore } - private makePlaybackWaveform(input: Float32Array): Promise { - return this.worker.call({ data: Array.from(input) }).then((resp) => resp.waveform); - } - private onPlaybackEnd = async (): Promise => { await this.context.suspend(); this.emit(PlaybackState.Stopped);