start static method
Starts a worker-hosted audio track over bytes, or returns null.
Null is the ordinary answer on any page that cannot host one — no shared
memory (not cross-origin isolated), no AudioWorklet, no compiled
payload, or a container this path cannot open. The player then runs its
normal audio pump, exactly as it did before this existed.
workletUrl exists so a test can serve the module from its own tree;
production always uses the package asset.
Implementation
static Future<WorkerAudioTrack?> start({
required Uint8List bytes,
required int sampleRate,
required int channels,
required Duration depth,
double volume = 1.0,
String workletUrl = kWorkletAssetUrl,
}) async {
final sink = await AudioRingSink.open(
sampleRate: sampleRate,
channels: channels,
depth: depth,
workletUrl: workletUrl,
);
if (sink == null) return null;
sink.volume = volume;
final Worker worker;
try {
worker = await spawn(
_entry,
message: <String, Object?>{
// SHARED, not transferred: both threads must address this same
// memory, and shared memory in a transfer list is a DataCloneError.
'ring': PlatformValue(sink.ring.shareable),
'bytes': bytes,
},
timeout: const Duration(seconds: 10),
);
} on Object {
await sink.close();
return null;
}
final track = WorkerAudioTrack._(sink, worker, sampleRate);
// A container the worker cannot open is not a transport failure and does
// not look like one: the pump records it and keeps answering. Ask once
// before committing, so the player falls back instead of playing silence.
if (await track._failure() != null) {
await track.close();
return null;
}
return track;
}