mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-06-06 06:45:52 +01:00
Remove await from audio worklet
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
This commit is contained in:
@@ -209,6 +209,7 @@ const STD_PACKAGES = new Set([
|
||||
'@react-types/shared',
|
||||
'@signalapp/minimask',
|
||||
'@signalapp/quill-cjs',
|
||||
'@signalapp/lame',
|
||||
'@typescript-eslint/eslint-plugin',
|
||||
'@typescript-eslint/parser',
|
||||
'axe-core',
|
||||
|
||||
@@ -22,8 +22,9 @@ cd -
|
||||
emcc -I lame-3.100/include -Oz -DNDEBUG -flto wrapper.c \
|
||||
./lame-3.100/libmp3lame/.libs/libmp3lame.a -o wrapper.mjs \
|
||||
-sEXPORTED_FUNCTIONS=_wrapper_init,_wrapper_get_num_samples,_wrapper_get_in,_wrapper_get_out,_wrapper_encode,_wrapper_flush,_wrapper_get_lametag_frame,_wrapper_close \
|
||||
-sEXPORTED_RUNTIME_METHODS=HEAPU8 \
|
||||
-sEXPORTED_RUNTIME_METHODS=HEAPU8 -sDYNAMIC_EXECUTION=0 \
|
||||
-sENVIRONMENT=worklet -sWASM=0 -sWASM_ASYNC_COMPILATION=0
|
||||
sed -I '' 's/^async //' wrapper.mjs
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
@@ -12,7 +12,7 @@ const {
|
||||
_wrapper_encode,
|
||||
_wrapper_get_lametag_frame,
|
||||
_wrapper_flush,
|
||||
} = await initWrapper();
|
||||
} = initWrapper();
|
||||
|
||||
const input = new Float32Array(
|
||||
HEAPU8.buffer,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -77,10 +77,15 @@ export class AudioRecorder {
|
||||
}
|
||||
if (data.type === 'complete') {
|
||||
this.#state = { type: 'idle' };
|
||||
chunks.push(data.finalFrame);
|
||||
|
||||
const result = Bytes.concatenate(chunks);
|
||||
|
||||
// Replace the original placeholder header with the one that has
|
||||
// full audio duration (necessary for VBR encoding).
|
||||
chunks[0] = data.lametagFrame;
|
||||
resolve(Bytes.concatenate(chunks));
|
||||
result.set(data.lametagFrame);
|
||||
|
||||
resolve(result);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -88,7 +93,6 @@ export class AudioRecorder {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
audio: {
|
||||
channelCount: { ideal: 1 },
|
||||
autoGainControl: { ideal: false },
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ export type WorkletMessageType = Readonly<
|
||||
| {
|
||||
type: 'complete';
|
||||
lametagFrame: Uint8Array<ArrayBuffer>;
|
||||
finalFrame: Uint8Array<ArrayBuffer>;
|
||||
}
|
||||
>;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
WorkletMessageType,
|
||||
RendererMessageType,
|
||||
} from '../types/AudioRecorder.std.ts';
|
||||
import { init, encode, flush, getLametagFrame } from '@signalapp/lame';
|
||||
|
||||
declare const sampleRate: number;
|
||||
|
||||
@@ -33,16 +34,7 @@ declare function registerProcessor(
|
||||
|
||||
const BIT_RATE = 128;
|
||||
|
||||
// Unfortunately `context.audioWorklet.addModule` doesn't wait for top-level
|
||||
// awaits to be resolved so we have to call `registerProcessor` immediately
|
||||
// and let the import resolve later on.
|
||||
const lame = (async () => {
|
||||
const result = await import('@signalapp/lame');
|
||||
|
||||
result.init(sampleRate, BIT_RATE);
|
||||
|
||||
return result;
|
||||
})();
|
||||
init(sampleRate, BIT_RATE);
|
||||
|
||||
class Mp3Encoder
|
||||
extends AudioWorkletProcessor
|
||||
@@ -53,21 +45,22 @@ class Mp3Encoder
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.port.onmessage = async ({ data }: { data: RendererMessageType }) => {
|
||||
this.port.onmessage = ({ data }: { data: RendererMessageType }) => {
|
||||
if (data.type !== 'stop') {
|
||||
throw new Error('Unexpected message');
|
||||
}
|
||||
this.#isStopped = true;
|
||||
const { flush, getLametagFrame } = await lame;
|
||||
this.#sendChunk(flush());
|
||||
|
||||
const chunk = new Uint8Array(flush());
|
||||
|
||||
const lametagFrame = new Uint8Array(getLametagFrame());
|
||||
this.port.postMessage(
|
||||
{
|
||||
type: 'complete',
|
||||
lametagFrame: lametagFrame,
|
||||
finalFrame: chunk,
|
||||
} satisfies WorkletMessageType,
|
||||
[lametagFrame.buffer]
|
||||
[lametagFrame.buffer, chunk.buffer]
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -83,19 +76,16 @@ class Mp3Encoder
|
||||
}
|
||||
|
||||
const [channel] = input;
|
||||
if (channel != null) {
|
||||
void this.#encode(channel);
|
||||
if (channel == null) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async #encode(channel: Float32Array<ArrayBuffer>): Promise<void> {
|
||||
const { encode } = await lame;
|
||||
this.#sendChunk(encode(channel));
|
||||
}
|
||||
const shared = encode(channel);
|
||||
if (shared.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#sendChunk(chunk: Uint8Array<ArrayBuffer>): void {
|
||||
const copy = new Uint8Array(chunk);
|
||||
const copy = new Uint8Array(shared);
|
||||
this.port.postMessage(
|
||||
{
|
||||
type: 'chunk',
|
||||
@@ -103,6 +93,7 @@ class Mp3Encoder
|
||||
} satisfies WorkletMessageType,
|
||||
[copy.buffer]
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user