diff --git a/.vscode/launch.json b/.vscode/launch.json index 13e6818..8e9f248 100755 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "name": "Flutter debug", "type": "dart", "request": "launch", - "program": "lib/output_device/output_device.dart", + "program": "lib/buffer_stream/websocket.dart", "flutterMode": "debug", "cwd": "${workspaceFolder}/example" }, @@ -24,7 +24,7 @@ "name": "Flutter release", "type": "dart", "request": "launch", - "program": "lib/main.dart", + "program": "lib/buffer_stream/websocket.dart", "flutterMode": "release", "cwd": "${workspaceFolder}/example" }, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 1aac3f6..ea26f4a 100755 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -3,13 +3,13 @@ "tasks": [ { "label": "compile linux debug verbose", - "command": "cd ${workspaceFolder}/example; flutter build linux -t lib/main.dart --debug --verbose", + "command": "cd ${workspaceFolder}/example; flutter build linux -t lib/buffer_stream/websocket.dart --debug --verbose", // "args": ["build", "linux", "--verbose"], "type": "shell" }, { "label": "compile linux debug", - "command": "cd ${workspaceFolder}/example; flutter build linux -t lib/output_device/output_device.dart --debug", + "command": "cd ${workspaceFolder}/example; flutter build linux -t lib/buffer_stream/websocket.dart --debug", "type": "shell" }, { @@ -31,6 +31,11 @@ "label": "compile web debug", "command": "cd ${workspaceFolder}/example; flutter run -d chrome --web-renderer canvaskit --web-browser-flag '--disable-web-security' -t lib/main.dart --release", "type": "shell" + }, + { + "label": "compile WASM", + "command": "sh ${workspaceFolder}/wasm.sh", + "type": "shell" } ] } diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 61842f2..bf99810 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -40,6 +40,7 @@ list(APPEND PLUGIN_SOURCES "${SRC_DIR}/analyzer.cpp" "${SRC_DIR}/synth/basic_wave.cpp" "${SRC_DIR}/waveform/waveform.cpp" + "${SRC_DIR}/audiobuffer/audiobuffer.cpp" "${SRC_DIR}/filters/filters.cpp" "${SRC_DIR}/filters/pitch_shift_filter.cpp" "${SRC_DIR}/filters/smbPitchShift.cpp" diff --git a/example/lib/buffer_stream/generate.dart b/example/lib/buffer_stream/generate.dart new file mode 100644 index 0000000..4a5bf44 --- /dev/null +++ b/example/lib/buffer_stream/generate.dart @@ -0,0 +1,272 @@ +import 'dart:developer' as dev; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_soloud/flutter_soloud.dart'; +import 'package:flutter_soloud_example/buffer_stream/ui/buffer_widget.dart'; +import 'package:logging/logging.dart'; + +/// Example of how to generate PCM audio inside an `Isolate` and play them. +/// +/// The `setBufferStream`, `addAudioDataStream` and `setDataIsEnded` methods +/// can be used inside an `Isolate`. So you can perform complex operations +/// computing audio inside an `Isolate` without freezing the main Isolate. + +void main() async { + // The `flutter_soloud` package logs everything + // (from severe warnings to fine debug messages) + // using the standard `package:logging`. + // You can listen to the logs as shown below. + Logger.root.level = kDebugMode ? Level.FINE : Level.INFO; + Logger.root.onRecord.listen((record) { + dev.log( + record.message, + time: record.time, + level: record.level.value, + name: record.loggerName, + zone: record.zone, + error: record.error, + stackTrace: record.stackTrace, + ); + }); + + WidgetsFlutterBinding.ensureInitialized(); + + /// Initialize the player. + await SoLoud.instance.init(); + + runApp( + const MaterialApp( + home: Generate(), + ), + ); +} + +@pragma('vm:entry-point') +Future generateTone(Map args) async { + final sound = args['sound'] as AudioSource; + + // Frequency in Hz + final frequency = args['frequency'] as double; + + // Sampling rate in Hz (samples per second) + final sampleRate = args['sampleRate'] as int; + + // Duration of the audio in seconds + final duration = args['duration'] as double; + + // Total number of samples needed for the given duration + final sampleCount = (sampleRate * duration).ceil(); + + // List to hold the audio samples + final audioData = Int8List(sampleCount); + + // Generate PCM data + for (var i = 0; i < sampleCount; i++) { + // Calculate the amplitude of the wave (between -128 and 127 for 8-bit PCM) + final amplitude = (127 * sin(2 * pi * frequency * i / sampleRate)).toInt(); + // Store the amplitude in the audio data buffer + audioData[i] = amplitude; + } + + SoLoud.instance.addAudioDataStream( + sound, + audioData.buffer.asUint8List(), + ); + SoLoud.instance.setDataIsEnded(sound); +} + +@pragma('vm:entry-point') +Future generateBouncingSoundPCM(Map args) async { + final sound = args['sound'] as AudioSource; + // Sampling rate in Hz (samples per second) + final sampleRate = args['sampleRate'] as int; + // Duration of the audio in seconds + final duration = args['duration'] as double; + // Total number of samples needed for the given duration + final sampleCount = sampleRate * duration; + // List to hold the audio samples + final audioData = Int8List(sampleCount.ceil()); + + // Parameters for bouncing effect + const baseFrequency = 300.0; // Base frequency in Hz + const bounceFrequency = 8.0; // Frequency of bounce effect + const bounceDepth = 200.0; // Depth of frequency variation + + // Generate PCM data with bouncing frequency modulation + for (var i = 0; i < sampleCount; i++) { + // Calculate time for each sample + final time = i / sampleRate; + + // Create a bouncing effect by oscillating the frequency + final modulatedFrequency = + baseFrequency + bounceDepth * sin(2 * pi * bounceFrequency * time); + + // Apply an oscillation to the amplitude to make it sound more dynamic + final amplitudeModulation = + 0.8 + 0.2 * sin(2 * pi * bounceFrequency * 0.5 * time); + + // Generate sample using modulated frequency and amplitude + final amplitude = + (127 * amplitudeModulation * sin(2 * pi * modulatedFrequency * time)) + .toInt(); + + // Store the sample value in the audio data buffer + audioData[i] = amplitude; + } + + SoLoud.instance.addAudioDataStream(sound, audioData.buffer.asUint8List()); + SoLoud.instance.setDataIsEnded(sound); +} + +@pragma('vm:entry-point') +Future generateWailingSirenSoundPCM(Map args) async { + final sound = args['sound'] as AudioSource; + // Sampling rate in Hz (samples per second) + final sampleRate = args['sampleRate'] as int; + // Duration of the audio in seconds + final duration = args['duration'] as double; + // Total number of samples needed for the given duration + final sampleCount = sampleRate * duration; + // List to hold the audio samples + final audioData = Int8List(sampleCount.ceil()); + + // Parameters for the siren effect + const baseFrequency = + 600.0; // Higher base frequency for a more noticeable sound + const sirenSpeed = 4.0; // Slower frequency oscillation for a siren effect + const frequencyRange = + 150.0; // Moderate frequency range for smooth oscillation + + // Generate PCM data with a smooth siren-like frequency modulation + for (var i = 0; i < sampleCount; i++) { + // Calculate time for each sample + final time = i / sampleRate; + + // Smoothly oscillate the frequency + final modulatedFrequency = + baseFrequency + frequencyRange * sin(2 * pi * sirenSpeed * time); + + // Generate the sample using a sinusoidal wave with modulated frequency + final amplitude = (127 * sin(2 * pi * modulatedFrequency * time)).toInt(); + + // Store the sample value in the audio data buffer + audioData[i] = amplitude; + } + + SoLoud.instance.addAudioDataStream(sound, audioData.buffer.asUint8List()); + SoLoud.instance.setDataIsEnded(sound); +} + +class Generate extends StatefulWidget { + const Generate({super.key}); + + @override + State createState() => _GenerateState(); +} + +class _GenerateState extends State { + AudioSource? tone; + AudioSource? bouncing; + AudioSource? siren; + + @override + Widget build(BuildContext context) { + const gap = SizedBox(height: 16); + return Scaffold( + appBar: AppBar(title: const Text('Generate PCM Data')), + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + OutlinedButton( + onPressed: () async { + /// Setup the buffer stream for each streams. + tone = SoLoud.instance.setBufferStream( + maxBufferSize: 1024 * 1024 * 1, + pcmFormat: BufferPcmType.s8, + ); + bouncing = SoLoud.instance.setBufferStream( + maxBufferSize: 1024 * 1024 * 1, + pcmFormat: BufferPcmType.s8, + ); + siren = SoLoud.instance.setBufferStream( + maxBufferSize: 1024 * 1024 * 1, + pcmFormat: BufferPcmType.s8, + ); + + /// Generate PCM data inside an Isolate + await Future.wait([ + compute(generateTone, { + 'sound': tone, + 'frequency': 440.0, + 'sampleRate': 44100, + 'duration': 1.0, + }), + compute(generateBouncingSoundPCM, { + 'sound': bouncing, + 'frequency': 200.0, + 'sampleRate': 44100, + 'duration': 3.0, + }), + compute(generateWailingSirenSoundPCM, { + 'sound': siren, + 'frequency': 200.0, + 'sampleRate': 44100, + 'duration': 2.0, + }), + ]); + + /// Just to rebuild [BufferBar] widgets + setState(() {}); + }, + child: const Text('generate PCM data'), + ), + gap, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + OutlinedButton( + onPressed: () async { + if (tone == null) return; + await SoLoud.instance.play(tone!, looping: true); + }, + child: const Text('Play tone'), + ), + OutlinedButton( + onPressed: () async { + if (siren == null) return; + await SoLoud.instance.play(siren!, looping: true); + }, + child: const Text('Play siren'), + ), + OutlinedButton( + onPressed: () async { + if (bouncing == null) return; + await SoLoud.instance.play(bouncing!, looping: true); + }, + child: const Text('Play bouncing'), + ), + ], + ), + gap, + OutlinedButton( + onPressed: () async { + await SoLoud.instance.disposeAllSources(); + tone = siren = bouncing = null; + setState(() {}); + }, + child: const Text('dispose all sounds'), + ), + gap, + BufferBar(sound: tone, startingMb: 1, label: 'tone'), + BufferBar(sound: siren, startingMb: 1, label: 'siren'), + BufferBar(sound: bouncing, startingMb: 1, label: 'bouncing'), + ], + ), + ), + ); + } +} diff --git a/example/lib/buffer_stream/ui/buffer_widget.dart b/example/lib/buffer_stream/ui/buffer_widget.dart new file mode 100644 index 0000000..36d9f45 --- /dev/null +++ b/example/lib/buffer_stream/ui/buffer_widget.dart @@ -0,0 +1,122 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +import 'dart:async'; + +import 'package:flutter/material.dart'; + +import 'package:flutter_soloud/flutter_soloud.dart'; + +class BufferBar extends StatefulWidget { + const BufferBar({ + super.key, + this.label = '', + this.sound, + this.startingMb = 10, + }); + + final String? label; + final AudioSource? sound; + final int startingMb; + + @override + State createState() => _BufferBarState(); +} + +class _BufferBarState extends State { + final width = 250.0; + final height = 30.0; + Timer? timer; + int currentMaxBytes = 1024 * 1024; // 1 MB + + @override + void initState() { + currentMaxBytes *= widget.startingMb; + super.initState(); + timer = Timer.periodic(const Duration(milliseconds: 100), (timer) { + setState(() {}); + }); + } + + @override + Widget build(BuildContext context) { + if (widget.sound == null) { + return const SizedBox.shrink(); + } + + final int bufferSize; + try { + bufferSize = SoLoud.instance.getBufferSize(widget.sound!); + } on Exception catch (_) { + return const SizedBox.shrink(); + } + + /// Increase the widget width when the buffer size increases. + if (bufferSize >= currentMaxBytes) { + currentMaxBytes += 1024 * 1024 * widget.startingMb; + } + + /// [soundLength] reflects the value of [progressValue]. + final soundLength = SoLoud.instance.getLength(widget.sound!); + final humanDuration = '${soundLength.inMinutes % 60}:' + '${(soundLength.inSeconds % 60).toString().padLeft(2, '0')}.' + '${(soundLength.inMilliseconds % 1000).toString().padLeft(3, '0')}'; + + /// The current progress value + final progressValue = bufferSize > 0.0 ? bufferSize / currentMaxBytes : 0.0; + + /// [handlesPos] reflects the handles position between start and + /// [soundLength] in percentage. + final handlesPos = []; + for (var i = 0; i < widget.sound!.handles.length; i++) { + final handlePos = + SoLoud.instance.getPosition(widget.sound!.handles.elementAt(i)); + handlesPos.add( + handlePos.inMilliseconds / soundLength.inMilliseconds, + ); + } + + return Padding( + padding: const EdgeInsets.all(8), + child: Row( + children: [ + SizedBox( + width: 120, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.label ?? '', + style: const TextStyle(fontWeight: FontWeight.bold), + ), + Text('${(bufferSize / 1024 / 1024).toStringAsFixed(1)} MB'), + Text(humanDuration), + ], + ), + ), + Stack( + children: [ + SizedBox( + height: height, + width: width, + child: LinearProgressIndicator( + value: progressValue, + backgroundColor: Colors.black, + valueColor: const AlwaysStoppedAnimation(Colors.red), + minHeight: height, + ), + ), + for (var i = 0; i < handlesPos.length; i++) + Positioned( + left: handlesPos[i] * progressValue * width - 3, + child: SizedBox( + height: height, + width: 3, + child: const ColoredBox(color: Colors.yellowAccent), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/example/lib/buffer_stream/websocket.dart b/example/lib/buffer_stream/websocket.dart new file mode 100644 index 0000000..cbddeaf --- /dev/null +++ b/example/lib/buffer_stream/websocket.dart @@ -0,0 +1,314 @@ +// ignore_for_file: avoid_print, unnecessary_lambdas + +import 'dart:async'; +import 'dart:developer' as dev; +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_soloud/flutter_soloud.dart'; +import 'package:flutter_soloud_example/buffer_stream/ui/buffer_widget.dart'; +import 'package:logging/logging.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; + +/// This example shows how to use BufferStream with a websocket. +/// +/// You must have a server which streams audio data. Here a repo that uses +/// websocketd as a server and ffmpeg to provide audio data: +/// https://github.com/alnitak/websocketd +/// +/// Run it and choose which audio format you want to stream and the speed for +/// testing BufferStream buffering. +/// Then run this example and choose the same audio format. + +void main() async { + // The `flutter_soloud` package logs everything + // (from severe warnings to fine debug messages) + // using the standard `package:logging`. + // You can listen to the logs as shown below. + Logger.root.level = kDebugMode ? Level.FINE : Level.INFO; + Logger.root.onRecord.listen((record) { + dev.log( + record.message, + time: record.time, + level: record.level.value, + name: record.loggerName, + zone: record.zone, + error: record.error, + stackTrace: record.stackTrace, + ); + }); + + WidgetsFlutterBinding.ensureInitialized(); + + /// Initialize the player. + await SoLoud.instance.init(); + + runApp( + const MaterialApp( + home: WebsocketExample(), + ), + ); +} + +/// Simple usecase of flutter_soloud plugin +class WebsocketExample extends StatefulWidget { + const WebsocketExample({super.key}); + + @override + State createState() => _WebsocketExampleState(); +} + +class _WebsocketExampleState extends State { + final websocketUri = 'ws://192.168.1.2:8080/'; + final sampleRate = [11025, 22050, 44100, 48000]; + final format = ['f32le', 's8', 's16le', 's32le']; + int srId = 2; + int chId = 0; + int fmtId = 0; + WebSocketChannel? channel; + AudioSource? currentSound; + SoundHandle? handle; + int numberOfChunks = 0; + int byteSize = 0; + final streamBuffering = ValueNotifier(false); + + @override + void dispose() { + SoLoud.instance.deinit(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (!SoLoud.instance.isInitialized) return const SizedBox.shrink(); + + return Scaffold( + appBar: AppBar( + title: const Text('PCM audio data from a websocket Example'), + ), + body: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + /// SAMPLERATE + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + for (var i = 0; i < sampleRate.length; i++) + RadioListTile( + title: Text( + sampleRate[i].toString(), + style: const TextStyle(fontSize: 12), + ), + value: i, + visualDensity: const VisualDensity( + horizontal: VisualDensity.minimumDensity, + vertical: VisualDensity.minimumDensity, + ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + groupValue: srId, + onChanged: (int? value) { + setState(() { + srId = value!; + }); + }, + ), + ], + ), + ), + + /// CHANNELS + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + for (var i = 0; i < Channels.values.length; i++) + RadioListTile( + title: Text( + Channels.values[i].toString(), + style: const TextStyle(fontSize: 12), + ), + value: i, + visualDensity: const VisualDensity( + horizontal: VisualDensity.minimumDensity, + vertical: VisualDensity.minimumDensity, + ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + groupValue: chId, + onChanged: (int? value) { + setState(() { + chId = value!; + }); + }, + ), + ], + ), + ), + + /// FORMAT + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + for (var i = 0; i < format.length; i++) + RadioListTile( + title: Text( + format[i], + style: const TextStyle(fontSize: 12), + ), + value: i, + visualDensity: const VisualDensity( + horizontal: VisualDensity.minimumDensity, + vertical: VisualDensity.minimumDensity, + ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + groupValue: fmtId, + onChanged: (int? value) { + setState(() { + fmtId = value!; + }); + }, + ), + ], + ), + ), + ], + ), + OutlinedButton( + onPressed: () async { + await channel?.sink.close(); + await SoLoud.instance.disposeAllSources(); + + currentSound = SoLoud.instance.setBufferStream( + maxBufferSize: 1024 * 1024 * 600, // 150 MB + bufferingTimeNeeds: 3, + sampleRate: sampleRate[srId], + channels: Channels.values[chId], + pcmFormat: BufferPcmType.values[fmtId], + onBuffering: (isBuffering, handle, time) async { + debugPrint('started buffering? $isBuffering with ' + 'handle: $handle at time $time'); + if (context.mounted) { + setState(() { + streamBuffering.value = !streamBuffering.value; + }); + } + }, + ); + setState(() {}); + }, + child: const Text('set chosen stream type'), + ), + const SizedBox(height: 16), + OutlinedButton( + onPressed: () async { + /// This could be a way to receive PCM data from some sources and + /// use it to create a new [AudioSource]. + /// Could be done inside an Isolate for example to manage received + /// data if it is in JSON format or the audio data is base64. + if (currentSound == null) { + debugPrint('A stream has not been set yet!'); + return; + } + + /// Connect to the websocket + final wsUrl = Uri.parse(websocketUri); + channel = WebSocketChannel.connect(wsUrl); + + /// Wait for the websocket to be ready + try { + await channel?.ready; + } on SocketException catch (e) { + debugPrint(e.toString()); + } on WebSocketChannelException catch (e) { + debugPrint(e.toString()); + } + + /// Listen to the websocket + channel?.stream.listen( + (message) async { + numberOfChunks++; + byteSize += (message as List).length; + + try { + SoLoud.instance.addAudioDataStream( + currentSound!, + Uint8List.fromList(message), + ); + } on Exception catch (e) { + debugPrint('error adding audio data: $e'); + await channel?.sink.close(); + } + }, + onDone: () { + if (currentSound != null) { + SoLoud.instance.setDataIsEnded(currentSound!); + } + debugPrint('ws channel closed. ' + 'numberOfChunks: $numberOfChunks byteSize: $byteSize'); + numberOfChunks = 0; + byteSize = 0; + }, + onError: (error) {}, + ); + }, + child: const Text('connect to WS and receive audio data'), + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + OutlinedButton( + onPressed: () async { + if (currentSound == null) return; + handle = await SoLoud.instance.play( + currentSound!, + volume: 0.6, + // looping: true, + ); + print('handle: $handle'); + Timer.periodic(const Duration(milliseconds: 1000), (timer) { + if (currentSound == null || + SoLoud.instance.getIsValidVoiceHandle(handle!) == + false) { + timer.cancel(); + setState(() {}); + } + }); + }, + child: const Text('paly'), + ), + const SizedBox(width: 16), + OutlinedButton( + onPressed: () async { + currentSound = null; + await SoLoud.instance.disposeAllSources(); + await channel?.sink.close(); + setState(() {}); + }, + child: const Text('stop all sounds and close ws'), + ), + ], + ), + const SizedBox(height: 16), + BufferBar(sound: currentSound), + const SizedBox(height: 16), + ValueListenableBuilder( + valueListenable: streamBuffering, + builder: (_, value, __) { + if (value) { + return const Text('BUFFERING!'); + } + return const SizedBox.shrink(); + }, + ), + ], + ), + ); + } +} diff --git a/example/linux/my_application.cc b/example/linux/my_application.cc index 4205f31..bdda6cb 100755 --- a/example/linux/my_application.cc +++ b/example/linux/my_application.cc @@ -47,7 +47,7 @@ static void my_application_activate(GApplication* application) { gtk_window_set_title(window, "flutter_soloud_example"); } - gtk_window_set_default_size(window, 650, 1000); + gtk_window_set_default_size(window, 600, 580); gtk_widget_show(GTK_WIDGET(window)); g_autoptr(FlDartProject) project = fl_dart_project_new(); diff --git a/example/pubspec.lock b/example/pubspec.lock index 5061a8f..f529c10 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -49,6 +49,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.4+2" + crypto: + dependency: transitive + description: + name: crypto + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + url: "https://pub.dev" + source: hosted + version: "3.0.5" cupertino_icons: dependency: "direct main" description: @@ -348,6 +356,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + web_socket_channel: + dependency: "direct main" + description: + name: web_socket_channel + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + url: "https://pub.dev" + source: hosted + version: "3.0.1" win32: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 184fe99..f86f1a0 100755 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -24,6 +24,8 @@ dependencies: #https://pub.dev/packages/logging logging: ^1.2.0 + web_socket_channel: ^3.0.1 + dev_dependencies: flutter_test: sdk: flutter diff --git a/lib/src/bindings/bindings_player.dart b/lib/src/bindings/bindings_player.dart index 5910c84..1c27a4f 100644 --- a/lib/src/bindings/bindings_player.dart +++ b/lib/src/bindings/bindings_player.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_positional_boolean_parameters + import 'dart:async'; import 'dart:typed_data'; @@ -12,6 +14,13 @@ import 'package:meta/meta.dart'; export 'package:flutter_soloud/src/bindings/bindings_player_ffi.dart' if (dart.library.js_interop) 'package:flutter_soloud/src/bindings/bindings_player_web.dart'; +/// Callback set in `setBufferStream` for the `onBuffering` closure. +typedef OnBufferingCallbackTFunction = void Function( + bool isBuffering, + int handle, + double time, +); + /// Abstract class defining the interface for the platform-specific /// implementations. abstract class FlutterSoLoud { @@ -124,6 +133,46 @@ abstract class FlutterSoLoud { LoadMode mode, ); + /// Set up an audio stream. + /// + /// [maxBufferSize] the max buffer size in bytes. + /// [bufferingTimeNeeds] the buffering time needed in seconds. If a handle + /// reaches the current buffer length, it will start to buffer pausing it and + /// waiting until the buffer will have enough data to cover this time. + /// [sampleRate], [channels], [pcmFormat] must be set in the case the + /// audio data is PCM format. + /// [pcmFormat]: 0 = f32le, 1 = s8, 2 = s16le, 3 = s32le + @mustBeOverridden + ({PlayerErrors error, SoundHash soundHash}) setBufferStream( + int maxBufferSize, + double bufferingTimeNeeds, + int sampleRate, + int channels, + int pcmFormat, + OnBufferingCallbackTFunction? onBuffering, + ); + + /// Add a chunk of audio data to the buffer stream. + /// + /// [hash] the hash of the sound. + /// [audioChunk] the audio data to add. + @mustBeOverridden + PlayerErrors addAudioDataStream( + int hash, + Uint8List audioChunk, + ); + + /// Set the end of the data stream. + /// [hash] the hash of the stream sound. + /// Returns [PlayerErrors.noError] if success. + @mustBeOverridden + PlayerErrors setDataIsEnded(SoundHash soundHash); + + /// Get the current buffer size in bytes of this sound with hash [hash]. + /// [hash] the hash of the stream sound. + @mustBeOverridden + ({PlayerErrors error, int sizeInBytes}) getBufferSize(SoundHash soundHash); + /// Load a new waveform to be played once or multiple times later. /// /// [waveform] @@ -135,7 +184,6 @@ abstract class FlutterSoLoud { @mustBeOverridden ({PlayerErrors error, SoundHash soundHash}) loadWaveform( WaveForm waveform, - // ignore: avoid_positional_boolean_parameters bool superWave, double scale, double detune, @@ -277,7 +325,6 @@ abstract class FlutterSoLoud { /// [handle] the sound handle. /// [enable] enable or not the looping. @mustBeOverridden - // ignore: avoid_positional_boolean_parameters void setLooping(SoundHandle handle, bool enable); /// Get sound loop point value. @@ -301,7 +348,6 @@ abstract class FlutterSoLoud { /// /// [enabled] whether to enable or disable. @mustBeOverridden - // ignore: avoid_positional_boolean_parameters void setVisualizationEnabled(bool enabled); /// Get visualization state. @@ -483,7 +529,6 @@ abstract class FlutterSoLoud { /// [handle] handle to check. /// [protect] whether to protect or not. @mustBeOverridden - // ignore: avoid_positional_boolean_parameters void setProtectVoice(SoundHandle handle, bool protect); /// Get the current maximum active voice count. diff --git a/lib/src/bindings/bindings_player_ffi.dart b/lib/src/bindings/bindings_player_ffi.dart index a81e332..09ad3ce 100644 --- a/lib/src/bindings/bindings_player_ffi.dart +++ b/lib/src/bindings/bindings_player_ffi.dart @@ -374,6 +374,121 @@ class FlutterSoLoudFfi extends FlutterSoLoud { int Function(ffi.Pointer, ffi.Pointer, int, int, ffi.Pointer)>(); + @override + ({PlayerErrors error, SoundHash soundHash}) setBufferStream( + int maxBufferSize, + double bufferingTimeNeeds, + int sampleRate, + int channels, + int pcmFormat, + OnBufferingCallbackTFunction? onBuffering, + ) { + // Create a NativeCallable for the given [onBuffering] callback. + ffi.NativeCallable? + nativeOnBufferingCallable; + if (onBuffering != null) { + nativeOnBufferingCallable = ffi.NativeCallable< + ffi.Void Function(ffi.Bool, ffi.Int, ffi.Double)>.listener( + onBuffering, + ); + } + + final ffi.Pointer hash = + calloc(ffi.sizeOf()); + final e = _setBufferStream( + hash, + maxBufferSize, + bufferingTimeNeeds, + sampleRate, + channels, + pcmFormat, + nativeOnBufferingCallable?.nativeFunction ?? ffi.nullptr, + ); + final soundHash = SoundHash(hash.value); + final ret = (error: PlayerErrors.values[e], soundHash: soundHash); + calloc.free(hash); + return ret; + } + + late final _setBufferStreamPtr = _lookup< + ffi.NativeFunction< + ffi.UnsignedInt Function( + ffi.Pointer, + ffi.UnsignedLong, + ffi.Double, + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.Int, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Bool, ffi.Int, + ffi.Double)>>)>>('setBufferStream'); + late final _setBufferStream = _setBufferStreamPtr.asFunction< + int Function( + ffi.Pointer, + int, + double, + int, + int, + int, + ffi.Pointer< + ffi + .NativeFunction>, + )>(); + + @override + PlayerErrors addAudioDataStream( + int hash, + Uint8List audioChunk, + ) { + final ffi.Pointer audioChunkPtr = calloc(audioChunk.length); + for (var i = 0; i < audioChunk.length; i++) { + audioChunkPtr[i] = audioChunk[i]; + } + final e = _addAudioDataStream( + hash, + audioChunkPtr, + audioChunk.length, + ); + return PlayerErrors.values[e]; + } + + late final _addAudioDataStreamPtr = _lookup< + ffi.NativeFunction< + ffi.Int32 Function(ffi.UnsignedInt, ffi.Pointer, + ffi.UnsignedInt)>>('addAudioDataStream'); + late final _addAudioDataStream = _addAudioDataStreamPtr + .asFunction, int)>(); + + @override + PlayerErrors setDataIsEnded(SoundHash soundHash) { + final e = _setDataIsEnded(soundHash.hash); + return PlayerErrors.values[e]; + } + + late final _setDataIsEndedPtr = + _lookup>( + 'setDataIsEnded'); + late final _setDataIsEnded = + _setDataIsEndedPtr.asFunction(); + + @override + ({PlayerErrors error, int sizeInBytes}) getBufferSize(SoundHash soundHash) { + final ffi.Pointer size = + calloc(ffi.sizeOf()); + final e = _getBufferSize(soundHash.hash, size); + final ret = (error: PlayerErrors.values[e], sizeInBytes: size.value); + calloc.free(size); + return ret; + } + + late final _getBufferSizePtr = _lookup< + ffi.NativeFunction< + ffi.UnsignedInt Function( + ffi.UnsignedInt, ffi.Pointer)>>('getBufferSize'); + late final _getBufferSize = _getBufferSizePtr + .asFunction)>(); + @override ({PlayerErrors error, SoundHash soundHash}) loadWaveform( WaveForm waveform, diff --git a/lib/src/bindings/bindings_player_web.dart b/lib/src/bindings/bindings_player_web.dart index 1b0e688..489ea8b 100644 --- a/lib/src/bindings/bindings_player_web.dart +++ b/lib/src/bindings/bindings_player_web.dart @@ -1,4 +1,8 @@ +// ignore_for_file: avoid_positional_boolean_parameters + import 'dart:convert'; +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; import 'dart:typed_data'; import 'package:flutter_soloud/src/bindings/audio_data.dart'; @@ -101,7 +105,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { final namesPtr = wasmMalloc(50 * 255); final deviceIdPtr = wasmMalloc(50 * 4); final isDefaultPtr = wasmMalloc(50 * 4); - final nDevicesPtr = wasmMalloc(4); // 4 bytes for an int + final nDevicesPtr = wasmMalloc(4); // 4 bytes for an int32 wasmListPlaybackDevices( namesPtr, @@ -110,15 +114,15 @@ class FlutterSoLoudWeb extends FlutterSoLoud { nDevicesPtr, ); - final nDevices = wasmGetI32Value(nDevicesPtr, '*'); + final nDevices = wasmGetI32Value(nDevicesPtr, 'i32'); final devices = []; for (var i = 0; i < nDevices; i++) { - final namePtr = wasmGetI32Value(namesPtr + i * 4, '*'); + final namePtr = wasmGetI32Value(namesPtr + i * 4, 'i32'); final name = wasmUtf8ToString(namePtr); final deviceId = - wasmGetI32Value(wasmGetI32Value(deviceIdPtr + i * 4, '*'), '*'); + wasmGetI32Value(wasmGetI32Value(deviceIdPtr + i * 4, 'i32'), 'i32'); final isDefault = - wasmGetI32Value(wasmGetI32Value(isDefaultPtr + i * 4, '*'), '*'); + wasmGetI32Value(wasmGetI32Value(isDefaultPtr + i * 4, 'i32'), 'i32'); devices.add(PlaybackDevice(deviceId, isDefault == 1, name)); } @@ -154,7 +158,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { Uint8List buffer, LoadMode mode, ) { - final hashPtr = wasmMalloc(4); // 4 bytes for an int + final hashPtr = wasmMalloc(4); // 4 bytes for an int32 final bytesPtr = wasmMalloc(buffer.length); final pathPtr = wasmMalloc(uniqueName.length); // Is there a way to speed up this array copy? @@ -185,6 +189,85 @@ class FlutterSoLoudWeb extends FlutterSoLoud { return ret; } + @override + ({PlayerErrors error, SoundHash soundHash}) setBufferStream( + int maxBufferSize, + double bufferingTimeNeeds, + int sampleRate, + int channels, + int pcmFormat, + OnBufferingCallbackTFunction? onBuffering, + ) { + final hashPtr = wasmMalloc(4); // 4 bytes for an int32 + final result = wasmSetBufferStream( + hashPtr, + maxBufferSize, + bufferingTimeNeeds, + sampleRate, + channels, + pcmFormat, + // not used on C side. The callback is set below on the JS side. Setting + // this to 1 to tell C that we have a callback. + onBuffering == null ? 0 : 1, + ); + final hash = wasmGetI32Value(hashPtr, 'i32'); + final soundHash = SoundHash(hash); + final ret = (error: PlayerErrors.values[result], soundHash: soundHash); + wasmFree(hashPtr); + + if (onBuffering != null) { + // Create a new JS function named `dartOnBufferingCallback_$hash`. + // To the function name is added the hash of the sound to make it unique. + // This is done to prevent collisions with other sounds. + // On the C++ side, this new function is called in `audiobuffer.cpp` + // within the `addData()` method (which then calls `onBuffering()` + // callback) when a playing handle reach the end of the buffer or + // there is enough audio data to start playing it again. + // If you change `dartOnBufferingCallback_$hash` name, you need to + // change it on the C++ side as well. + globalThis.setProperty( + 'dartOnBufferingCallback_$hash'.toJS, + onBuffering.toJS, + ); + } + + return ret; + } + + @override + PlayerErrors addAudioDataStream( + int hash, + Uint8List audioChunk, + ) { + final audioChunkPtr = wasmMalloc(audioChunk.length); + for (var i = 0; i < audioChunk.length; i++) { + wasmSetValue(audioChunkPtr + i, audioChunk[i], 'i8'); + } + + final result = + wasmAddAudioDataStream(hash, audioChunkPtr, audioChunk.length); + wasmFree(audioChunkPtr); + + return PlayerErrors.values[result]; + } + + @override + PlayerErrors setDataIsEnded(SoundHash soundHash) { + final result = wasmSetDataIsEnded(soundHash.hash); + return PlayerErrors.values[result]; + } + + @override + ({PlayerErrors error, int sizeInBytes}) getBufferSize(SoundHash soundHash) { + final sizeInBytesPtr = wasmMalloc(4); + final result = wasmGetBufferSize(soundHash.hash, sizeInBytesPtr); + final sizeInBytes = wasmGetI32Value(sizeInBytesPtr, 'i32'); + wasmFree(sizeInBytesPtr); + + final ret = (error: PlayerErrors.values[result], sizeInBytes: sizeInBytes); + return ret; + } + @override ({PlayerErrors error, SoundHash soundHash}) loadWaveform( WaveForm waveform, @@ -192,7 +275,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { double scale, double detune, ) { - final hashPtr = wasmMalloc(4); // 4 bytes for an int + final hashPtr = wasmMalloc(4); // 4 bytes for an int32 final result = wasmLoadWaveform( waveform.index, superWave, @@ -202,7 +285,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { ); /// "*" means unsigned int 32 - final hash = wasmGetI32Value(hashPtr, '*'); + final hash = wasmGetI32Value(hashPtr, 'i32'); final soundHash = SoundHash(hash); final ret = (error: PlayerErrors.values[result], soundHash: soundHash); wasmFree(hashPtr); @@ -237,15 +320,14 @@ class FlutterSoLoudWeb extends FlutterSoLoud { @override ({PlayerErrors error, SoundHandle handle}) speechText(String textToSpeech) { - final handlePtr = wasmMalloc(4); // 4 bytes for an int + final handlePtr = wasmMalloc(4); // 4 bytes for an int32 final textToSpeechPtr = wasmMalloc(textToSpeech.length); final result = wasmSpeechText( textToSpeechPtr, handlePtr, ); - /// "*" means unsigned int 32 - final newHandle = wasmGetI32Value(handlePtr, '*'); + final newHandle = wasmGetI32Value(handlePtr, 'i32'); final ret = ( error: PlayerErrors.values[result], handle: SoundHandle(newHandle), @@ -290,7 +372,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { bool looping = false, Duration loopingStartAt = Duration.zero, }) { - final handlePtr = wasmMalloc(4); // 4 bytes for an int + final handlePtr = wasmMalloc(4); // 4 bytes for an int32 final result = wasmPlay( soundHash.hash, volume, @@ -302,7 +384,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { ); /// "*" means unsigned int 32 - final newHandle = wasmGetI32Value(handlePtr, '*'); + final newHandle = wasmGetI32Value(handlePtr, 'i32'); final ret = (error: PlayerErrors.values[result], newHandle: SoundHandle(newHandle)); wasmFree(handlePtr); @@ -651,7 +733,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { SoundHash? soundHash, }) { // ignore: omit_local_variable_types - final idPtr = wasmMalloc(4); // 4 bytes for an int + final idPtr = wasmMalloc(4); // 4 bytes for an int32 final e = wasmIsFilterActive(soundHash?.hash ?? 0, filterType.index, idPtr); final index = wasmGetI32Value(idPtr, 'i32'); final ret = (error: PlayerErrors.values[e], index: index); @@ -663,14 +745,14 @@ class FlutterSoLoudWeb extends FlutterSoLoud { ({PlayerErrors error, List names}) getFilterParamNames( FilterType filterType, ) { - final paramsCountPtr = wasmMalloc(4); // 4 bytes for an int + final paramsCountPtr = wasmMalloc(4); // 4 bytes for an int32 final namesPtr = wasmMalloc(30 * 20); // list of 30 String with 20 chars final e = wasmGetFilterParamNames(filterType.index, paramsCountPtr, namesPtr); final pNames = []; var offsetPtr = 0; - final paramsCount = wasmGetI32Value(paramsCountPtr, '*'); + final paramsCount = wasmGetI32Value(paramsCountPtr, 'i32'); for (var i = 0; i < paramsCount; i++) { final namePtr = wasmGetI32Value(namesPtr + offsetPtr, 'i32'); final name = wasmUtf8ToString(namePtr); @@ -755,7 +837,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { bool looping = false, Duration loopingStartAt = Duration.zero, }) { - final handlePtr = wasmMalloc(4); // 4 bytes for an int + final handlePtr = wasmMalloc(4); // 4 bytes for an int32 final result = wasmPlay3d( soundHash.hash, posX, @@ -772,7 +854,7 @@ class FlutterSoLoudWeb extends FlutterSoLoud { ); /// "*" means unsigned int 32 - final newHandle = wasmGetI32Value(handlePtr, '*'); + final newHandle = wasmGetI32Value(handlePtr, 'i32'); final ret = (error: PlayerErrors.values[result], newHandle: SoundHandle(newHandle)); wasmFree(handlePtr); diff --git a/lib/src/bindings/js_extension.dart b/lib/src/bindings/js_extension.dart index 7139e5f..bf2f72b 100644 --- a/lib/src/bindings/js_extension.dart +++ b/lib/src/bindings/js_extension.dart @@ -3,6 +3,9 @@ import 'dart:js_interop'; import 'package:web/web.dart' as web; +@JS('globalThis') +external JSObject get globalThis; + @JS('Module._malloc') external int wasmMalloc(int bytesCount); @@ -45,6 +48,26 @@ external void wasmSendToWorker(int message, int value); @JS('Module.wasmWorker') external web.Worker wasmWorker; +@JS('Module._setBufferStream') +external int wasmSetBufferStream( + int hashPtr, + int maxBufferSize, + double bufferingTimeNeeds, + int sampleRate, + int channels, + int pcmFormat, + int onBufferingPtr, +); + +@JS('Module._addAudioDataStream') +external int wasmAddAudioDataStream(int hash, int audioChunkPtr, int dataLen); + +@JS('Module._setDataIsEnded') +external int wasmSetDataIsEnded(int hash); + +@JS('Module._getBufferSize') +external int wasmGetBufferSize(int hash, int sizeInBytesPtr); + @JS('Module._initEngine') external int wasmInitEngine( int deviceId, diff --git a/lib/src/enums.dart b/lib/src/enums.dart index 4799111..69388d1 100644 --- a/lib/src/enums.dart +++ b/lib/src/enums.dart @@ -65,7 +65,20 @@ enum PlayerErrors { filterParameterGetError(18), /// No playback devices were found. - noPlaybackDevicesFound(19); + noPlaybackDevicesFound(19), + + /// Trying to add PCM data but the buffer is full or not large + /// enough for the neded PCM data. Try increasing the buffer size. + /// Or, stream buffer has been set to be ended. + pcmBufferFull(20), + + /// Given hash doesn't belong to a buffer stream. + hashIsNotABufferStream(21), + + /// Trying to add PCM data but the stream is marked to be ended + /// already by the user or when the stream reached its maximum + /// capacity, in this case the stream is automatically marked to be ended. + streamEndedAlready(22); const PlayerErrors(this.value); @@ -123,6 +136,17 @@ enum PlayerErrors { case PlayerErrors.noPlaybackDevicesFound: return 'No playback devices were found while initializing engine or ' 'when changing the output device.'; + case PlayerErrors.pcmBufferFull: + return 'Trying to add PCM data but the buffer is full or not large ' + 'enough for the neded PCM data. Try increasing the buffer size. ' + 'Or, stream buffer has been set to be ended. '; + case PlayerErrors.hashIsNotABufferStream: + return "Given hash doesn't belong to a buffer stream."; + case PlayerErrors.streamEndedAlready: + return 'Trying to add PCM data but the stream is marked to be ended ' + 'already, by the user or when the stream reached its maximum ' + 'capacity, in this case the stream is automatically marked to be ' + 'ended.'; } } @@ -270,4 +294,60 @@ enum Channels { /// The channels count. final int count; + + /// Returns a human-friendly channel name. + @override + String toString() { + switch (this) { + case Channels.mono: + return 'Mono'; + case Channels.stereo: + return 'Stereo'; + case Channels.quad: + return 'Quad'; + case Channels.surround51: + return 'Surround 5.1'; + case Channels.dolby71: + return 'Dolby 7.1'; + } + } +} + +/// The PCM types. +/// +/// WARNING: Keep these in sync with `src/enums.h`. +enum BufferPcmType { + /// 32-bit floating point, little-endian. + f32le(0), + + /// 8-bit signed, little-endian. + s8(1), + + /// 16-bit signed, little-endian. + s16le(2), + + /// 32-bit signed, little-endian. + s32le(3); + + /// The integer value of the PCM type. + final int value; + + /// Constructs a valid PCM type with [value]. + // ignore: sort_constructors_first + const BufferPcmType(this.value); + + /// Returns a human-friendly channel name. + @override + String toString() { + switch (this) { + case BufferPcmType.s8: + return 'Signed 8-bit'; + case BufferPcmType.s16le: + return 'Little Endian Signed 16-bit'; + case BufferPcmType.s32le: + return 'Little Endian Signed 32-bit'; + case BufferPcmType.f32le: + return 'Little Endian Float 32-bit'; + } + } } diff --git a/lib/src/exceptions/exceptions.dart b/lib/src/exceptions/exceptions.dart index 730b714..adb2f98 100644 --- a/lib/src/exceptions/exceptions.dart +++ b/lib/src/exceptions/exceptions.dart @@ -106,6 +106,12 @@ abstract class SoLoudCppException extends SoLoudException { return const SoLoudFilterParameterGetErrorCppException(); case PlayerErrors.noPlaybackDevicesFound: return const SoLoudNoPlaybackDevicesFoundCppException(); + case PlayerErrors.pcmBufferFull: + return const SoLoudPcmBufferFullCppException(); + case PlayerErrors.hashIsNotABufferStream: + return const SoLoudHashIsNotABufferStreamCppException(); + case PlayerErrors.streamEndedAlready: + return const SoLoudStreamEndedAlreadyCppException(); } } diff --git a/lib/src/exceptions/exceptions_from_cpp.dart b/lib/src/exceptions/exceptions_from_cpp.dart index 2e0e4d6..5619aeb 100644 --- a/lib/src/exceptions/exceptions_from_cpp.dart +++ b/lib/src/exceptions/exceptions_from_cpp.dart @@ -243,3 +243,44 @@ class SoLoudNoPlaybackDevicesFoundCppException extends SoLoudCppException { 'initializing engine or when changing the output device. ' '(on the C++ side).'; } + +/// Trying to add PCM data but the stream is marked to be ended +/// already by the user or when the stream reached its maximum +/// capacity, in this case the stream is automatically marked to be ended. +class SoLoudPcmBufferFullCppException extends SoLoudCppException { + /// Creates a new [SoLoudPcmBufferFullCppException]. + const SoLoudPcmBufferFullCppException([super.message]); + + @override + String get description => + 'Trying to add PCM data but the buffer is full or not large ' + 'enough for the neded PCM data. Try increasing the buffer size. ' + 'Or, stream buffer has been set to be ended. ' + '(on the C++ side).'; +} + +/// An error occurred when asking to add audio data to an AudioSource that +/// is not a buffer stream. +class SoLoudHashIsNotABufferStreamCppException extends SoLoudCppException { + /// Creates a new [SoLoudHashIsNotABufferStreamCppException]. + const SoLoudHashIsNotABufferStreamCppException([super.message]); + + @override + String get description => 'The given AudioSource is not a buffer stream. ' + '(on the C++ side).'; +} + +/// Trying to add PCM data but the stream is marked to be ended +/// already, by the user or when the stream reached its maximum +/// capacity, in this case the stream is automatically marked to be ended. +class SoLoudStreamEndedAlreadyCppException extends SoLoudCppException { + /// Creates a new [SoLoudStreamEndedAlreadyCppException]. + const SoLoudStreamEndedAlreadyCppException([super.message]); + + @override + String get description => + 'Trying to add PCM data but the stream is marked to be ended ' + 'already, by the user or when the stream reached its maximum ' + 'capacity, in this case the stream is automatically marked to be ended. ' + '(on the C++ side).'; +} diff --git a/lib/src/soloud.dart b/lib/src/soloud.dart index 5f95a11..d90ed5c 100644 --- a/lib/src/soloud.dart +++ b/lib/src/soloud.dart @@ -522,6 +522,38 @@ interface class SoLoud { // } } + AudioSource _addNewSound( + PlayerErrors error, + String completeFileName, + int hash, + ) { + final newSound = AudioSource(SoundHash(hash)); + final alreadyLoaded = _activeSounds + .where((sound) => sound.soundHash == newSound.soundHash) + .length == + 1; + _logPlayerError(error, from: 'loadFile() result'); + if (error == PlayerErrors.noError) { + if (!alreadyLoaded) { + _activeSounds.add(newSound); + } + } else if (error == PlayerErrors.fileAlreadyLoaded) { + // If we are here, the file has been already loaded on C++ side. + // In any case return the existing sound. + // Check if it is already in [_activeSounds], if not add it. + if (alreadyLoaded) { + _log.warning(() => "Sound '$completeFileName' was already " + 'loaded. Prefer loading only once, and reusing the loaded ' + 'sound when playing.'); + } else { + _activeSounds.add(newSound); + } + } else { + throw SoLoudCppException.fromPlayerError(error); + } + return newSound; + } + // //////////////////////////////////////////////// // Below all the methods implemented with FFI for the player // //////////////////////////////////////////////// @@ -625,6 +657,179 @@ interface class SoLoud { }); } + /// Set up an audio stream. + /// + /// [maxBufferSize] the max buffer size in **bytes**. When adding audio data + /// using [addAudioDataStream] and this values is reached, the stream will + /// be considered ended (likewise we called [setDataIsEnded]). This means that + /// when playing it, it will stop at that point (if loop is not set). + /// + /// **Note:** this parameter doesn't allocate any memory, but it just limits + /// the amount of data that can be added. + /// + /// [bufferingTimeNeeds] the buffering time needed in seconds. If a handle + /// reaches the current buffer length, it will start to buffer pausing it and + /// waiting until the buffer will have enough data to cover this time. + /// + /// [sampleRate] the sample rate. Usually is 22050 or 44100 (CD quality). + /// + /// [channels] enum to choose the number of channels. + /// + /// [pcmFormat] enum to choose from `f32le`, `s8`, `s16le` and `s32le`. + /// + /// [onBuffering] a callback that is called when starting to buffer + /// (isBuffering = true) and when the buffering is done (isBuffering = false). + /// The callback is called with the `handle` which triggered the event and + /// the `time` in seconds. + /// + /// Throws [SoLoudNotInitializedException] if the engine is not initialized. + AudioSource setBufferStream({ + int maxBufferSize = 1024 * 1024 * 100, // 100 MB in bytes + double bufferingTimeNeeds = 2, // 2 seconds of data needed to un-pause + int sampleRate = 22050, + Channels channels = Channels.mono, + BufferPcmType pcmFormat = BufferPcmType.s16le, + void Function(bool isBuffering, int handle, double time)? onBuffering, + }) { + if (!isInitialized) { + throw const SoLoudNotInitializedException(); + } + + final ret = SoLoudController().soLoudFFI.setBufferStream( + maxBufferSize, + bufferingTimeNeeds, + sampleRate, + channels.count, + pcmFormat.value, + onBuffering, + ); + + final newSound = _addNewSound(ret.error, '', ret.soundHash.hash); + return newSound; + } + + /// Add PCM audio data to the stream. + /// + /// This method can be called within an `Isolate` making it possible + /// to create PCM data and send them to the buffer without frezing + /// the main thread. + /// When finishing to add data to the stream, call [setDataIsEnded]. + /// + /// [source] the audio source to add audio data to. + /// + /// [audioChunk] the audio data to add. This is of `Uint8List` type, so if + /// you want to add any other typed data like `Float32List`, 'Int32List', + /// 'Int16List' etc, you will have to convert it to `Uint8List`: + /// `[yourTypedData*List].buffer.asUint8List()`. + /// + /// **Example**: compute PCM audio inside an `Isolate` returning the new + /// `AudioSource`. + /// ```dart + /// // This is a global function or a static member of a class. + /// @pragma('vm:entry-point') + /// Future computePCM(void args) async { + /// final pcmBuffer = Uint8List(1024 * 1024); // 1 MB in bytes + /// final pcmAudio = SoLoud.instance.setBufferStream( + /// maxBufferSize: 1024 * 1024, // 1 MB in bytes + /// pcmFormat: BufferPcmType.s8, // signed 8 bits + /// ); + /// for (var i = 0; i < pcmBuffer.length; i++) { + /// // Compose your PCM data here. + /// pcmBuffer[i] = Random().nextInt(256) - 128; + /// } + /// + /// /// Add the PCM data to the audio stream. + /// SoLoud.instance + /// .addAudioDataStream(pcmAudio, pcmBuffer.buffer.asUint8List()); + /// + /// /// Mark the end of the PCM data. + /// SoLoud.instance.setDataIsEnded(pcmAudio); + /// + /// return pcmAudio; + /// } + /// + /// /// A method inside a class to call the `computePCM` function. + /// Future generate() async { + /// /// Generate PCM data inside an Isolate. + /// final myNewGeneratedAudio = await compute(computePCM, ''); + /// } + /// ``` + /// An example is also included in `example/lib/buffer_stream/generate.dart`. + /// + /// Throws [SoLoudNotInitializedException] if the engine is not initialized. + /// Throws [SoLoudPcmBufferFullCppException] if trying to add data and the + /// buffer is full. + /// Throws [SoLoudHashIsNotABufferStreamCppException] if the given [source] + /// is not a buffer stream. + /// Throws [SoLoudStreamEndedAlreadyCppException] if trying to add PCM data + /// but the stream is marked to be ended already, by the user or when the + /// stream reached its maximum capacity, in this case the stream is + /// automatically marked to be ended. + /// Thows [SoLoudOutOfMemoryException] if the buffer is out of OS memory or + /// the given `maxBufferSize` of the `setBufferStream` call is too small. + void addAudioDataStream( + AudioSource source, + Uint8List audioChunk, + ) { + if (!isInitialized) { + throw const SoLoudNotInitializedException(); + } + + final e = SoLoudController().soLoudFFI.addAudioDataStream( + source.soundHash.hash, + audioChunk, + ); + + if (e != PlayerErrors.noError) { + _logPlayerError(e, from: 'addAudioDataStream() result'); + throw SoLoudCppException.fromPlayerError(e); + } + } + + /// Set the end of the data stream. + /// + /// By setting the stream to be ended means that when playing it, it can + /// handle the stop event when it reaches the end of the data stream or can + /// be looped if the looping is enabled. + /// + /// [hash] the hash of the stream sound. + /// + /// Throws [SoLoudNotInitializedException] if the engine is not initialized. + /// Throws [SoLoudSoundHashNotFoundDartException] if the [sound] is not found. + void setDataIsEnded(AudioSource sound) { + if (!isInitialized) { + throw const SoLoudNotInitializedException(); + } + final e = SoLoudController().soLoudFFI.setDataIsEnded(sound.soundHash); + + if (e != PlayerErrors.noError) { + _logPlayerError(e, from: 'setDataIsEnded() result'); + throw SoLoudCppException.fromPlayerError(e); + } + } + + /// Get the current buffer size in bytes of this sound with hash [hash]. + /// [hash] the hash of the stream sound. + /// + /// **NOTE**: the returned value is in bytes and since by default uses floats, + /// the returned value should be divided by 4 and by the number of channels + /// to have the number of samples. + /// + /// Throws [SoLoudNotInitializedException] if the engine is not initialized. + /// Throws [SoLoudSoundHashNotFoundDartException] if the [sound] is not found. + int getBufferSize(AudioSource sound) { + if (!isInitialized) { + throw const SoLoudNotInitializedException(); + } + final e = SoLoudController().soLoudFFI.getBufferSize(sound.soundHash); + + if (e.error != PlayerErrors.noError) { + _logPlayerError(e.error, from: 'getBufferSize() result'); + throw SoLoudCppException.fromPlayerError(e.error); + } + return e.sizeInBytes; + } + /// Load a new sound to be played once or multiple times later, from /// an asset. /// @@ -852,6 +1057,8 @@ interface class SoLoud { /// Returns the [SoundHandle] of the new sound instance. /// /// Throws [SoLoudNotInitializedException] if the engine is not initialized. + /// Throws [SoLoudSoundHashNotFoundDartException] if the given [sound] + /// is not found. Future play( AudioSource sound, { double volume = 1, diff --git a/lib/src/sound_handle.dart b/lib/src/sound_handle.dart index c524484..a087ed7 100644 --- a/lib/src/sound_handle.dart +++ b/lib/src/sound_handle.dart @@ -18,7 +18,6 @@ import 'package:meta/meta.dart'; /// for users to create a handle from Dart. extension type const SoundHandle._(int id) { /// Constructs a valid handle with [id]. - @internal const SoundHandle(this.id) : assert( id >= 0, diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 7ba9b4d..7a46047 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -40,6 +40,7 @@ list(APPEND PLUGIN_SOURCES "${SRC_DIR}/analyzer.cpp" "${SRC_DIR}/synth/basic_wave.cpp" "${SRC_DIR}/waveform/waveform.cpp" + "${SRC_DIR}/audiobuffer/audiobuffer.cpp" "${SRC_DIR}/filters/filters.cpp" "${SRC_DIR}/filters/pitch_shift_filter.cpp" "${SRC_DIR}/filters/smbPitchShift.cpp" @@ -60,7 +61,7 @@ target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR} target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) -target_compile_options("${PLUGIN_NAME}" PRIVATE -Wall -Wno-error -fPIC -O0 -msse3 -msse2) # -ldl -lpthread -lm +target_compile_options("${PLUGIN_NAME}" PRIVATE -Wall -Wno-error -Wno-vla -fPIC -O0 -msse3 -msse2) # -ldl -lpthread -lm # List of absolute paths to libraries that should be bundled with the plugin. set(flutter_soloud_bundled_libraries diff --git a/src/active_sound.h b/src/active_sound.h index 4fbcdf2..8bb3f13 100644 --- a/src/active_sound.h +++ b/src/active_sound.h @@ -1,8 +1,8 @@ #ifndef ACTIVE_SOUND_H #define ACTIVE_SOUND_H -#include "enums.h" #include "filters/filters.h" +#include "enums.h" #include "soloud.h" #include @@ -10,18 +10,28 @@ #include class Filters; +#define MAX_DOUBLE 1.7976931348623157e+308 + +struct ActiveHandle +{ + SoLoud::handle handle; + // this is managed only in `audiobuffer.cpp` an it is used to + // know when a handle reaches the end or when there is not enough data + // in the buffer to resume playing. Used also to send the buffering events. + SoLoud::time bufferingTime; +}; /// The default number of concurrent voices - maximum number of "streams" - is 16, /// but this can be adjusted at runtime -typedef struct ActiveSound +struct ActiveSound { std::unique_ptr sound; SoundType soundType; - std::vector handle; + std::vector handle; std::unique_ptr filters; // unique identifier of this sound based on the file name unsigned int soundHash; std::string completeFileName; -} ActiveSound; +}; #endif // ACTIVE_SOUND_H \ No newline at end of file diff --git a/src/audiobuffer/audiobuffer.cpp b/src/audiobuffer/audiobuffer.cpp new file mode 100644 index 0000000..5607a2c --- /dev/null +++ b/src/audiobuffer/audiobuffer.cpp @@ -0,0 +1,227 @@ + +#include +#include +#include +#include + +#include "audiobuffer.h" + +#ifdef __EMSCRIPTEN__ +#include +#endif + +// TODO: readSamplesFromBuffer as for waveform + +namespace SoLoud +{ + BufferStreamInstance::BufferStreamInstance(BufferStream *aParent) + { + mParent = aParent; + mOffset = 0; + } + + BufferStreamInstance::~BufferStreamInstance() + { + } + + unsigned int BufferStreamInstance::getAudio(float *aBuffer, unsigned int aSamplesToRead, unsigned int aBufferSize) + { + if (mParent->mBuffer.getFloatsBufferSize() == 0) + { + memset(aBuffer, 0, sizeof(float) * aSamplesToRead); + return 0; + } + + unsigned int bufferSize = mParent->mBuffer.getFloatsBufferSize(); + float *buffer = reinterpret_cast(mParent->mBuffer.buffer.data()); + int samplesToRead = mOffset + aSamplesToRead > bufferSize ? bufferSize - mOffset : aSamplesToRead; + if (samplesToRead <= 0) + return 0; + + if (samplesToRead != aSamplesToRead) + { + memset(aBuffer, 0, sizeof(float) * aSamplesToRead); + } + + if (mChannels == 1) + { + // Optimization: if we have a mono audio source, we can just copy all the data in one go. + memcpy(aBuffer, buffer + mOffset, sizeof(float) * samplesToRead); + } + else + { + // From SoLoud documentation: + // So, if 1024 samples are requested from a stereo audio source, the first 1024 floats + // should be for the first channel, and the next 1024 samples should be for the second channel. + unsigned int i, j; + for (j = 0; j < mChannels; j++) + { + for (i = 0; i < samplesToRead; i++) + { + aBuffer[j * samplesToRead + i] = buffer[mOffset + i * mChannels + j]; + } + } + } + + mOffset += samplesToRead * mChannels; + return samplesToRead; + } + + result BufferStreamInstance::seek(double aSeconds, float *mScratch, unsigned int mScratchSize) + { + return AudioSourceInstance::seek(aSeconds, mScratch, mScratchSize); + } + + result BufferStreamInstance::rewind() + { + mOffset = 0; + mStreamPosition = 0.0f; + return 0; + } + + bool BufferStreamInstance::hasEnded() + { + if (mOffset >= mParent->mSampleCount * mParent->mPCMformat.bytesPerSample && + mParent->dataIsEnded) + { + return 1; + } + return 0; + } + + // ////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////// + + BufferStream::BufferStream() {} + + BufferStream::~BufferStream() + { + stop(); + } + + void BufferStream::setBufferStream( + Player *aPlayer, + ActiveSound *aParent, + unsigned int maxBufferSize, + SoLoud::time bufferingTimeNeeds, + PCMformat pcmFormat, + dartOnBufferingCallback_t onBufferingCallback) + { + mSampleCount = 0; + dataIsEnded = false; + mEndianness = Endianness::BUFFER_LITTLE_ENDIAN; // TODO? + mThePlayer = aPlayer; + mParent = aParent; + mPCMformat.sampleRate = pcmFormat.sampleRate; + mPCMformat.channels = pcmFormat.channels; + mPCMformat.bytesPerSample = pcmFormat.bytesPerSample; + mPCMformat.dataType = pcmFormat.dataType; + mBuffer.clear(); + mBuffer.setSizeInBytes(maxBufferSize); + mBufferingTimeNeeds = bufferingTimeNeeds; + mChannels = pcmFormat.channels; + mBaseSamplerate = (float)pcmFormat.sampleRate; + mOnBufferingCallback = onBufferingCallback; + } + + void BufferStream::setDataIsEnded() + { + dataIsEnded = true; + } + + PlayerErrors BufferStream::addData(const void *aData, unsigned int aDataLen) + { + if (dataIsEnded) + { + return streamEndedAlready; + } + + unsigned int bytesWritten = 0; + // add PCM data to the buffer + bytesWritten = mBuffer.addData(mPCMformat, aData, aDataLen / mPCMformat.bytesPerSample); + + mSampleCount += bytesWritten / mPCMformat.bytesPerSample; + + // If a handle reaches the end and data is not ended, we have to wait for it has enough data + // to reach [TIME_FOR_BUFFERING] and restart playing it. + time currBufferTime = getLength(); + for (int i = 0; i < mParent->handle.size(); i++) + { + double pos = mThePlayer->getPosition(mParent->handle[i].handle); + // This handle needs to wait for [TIME_FOR_BUFFERING] + if (pos >= currBufferTime && !mThePlayer->getPause(mParent->handle[i].handle)) + { + mParent->handle[i].bufferingTime = currBufferTime; + mThePlayer->setPause(mParent->handle[i].handle, true); + if (mOnBufferingCallback != nullptr) + { +#ifdef __EMSCRIPTEN__ + // Call the Dart callback stored on globalThis, if it exists. + // The `dartOnBufferingCallback_$hash` function is created in + // `setBufferStream()` in `bindings_player_web.dart` and it's + // meant to call the Dart callback passed to `setBufferStream()`. + EM_ASM({ + // Compose the function name for this soundHash + var functionName = "dartOnBufferingCallback_" + $3; + if (typeof window[functionName] === "function") { + var buffering = $0 == 1 ? true : false; + window[functionName](buffering, $1, $2); // Call it + } else { + console.log("EM_ASM 'dartOnBufferingCallback_$hash' not found."); + } }, true, mParent->handle[i].handle, currBufferTime, mParent->soundHash); +#else + mOnBufferingCallback(true, mParent->handle[i].handle, currBufferTime); +#endif + } + } + if (currBufferTime - mParent->handle[i].bufferingTime >= mBufferingTimeNeeds && + mThePlayer->getPause(mParent->handle[i].handle)) + { + mThePlayer->setPause(mParent->handle[i].handle, false); + mParent->handle[i].bufferingTime = MAX_DOUBLE; + if (mOnBufferingCallback != nullptr) + { +#ifdef __EMSCRIPTEN__ + // Call the Dart callback stored on globalThis, if it exists. + EM_ASM({ + // Compose the function name for this soundHash + var functionName = "dartOnBufferingCallback_" + $3; + if (typeof window[functionName] === "function") { + var buffering = $0 == 1 ? true : false; + window[functionName](buffering, $1, $2); // Call it + } else { + console.log("EM_ASM 'dartOnBufferingCallback_$hash' not found."); + } }, false, mParent->handle[i].handle, currBufferTime, mParent->soundHash); +#else + mOnBufferingCallback(false, mParent->handle[i].handle, currBufferTime); +#endif + } + } + } + + // data has been added to the buffer, but not all because reached its full capacity. + // So mark this stream as ended and no more data can be added. + if (bytesWritten < aDataLen / mPCMformat.bytesPerSample) + { + dataIsEnded = true; + return pcmBufferFull; + } + + return noError; + } + + AudioSourceInstance *BufferStream::createInstance() + { + return new BufferStreamInstance(this); + } + + double BufferStream::getLength() + { + if (mBaseSamplerate == 0) + return 0; + return mSampleCount / mBaseSamplerate * mPCMformat.bytesPerSample / mPCMformat.channels; + } +}; diff --git a/src/audiobuffer/audiobuffer.h b/src/audiobuffer/audiobuffer.h new file mode 100644 index 0000000..7f7f46e --- /dev/null +++ b/src/audiobuffer/audiobuffer.h @@ -0,0 +1,67 @@ +#pragma once + +#ifndef _AUDIOBUFFER_H +#define _AUDIOBUFFER_H + +#include +#include +#include +#include "soloud.h" +#include "../player.h" +#include "../enums.h" +#include "../active_sound.h" +#include "buffer.h" + +class Player; + +namespace SoLoud +{ + class BufferStream; + + class BufferStreamInstance : public AudioSourceInstance + { + BufferStream *mParent; + unsigned int mOffset; + + public: + BufferStreamInstance(BufferStream *aParent); + virtual unsigned int getAudio(float *aBuffer, unsigned int aSamplesToRead, unsigned int aBufferSize); + virtual result seek(double aSeconds, float *mScratch, unsigned int mScratchSize); + virtual result rewind(); + virtual bool hasEnded(); + virtual ~BufferStreamInstance(); + }; + + class BufferStream : public AudioSource + { + public: + // The flutter_soloud main [player] instance + Player *mThePlayer; + // Used to access the AudioSource this stream belongs to + ActiveSound* mParent; + dartOnBufferingCallback_t mOnBufferingCallback; + enum Endianness mEndianness; // TODO? + unsigned int mMaxBufferSize; + unsigned int mSampleCount; + SoLoud::time mBufferingTimeNeeds; + PCMformat mPCMformat; + Buffer mBuffer; + bool dataIsEnded; + + BufferStream(); + virtual ~BufferStream(); + void setBufferStream( + Player *aPlayer, + ActiveSound *aParent, + unsigned int maxBufferSize = 1024 * 1024 * 100, // 100 Mbytes + time bufferingTimeNeeds = 2.0f, // 2 seconds of data to wait + PCMformat pcmFormat = {44100, 2, 2, PCM_S16LE}, + dartOnBufferingCallback_t onBufferingCallback = nullptr); + void setDataIsEnded(); + PlayerErrors addData(const void *aData, unsigned int numSamples); + virtual AudioSourceInstance *createInstance(); + time getLength(); + }; +}; + +#endif // _AUDIOBUFFER_H \ No newline at end of file diff --git a/src/audiobuffer/buffer.h b/src/audiobuffer/buffer.h new file mode 100644 index 0000000..63bb7de --- /dev/null +++ b/src/audiobuffer/buffer.h @@ -0,0 +1,119 @@ +#ifndef BUFFER_H +#define BUFFER_H + +#include +#include +#include +#include +#include + +enum Endianness // TODO? +{ + BUFFER_LITTLE_ENDIAN, + BUFFER_BIG_ENDIAN +}; + +class Buffer +{ +public: + std::vector buffer; // Buffer that stores int8_t data + +private: + size_t maxBytes; // Maximum capacity in bytes + +public: + // Constructor that accepts the maxBytes parameter + Buffer() : maxBytes(0) {} + + ~Buffer() + { + clear(); + } + + void setSizeInBytes(size_t newBytes) + { + maxBytes = newBytes; + + } + + // Return the number of data written. Should be the same as numSamples else + // the buffer reached the [maxBytes] meaning the buffer is full. + size_t addData(const PCMformat format, const void* data, size_t numSamples) { + switch (format.dataType) + { + case 0: // PCM_F32LE + { + return addData(reinterpret_cast(data), numSamples); + } + break; + case 1: // PCM_S8 + { + const int8_t* data8 = reinterpret_cast(data); + float* d = new float[numSamples]; + for (size_t i = 0; i < numSamples; ++i) { + d[i] = data8[i] / 128.0f; + } + size_t ret = addData(d, numSamples); + delete[] d; + return ret; + } + break; + case 2: // PCM_S16LE + { + const int16_t* data16 = reinterpret_cast(data); + float* d = new float[numSamples]; + for (size_t i = 0; i < numSamples; ++i) { + d[i] = data16[i] / 32768.0f; + } + size_t ret = addData(d, numSamples); + delete[] d; + return ret; + } + break; + case 3: // PCM_S32LE + { + const int32_t* data32 = reinterpret_cast(data); + float* d = new float[numSamples]; + for (size_t i = 0; i < numSamples; ++i) { + d[i] = data32[i] / 2147483648.0f; + } + size_t ret = addData(d, numSamples); + delete[] d; + return ret; + } + break; + } + } + + // Overload for float data, directly adding its bytes to the buffer + // Return the number of floats written. + size_t addData(const float* data, size_t numSamples) { + // No normalization needed for floats: the player is set to use f32 + unsigned int bytesNeeded = numSamples * sizeof(float); + int32_t newNumSamples = numSamples; + if (buffer.size() + bytesNeeded > maxBytes) + { + int bytesLeft = maxBytes - buffer.size(); + newNumSamples = bytesLeft / sizeof(float); + if (bytesLeft <= 0) + return 0; + } + const int8_t* data8 = reinterpret_cast(data); // Convert float array to int8_t array + buffer.insert(buffer.end(), data8, data8 + newNumSamples*sizeof(float)); // Append directly + return newNumSamples; + } + + // Function to get the current size of the buffer in bytes + size_t getFloatsBufferSize() const + { + return buffer.size() / sizeof(float); + } + + // Clear the buffer + void clear() + { + buffer.clear(); + } +}; + +#endif // BUFFER_H diff --git a/src/bindings.cpp b/src/bindings.cpp index 9c2d890..64fe342 100644 --- a/src/bindings.cpp +++ b/src/bindings.cpp @@ -1,7 +1,10 @@ +#include "soloud/include/soloud_fft.h" +#include "soloud_thread.h" #include "player.h" #include "analyzer.h" #include "synth/basic_wave.h" #include "waveform/waveform.h" + #ifndef COMMON_H #include "common.h" #endif @@ -10,9 +13,6 @@ #include #endif -#include "soloud/include/soloud_fft.h" -#include "soloud_thread.h" - #include #include #include @@ -354,6 +354,84 @@ extern "C" return (PlayerErrors)player.get()->loadMem(uniqueName, buffer, length, loadIntoMem, *hash); } + /// Set up an audio stream. + /// + /// [maxBufferSize] the max buffer size in bytes. + /// [sampleRate], [channels], [pcmFormat] should be set in the case the audio data is PCM. + /// [pcmFormat]: 0 = f32le, 1 = s8, 2 = s16le, 3 = s32le + FFI_PLUGIN_EXPORT enum PlayerErrors setBufferStream( + unsigned int *hash, + unsigned long maxBufferSize, + double bufferingTimeNeeds, + unsigned int sampleRate, + unsigned int channels, + int pcmFormat, + dartOnBufferingCallback_t onBufferingCallback) + { + std::lock_guard guard_init(init_deinit_mutex); + std::lock_guard guard_load(loadMutex); + if (player.get() == nullptr || !player.get()->isInited()) + return backendNotInited; + + unsigned int bytesPerSample; + switch (pcmFormat) + { + case 0: + bytesPerSample = 4; + break; + case 1: + bytesPerSample = 1; + break; + case 2: + bytesPerSample = 2; + break; + case 3: + bytesPerSample = 4; + break; + } + PCMformat dataType = {sampleRate, channels, bytesPerSample, (BufferPcmType)pcmFormat}; + PlayerErrors e = (PlayerErrors)player.get()->setBufferStream( + *hash, + maxBufferSize, + bufferingTimeNeeds, + dataType, + onBufferingCallback); + return e; + } + + /// Add a chunk of audio data to the buffer stream. + /// + /// [hash] the hash of the sound. + /// [data] the audio data to add. + /// [aDataLen] the length of [data]. + FFI_PLUGIN_EXPORT enum PlayerErrors addAudioDataStream( + unsigned int hash, + const unsigned char *data, + unsigned int aDataLen) + { + if (player.get() == nullptr || !player.get()->isInited()) + return backendNotInited; + return player.get()->addAudioDataStream(hash, data, aDataLen); + } + + // Set the end of the data stream. + // [hash] the hash of the stream sound. + FFI_PLUGIN_EXPORT enum PlayerErrors setDataIsEnded(unsigned int hash) + { + if (player.get() == nullptr || !player.get()->isInited()) + return backendNotInited; + return player.get()->setDataIsEnded(hash); + } + + // Get the current buffer size in bytes of this sound with hash [hash]. + // [hash] the hash of the stream sound. + FFI_PLUGIN_EXPORT enum PlayerErrors getBufferSize(unsigned int hash, unsigned int *sizeInBytes) + { + if (player.get() == nullptr || !player.get()->isInited()) + return backendNotInited; + return player.get()->getBufferSize(hash, sizeInBytes); + } + /// Load a new waveform to be played once or multiple times later /// /// [waveform] WAVE_SQUARE = 0, diff --git a/src/enums.h b/src/enums.h index 4ec3150..033269d 100644 --- a/src/enums.h +++ b/src/enums.h @@ -48,6 +48,15 @@ typedef enum PlayerErrors filterParameterGetError = 18, /// No playback devices were found. noPlaybackDevicesFound = 19, + /// Trying to add PCM data but the buffer is full or not large + /// enough for the neded PCM data. Try increasing the buffer size. + pcmBufferFull = 20, + /// Given hash doesn't belong to a buffer stream. + hashIsNotABufferStream = 21, + /// Trying to add PCM data but the stream is marked to be ended + /// already, by the user or when the stream reached its maximum + /// capacity, in this case the stream is automatically marked to be ended. + streamEndedAlready = 22 } PlayerErrors_t; /// Possible read sample errors @@ -82,7 +91,9 @@ typedef enum SoundType // using Soloud::wavStream TYPE_WAVSTREAM, // this sound is a waveform - TYPE_SYNTH + TYPE_SYNTH, + // this sound is a streaming buffer + TYPE_BUFFER_STREAM, } SoundType_t; typedef enum FilterType @@ -99,4 +110,25 @@ typedef enum FilterType PitchShiftFilter } FilterType_t; +/// WARNING: Keep these in sync with `lib/src/enums.dart`. +typedef enum BufferPcmType +{ + PCM_F32LE = 0, + PCM_S8 = 1, + PCM_S16LE = 2, + PCM_S32LE = 3, +} BufferPcmType_t; + + +typedef struct PCMformat +{ + unsigned int sampleRate; + unsigned int channels; + unsigned int bytesPerSample; + BufferPcmType dataType; +} PCMformat; + + +typedef void (*dartOnBufferingCallback_t)(bool isBuffering, unsigned int handle, double time); + #endif // ENUMS_H \ No newline at end of file diff --git a/src/ffi_gen_tmp.h b/src/ffi_gen_tmp.h index 48d19b0..890847f 100644 --- a/src/ffi_gen_tmp.h +++ b/src/ffi_gen_tmp.h @@ -19,4 +19,6 @@ //--------------------- copy here the new functions to generate -FFI_PLUGIN_EXPORT enum PlayerErrors changeDevice(int deviceID); +// Get the current buffer size in bytes of this sound with hash [hash]. +// [hash] the hash of the stream sound. +FFI_PLUGIN_EXPORT enum PlayerErrors getBufferSize(unsigned int hash, unsigned int *sizeInBytes); diff --git a/src/filters/filters.h b/src/filters/filters.h index 154a9bb..2c56848 100644 --- a/src/filters/filters.h +++ b/src/filters/filters.h @@ -23,6 +23,8 @@ #include #include +struct ActiveSound; + struct FilterObject { FilterType type; diff --git a/src/flutter_soloud.cpp b/src/flutter_soloud.cpp index 1f72e8c..433ef5e 100755 --- a/src/flutter_soloud.cpp +++ b/src/flutter_soloud.cpp @@ -105,6 +105,7 @@ #include "analyzer.cpp" #include "synth/basic_wave.cpp" #include "waveform/waveform.cpp" +#include "audiobuffer/audiobuffer.cpp" #include "filters/filters.cpp" #include "filters/pitch_shift_filter.cpp" #include "filters/smbPitchShift.cpp" diff --git a/src/player.cpp b/src/player.cpp index 9a17d5d..a58353c 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -16,7 +16,6 @@ #include #endif - Player::Player() : mInited(false), mFilters(&soloud, nullptr) {} Player::~Player() @@ -53,12 +52,14 @@ PlayerErrors Player::init(unsigned int sampleRate, unsigned int bufferSize, unsi SoLoud::result result = soloud.init( SoLoud::Soloud::CLIP_ROUNDOFF, SoLoud::Soloud::MINIAUDIO, sampleRate, bufferSize, channels, playbackInfos_id); - if (result == SoLoud::SO_NO_ERROR){ + if (result == SoLoud::SO_NO_ERROR) + { mInited = true; mSampleRate = sampleRate; mBufferSize = bufferSize; mChannels = channels; - } else + } + else result = backendNotInited; return (PlayerErrors)result; } @@ -77,7 +78,7 @@ PlayerErrors Player::changeDevice(int deviceID) playbackInfos_id = &pPlaybackInfos[deviceID].id; SoLoud::result result = soloud.miniaudio_changeDevice(playbackInfos_id); - + // miniaudio_changeDevice can only throw UNKNOWN_ERROR. This means that // for some reasons the device could not be changed (maybe the engine // was turned off in the meantime?). @@ -103,11 +104,11 @@ std::vector Player::listPlaybackDevices() } if ((result = ma_context_get_devices( - &context, - &pPlaybackInfos, - &playbackCount, - &pCaptureInfos, - &captureCount)) != MA_SUCCESS) + &context, + &pPlaybackInfos, + &playbackCount, + &pCaptureInfos, + &captureCount)) != MA_SUCCESS) { printf("Failed to get devices %d\n", result); return ret; @@ -196,6 +197,12 @@ const std::string Player::getErrorString(PlayerErrors errorCode) const return "error: getting filter parameter error!"; case noPlaybackDevicesFound: return "error: no playback devices found!"; + case pcmBufferFull: + return "error: pcm buffer full!"; + case hashIsNotABufferStream: + return "error: hash is not a buffer stream!"; + case streamEndedAlready: + return "error: trying to add PCM data but the stream is marked to be ended!"; } return "Other error"; } @@ -207,14 +214,13 @@ PlayerErrors Player::loadFile( { if (!mInited) return backendNotInited; - + *hash = 0; unsigned int newHash = (int32_t)std::hash{}(completeFileName) & 0x7fffffff; /// check if the sound has been already loaded auto const s = findByHash(newHash); - if (s != nullptr) { *hash = newHash; @@ -223,8 +229,6 @@ PlayerErrors Player::loadFile( auto sound = std::make_unique(); - - sound->completeFileName = std::string(completeFileName); sound->soundHash = newHash; @@ -245,12 +249,13 @@ PlayerErrors Player::loadFile( if (result != SoLoud::SO_NO_ERROR) { *hash = 0; - } else { + } + else + { *hash = newHash; sound->filters = std::make_unique(&soloud, sound.get()); sounds.push_back(std::move(sound)); } - return (PlayerErrors)result; } @@ -294,7 +299,7 @@ PlayerErrors Player::loadMem( newSound.get()->soundType = TYPE_WAVSTREAM; result = static_cast(newSound.get()->sound.get())->loadMem(mem, length, false, true); } - + if (result == SoLoud::SO_NO_ERROR) { newSound.get()->filters = std::make_unique(&soloud, newSound.get()); @@ -304,6 +309,74 @@ PlayerErrors Player::loadMem( return (PlayerErrors)result; } +PlayerErrors Player::setBufferStream( + unsigned int &hash, + unsigned long maxBufferSize, + SoLoud::time bufferingTimeNeeds, + PCMformat pcmFormat, + dartOnBufferingCallback_t onBufferingCallback) +{ + if (!mInited) + return backendNotInited; + + std::random_device rd; + std::mt19937 g(rd()); + std::uniform_int_distribution dist(0, INT32_MAX); + + hash = dist(g); + + std::unique_ptr newSound = std::make_unique(); + newSound.get()->completeFileName = ""; + newSound.get()->soundHash = hash; + + newSound.get()->sound = std::make_unique(); + newSound.get()->soundType = TYPE_BUFFER_STREAM; + static_cast(newSound.get()->sound.get())->setBufferStream(this, newSound.get(), maxBufferSize, bufferingTimeNeeds, pcmFormat, onBufferingCallback); + + newSound.get()->filters = std::make_unique(&soloud, newSound.get()); + sounds.push_back(std::move(newSound)); + + return noError; +} + +PlayerErrors Player::addAudioDataStream( + unsigned int hash, + const unsigned char *data, + unsigned int aDataLen) +{ + auto const s = findByHash(hash); + + if (s == nullptr) + return soundHashNotFound; + + if (s->soundType != TYPE_BUFFER_STREAM) + return hashIsNotABufferStream; + + return static_cast(s->sound.get())->addData(data, aDataLen); +} + +PlayerErrors Player::setDataIsEnded(unsigned int hash) +{ + auto const s = findByHash(hash); + + if (s == nullptr || s->soundType != TYPE_BUFFER_STREAM) + return soundHashNotFound; + + static_cast(s->sound.get())->setDataIsEnded(); + return noError; +} + +PlayerErrors Player::getBufferSize(unsigned int hash, unsigned int *sizeInBytes) +{ + auto const s = findByHash(hash); + + if (s == nullptr || s->soundType != TYPE_BUFFER_STREAM) + return soundHashNotFound; + + *sizeInBytes = static_cast(s->sound.get())->mBuffer.buffer.size(); + return noError; +} + PlayerErrors Player::loadWaveform( int waveform, bool superWave, @@ -318,7 +391,7 @@ PlayerErrors Player::loadWaveform( std::random_device rd; std::mt19937 g(rd()); - std::uniform_int_distribution dist(0, UINT32_MAX); + std::uniform_int_distribution dist(0, INT32_MAX); hash = dist(g); @@ -425,7 +498,7 @@ unsigned int Player::play( SoLoud::handle newHandle = soloud.play( *sound->sound.get(), volume, pan, paused, 0); if (newHandle != 0) - sound->handle.push_back(newHandle); + sound->handle.push_back({newHandle, MAX_DOUBLE}); if (looping) { @@ -453,7 +526,7 @@ void Player::removeHandle(unsigned int handle) for (int i = 0; i < sounds.size(); ++i) for (int n = 0; n < sounds[i]->handle.size(); ++n) { - if (sounds[i]->handle[n] == handle) + if (sounds[i]->handle[n].handle == handle) { sounds[i]->handle.erase(sounds[i]->handle.begin() + n); e = false; @@ -516,7 +589,7 @@ PlayerErrors Player::textToSpeech(const std::string &textToSpeech, unsigned int { handle = soloud.play(speech); sounds.back().get()->filters = std::make_unique(&soloud, sounds.back().get()); - sounds.back().get()->handle.push_back(handle); + sounds.back().get()->handle.push_back({handle, MAX_DOUBLE}); } else { @@ -554,9 +627,11 @@ double Player::getLength(unsigned int soundHash) return 0.0; if (s->soundType == TYPE_WAV) return static_cast(s->sound.get())->getLength(); - - // if (s->soundType == TYPE_WAVSTREAM) - return static_cast(s->sound.get())->getLength(); + if (s->soundType == TYPE_BUFFER_STREAM) + return static_cast(s->sound.get())->getLength(); + if (s->soundType == TYPE_WAVSTREAM) + return static_cast(s->sound.get())->getLength(); + return 0.0; } // time in seconds @@ -615,10 +690,14 @@ void Player::setPan(SoLoud::handle handle, float pan) void Player::setPanAbsolute(SoLoud::handle handle, float panLeft, float panRight) { - if (panLeft > 1.0f) panLeft = 1.0f; - if (panLeft < -1.0f) panLeft = -1.0f; - if (panRight > 1.0f) panRight = 1.0f; - if (panRight < -1.0f) panRight = -1.0f; + if (panLeft > 1.0f) + panLeft = 1.0f; + if (panLeft < -1.0f) + panLeft = -1.0f; + if (panRight > 1.0f) + panRight = 1.0f; + if (panRight < -1.0f) + panRight = -1.0f; soloud.setPanAbsolute(handle, panLeft, panRight); } @@ -636,16 +715,23 @@ int Player::countAudioSource(unsigned int soundHash) { auto const &s = findByHash(soundHash); - if (s == nullptr || s->soundType == TYPE_SYNTH) + if (s == nullptr) return 0; - if (s->soundType == TYPE_WAV) + + SoLoud::AudioSource *as; + switch (s->soundType) { - SoLoud::AudioSource *as = static_cast(s->sound.get()); - return soloud.countAudioSource(*as); + case TYPE_SYNTH: + return 0; + case TYPE_WAV: + as = static_cast(s->sound.get()); + case TYPE_WAVSTREAM: + as = static_cast(s->sound.get()); + case TYPE_BUFFER_STREAM: + as = static_cast(s->sound.get()); + default: + return 0; } - - // if (s->soundType == TYPE_WAVSTREAM) - SoLoud::AudioSource *as = static_cast(s->sound.get()); return soloud.countAudioSource(*as); } @@ -682,7 +768,7 @@ ActiveSound *Player::findByHandle(SoLoud::handle handle) int index = 0; while (index < (int)sounds[i].get()->handle.size()) { - if (sounds[i].get()->handle[index] == handle) + if (sounds[i].get()->handle[index].handle == handle) { return sounds[i].get(); } @@ -712,7 +798,7 @@ void Player::debug() { printf("%d: \thandle: ", n); for (auto &handle : sound.get()->handle) - printf("%d ", handle); + printf("%d ", handle.handle); printf(" %s\n", sound.get()->completeFileName.c_str()); n++; @@ -723,24 +809,29 @@ void Player::debug() /// voice groups ///////////////////////////////////////// -unsigned int Player::createVoiceGroup() { +unsigned int Player::createVoiceGroup() +{ auto ret = soloud.createVoiceGroup(); return ret; } -void Player::destroyVoiceGroup(SoLoud::handle handle) { +void Player::destroyVoiceGroup(SoLoud::handle handle) +{ soloud.destroyVoiceGroup(handle); } -void Player::addVoiceToGroup(SoLoud::handle voiceGroupHandle, SoLoud::handle voiceHandle) { +void Player::addVoiceToGroup(SoLoud::handle voiceGroupHandle, SoLoud::handle voiceHandle) +{ soloud.addVoiceToGroup(voiceGroupHandle, voiceHandle); } -bool Player::isVoiceGroup(SoLoud::handle handle) { +bool Player::isVoiceGroup(SoLoud::handle handle) +{ return soloud.isVoiceGroup(handle); } -bool Player::isVoiceGroupEmpty(SoLoud::handle handle) { +bool Player::isVoiceGroupEmpty(SoLoud::handle handle) +{ return soloud.isVoiceGroupEmpty(handle); } @@ -833,7 +924,7 @@ unsigned int Player::play3d( paused, bus); if (newHandle != 0) - sound->handle.emplace_back(newHandle); + sound->handle.push_back({newHandle, MAX_DOUBLE}); if (looping) { seek(newHandle, loopingStartAt); diff --git a/src/player.h b/src/player.h index 80d35a8..c730f2f 100644 --- a/src/player.h +++ b/src/player.h @@ -8,6 +8,7 @@ #include "enums.h" #include "filters/filters.h" #include "active_sound.h" +#include "audiobuffer/audiobuffer.h" #include "soloud/src/backend/miniaudio/miniaudio.h" #include @@ -18,7 +19,6 @@ #include #include - struct PlaybackDevice { char *name; @@ -100,6 +100,38 @@ class Player bool loadIntoMem, unsigned int &hash); + /// @brief Set up an audio stream. + /// @param hash return the hash of the sound. + /// @param maxBufferSize the max buffer size in bytes. + /// @param isPCM if true, the audio data is PCM. + /// @param dataType in case the audio data is PCM, here are the parameters to set it up. + PlayerErrors setBufferStream( + unsigned int &hash, + unsigned long maxBufferSize, + SoLoud::time bufferingTimeNeeds, + PCMformat pcmFormat = {44100, 2, 4, PCM_F32LE}, + dartOnBufferingCallback_t onBufferingCallback = nullptr); + + /// @brief Add an audio data stream. + /// @param hash the hash of the sound. + /// @param data the audio data to add. + /// @param aDataLen the length of [data]. + PlayerErrors addAudioDataStream( + unsigned int hash, + const unsigned char *data, + unsigned int aDataLen); + + /// @brief Set the end of the data stream. + /// @param hash the hash of the sound. + /// @return Returns [PlayerErrors.SO_NO_ERROR] if success. + PlayerErrors setDataIsEnded(unsigned int hash); + + /// @brief Get the current buffer size in bytes of this sound with hash [hash]. + /// @param hash the hash of the stream sound. + /// @param sizeInBytes return the size in bytes. + /// @return Returns [PlayerErrors.SO_NO_ERROR] if success. + PlayerErrors getBufferSize(unsigned int hash, unsigned int *sizeInBytes); + /// @brief Load a new sound which will be generated by the given params. /// @param waveform the type of [SoLoud::Soloud::WAVEFORM] to generate. /// @param superWave whater this is a superWave. diff --git a/web/compile_wasm.sh b/web/compile_wasm.sh index 7e4ada3..c9f25b2 100755 --- a/web/compile_wasm.sh +++ b/web/compile_wasm.sh @@ -46,9 +46,10 @@ em++ \ ../../src/bindings.cpp \ ../../src/player.cpp \ ../../src/analyzer.cpp \ -../../src/synth/basic_wave.cpp \ +../../src/synth/*.cpp \ ../../src/filters/*.cpp \ ../../src/waveform/*.cpp \ +../../src/audiobuffer/*.cpp \ -O3 -D WITH_MINIAUDIO \ -msimd128 -msse3 \ -s "EXPORTED_RUNTIME_METHODS=['ccall','cwrap']" \ diff --git a/web/libflutter_soloud_plugin.js b/web/libflutter_soloud_plugin.js index 3a9ae25..fd0cbb4 100644 --- a/web/libflutter_soloud_plugin.js +++ b/web/libflutter_soloud_plugin.js @@ -1 +1 @@ -var Module=typeof Module!="undefined"?Module:{};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");scriptDirectory=__dirname+"/";read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}process.on("uncaughtException",ex=>{if(ex!=="unwind"&&!(ex instanceof ExitStatus)&&!(ex.context instanceof ExitStatus)){throw ex}});quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{if(isFileURI(url)){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null);return}fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))}).then(onload,onerror)}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];function getSafeHeapType(bytes,isFloat){switch(bytes){case 1:return"i8";case 2:return"i16";case 4:return isFloat?"float":"i32";case 8:return isFloat?"double":"i64";default:abort(`getSafeHeapType() invalid bytes=${bytes}`)}}function SAFE_HEAP_STORE(dest,value,bytes,isFloat){if(dest<=0)abort(`segmentation fault storing ${bytes} bytes to address ${dest}`);if(dest%bytes!==0)abort(`alignment error storing to address ${dest}, which was expected to be aligned to a multiple of ${bytes}`);if(runtimeInitialized){var brk=_sbrk(0);if(dest+bytes>brk)abort(`segmentation fault, exceeded the top of the available dynamic heap when storing ${bytes} bytes to address ${dest}. DYNAMICTOP=${brk}`);if(brk<_emscripten_stack_get_base())abort(`brk >= _emscripten_stack_get_base() (brk=${brk}, _emscripten_stack_get_base()=${_emscripten_stack_get_base()})`);if(brk>wasmMemory.buffer.byteLength)abort(`brk <= wasmMemory.buffer.byteLength (brk=${brk}, wasmMemory.buffer.byteLength=${wasmMemory.buffer.byteLength})`)}setValue_safe(dest,value,getSafeHeapType(bytes,isFloat));return value}function SAFE_HEAP_STORE_D(dest,value,bytes){return SAFE_HEAP_STORE(dest,value,bytes,true)}function SAFE_HEAP_LOAD(dest,bytes,unsigned,isFloat){if(dest<=0)abort(`segmentation fault loading ${bytes} bytes from address ${dest}`);if(dest%bytes!==0)abort(`alignment error loading from address ${dest}, which was expected to be aligned to a multiple of ${bytes}`);if(runtimeInitialized){var brk=_sbrk(0);if(dest+bytes>brk)abort(`segmentation fault, exceeded the top of the available dynamic heap when loading ${bytes} bytes from address ${dest}. DYNAMICTOP=${brk}`);if(brk<_emscripten_stack_get_base())abort(`brk >= _emscripten_stack_get_base() (brk=${brk}, _emscripten_stack_get_base()=${_emscripten_stack_get_base()})`);if(brk>wasmMemory.buffer.byteLength)abort(`brk <= wasmMemory.buffer.byteLength (brk=${brk}, wasmMemory.buffer.byteLength=${wasmMemory.buffer.byteLength})`)}var type=getSafeHeapType(bytes,isFloat);var ret=getValue_safe(dest,type);if(unsigned)ret=unSign(ret,parseInt(type.substr(1),10));return ret}function SAFE_HEAP_LOAD_D(dest,bytes,unsigned){return SAFE_HEAP_LOAD(dest,bytes,unsigned,true)}function segfault(){abort("segmentation fault")}function alignfault(){abort("alignment fault")}var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="libflutter_soloud_plugin.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return new Promise((resolve,reject)=>{readAsync(binaryFile,response=>resolve(new Uint8Array(response)),error=>{try{resolve(getBinarySync(binaryFile))}catch(e){reject(e)}})})}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["q"];updateMemoryViews();addOnInit(wasmExports["r"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);return false}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;var tempI64;var ASM_CONSTS={86768:($0,$1,$2,$3,$4)=>{if(typeof window==="undefined"||(window.AudioContext||window.webkitAudioContext)===undefined){return 0}if(typeof window.miniaudio==="undefined"){window.miniaudio={referenceCount:0};window.miniaudio.device_type={};window.miniaudio.device_type.playback=$0;window.miniaudio.device_type.capture=$1;window.miniaudio.device_type.duplex=$2;window.miniaudio.device_state={};window.miniaudio.device_state.stopped=$3;window.miniaudio.device_state.started=$4;let miniaudio=window.miniaudio;miniaudio.devices=[];miniaudio.track_device=function(device){for(var iDevice=0;iDevice0){if(miniaudio.devices[miniaudio.devices.length-1]==null){miniaudio.devices.pop()}else{break}}};miniaudio.untrack_device=function(device){for(var iDevice=0;iDevice{_ma_device__on_notification_unlocked(device.pDevice)},error=>{console.error("Failed to resume audiocontext",error)})}}miniaudio.unlock_event_types.map(function(event_type){document.removeEventListener(event_type,miniaudio.unlock,true)})};miniaudio.unlock_event_types.map(function(event_type){document.addEventListener(event_type,miniaudio.unlock,true)})}window.miniaudio.referenceCount+=1;return 1},88946:()=>{if(typeof window.miniaudio!=="undefined"){miniaudio.unlock_event_types.map(function(event_type){document.removeEventListener(event_type,miniaudio.unlock,true)});window.miniaudio.referenceCount-=1;if(window.miniaudio.referenceCount===0){delete window.miniaudio}}},89236:()=>navigator.mediaDevices!==undefined&&navigator.mediaDevices.getUserMedia!==undefined,89340:()=>{try{var temp=new(window.AudioContext||window.webkitAudioContext);var sampleRate=temp.sampleRate;temp.close();return sampleRate}catch(e){return 0}},89511:($0,$1,$2,$3,$4,$5)=>{var deviceType=$0;var channels=$1;var sampleRate=$2;var bufferSize=$3;var pIntermediaryBuffer=$4;var pDevice=$5;if(typeof window.miniaudio==="undefined"){return-1}var device={};var audioContextOptions={};if(deviceType==window.miniaudio.device_type.playback&&sampleRate!=0){audioContextOptions.sampleRate=sampleRate}device.webaudio=new(window.AudioContext||window.webkitAudioContext)(audioContextOptions);device.webaudio.suspend();device.state=window.miniaudio.device_state.stopped;var channelCountIn=0;var channelCountOut=channels;if(deviceType!=window.miniaudio.device_type.playback){channelCountIn=channels}device.scriptNode=device.webaudio.createScriptProcessor(bufferSize,channelCountIn,channelCountOut);device.scriptNode.onaudioprocess=function(e){if(device.intermediaryBufferView==null||device.intermediaryBufferView.length==0){device.intermediaryBufferView=new Float32Array(HEAPF32.buffer,pIntermediaryBuffer,bufferSize*channels)}if(deviceType==window.miniaudio.device_type.capture||deviceType==window.miniaudio.device_type.duplex){for(var iChannel=0;iChannelwindow.miniaudio.get_device_by_index($0).webaudio.sampleRate,92461:$0=>{var device=window.miniaudio.get_device_by_index($0);if(device.scriptNode!==undefined){device.scriptNode.onaudioprocess=function(e){};device.scriptNode.disconnect();device.scriptNode=undefined}if(device.streamNode!==undefined){device.streamNode.disconnect();device.streamNode=undefined}device.webaudio.close();device.webaudio=undefined;device.pDevice=undefined},92861:$0=>{window.miniaudio.untrack_device_by_index($0)},92911:$0=>{var device=window.miniaudio.get_device_by_index($0);device.webaudio.resume();device.state=window.miniaudio.device_state.started},93050:$0=>{var device=window.miniaudio.get_device_by_index($0);device.webaudio.suspend();device.state=window.miniaudio.device_state.stopped},93190:()=>{if(!Module.wasmWorker){var workerUri="assets/packages/flutter_soloud/web/worker.dart.js";console.log("EM_ASM creating web worker!");Module.wasmWorker=new Worker(workerUri)}else{console.log("EM_ASM web worker already created!")}},93438:($0,$1)=>{if(Module.wasmWorker){console.log("EM_ASM posting message "+UTF8ToString($0)+" with value "+$1);Module.wasmWorker.postMessage(JSON.stringify({message:UTF8ToString($0),value:$1}))}else{console.error("Worker not found.")}}};function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}Module["ExitStatus"]=ExitStatus;var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};Module["callRuntimeCallbacks"]=callRuntimeCallbacks;function getValue(ptr,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":return SAFE_HEAP_LOAD(ptr,1,0);case"i8":return SAFE_HEAP_LOAD(ptr,1,0);case"i16":return SAFE_HEAP_LOAD((ptr>>1)*2,2,0);case"i32":return SAFE_HEAP_LOAD((ptr>>2)*4,4,0);case"i64":abort("to do getValue(i64) use WASM_BIGINT");case"float":return SAFE_HEAP_LOAD_D((ptr>>2)*4,4,0);case"double":return SAFE_HEAP_LOAD_D((ptr>>3)*8,8,0);case"*":return SAFE_HEAP_LOAD((ptr>>2)*4,4,1);default:abort(`invalid type for getValue: ${type}`)}}Module["getValue"]=getValue;function getValue_safe(ptr,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":return HEAP8[ptr];case"i8":return HEAP8[ptr];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":abort("to do getValue(i64) use WASM_BIGINT");case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];case"*":return HEAPU32[ptr>>2];default:abort(`invalid type for getValue: ${type}`)}}Module["getValue_safe"]=getValue_safe;var noExitRuntime=Module["noExitRuntime"]||true;Module["noExitRuntime"]=noExitRuntime;function setValue(ptr,value,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":SAFE_HEAP_STORE(ptr,value,1);break;case"i8":SAFE_HEAP_STORE(ptr,value,1);break;case"i16":SAFE_HEAP_STORE((ptr>>1)*2,value,2);break;case"i32":SAFE_HEAP_STORE((ptr>>2)*4,value,4);break;case"i64":abort("to do setValue(i64) use WASM_BIGINT");case"float":SAFE_HEAP_STORE_D((ptr>>2)*4,value,4);break;case"double":SAFE_HEAP_STORE_D((ptr>>3)*8,value,8);break;case"*":SAFE_HEAP_STORE((ptr>>2)*4,value,4);break;default:abort(`invalid type for setValue: ${type}`)}}Module["setValue"]=setValue;function setValue_safe(ptr,value,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":HEAP8[ptr]=value;break;case"i8":HEAP8[ptr]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":abort("to do setValue(i64) use WASM_BIGINT");case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;case"*":HEAPU32[ptr>>2]=value;break;default:abort(`invalid type for setValue: ${type}`)}}Module["setValue_safe"]=setValue_safe;var stackRestore=val=>__emscripten_stack_restore(val);Module["stackRestore"]=stackRestore;var stackSave=()=>_emscripten_stack_get_current();Module["stackSave"]=stackSave;var unSign=(value,bits)=>{if(value>=0){return value}return bits<=32?2*Math.abs(1<{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};Module["UTF8ArrayToString"]=UTF8ArrayToString;var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";Module["UTF8ToString"]=UTF8ToString;var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};Module["___assert_fail"]=___assert_fail;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){SAFE_HEAP_STORE((this.ptr+4>>2)*4,type,4)}get_type(){return SAFE_HEAP_LOAD((this.ptr+4>>2)*4,4,1)}set_destructor(destructor){SAFE_HEAP_STORE((this.ptr+8>>2)*4,destructor,4)}get_destructor(){return SAFE_HEAP_LOAD((this.ptr+8>>2)*4,4,1)}set_caught(caught){caught=caught?1:0;SAFE_HEAP_STORE(this.ptr+12,caught,1)}get_caught(){return SAFE_HEAP_LOAD(this.ptr+12,1,0)!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;SAFE_HEAP_STORE(this.ptr+13,rethrown,1)}get_rethrown(){return SAFE_HEAP_LOAD(this.ptr+13,1,0)!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){SAFE_HEAP_STORE((this.ptr+16>>2)*4,adjustedPtr,4)}get_adjusted_ptr(){return SAFE_HEAP_LOAD((this.ptr+16>>2)*4,4,1)}get_exception_ptr(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return SAFE_HEAP_LOAD((this.excPtr>>2)*4,4,1)}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}Module["ExceptionInfo"]=ExceptionInfo;var exceptionLast=0;Module["exceptionLast"]=exceptionLast;var uncaughtExceptionCount=0;Module["uncaughtExceptionCount"]=uncaughtExceptionCount;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};Module["___cxa_throw"]=___cxa_throw;function syscallGetVarargI(){var ret=SAFE_HEAP_LOAD((+SYSCALLS.varargs>>2)*4,4,0);SYSCALLS.varargs+=4;return ret}Module["syscallGetVarargI"]=syscallGetVarargI;var syscallGetVarargP=syscallGetVarargI;Module["syscallGetVarargP"]=syscallGetVarargP;var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};Module["PATH"]=PATH;var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("initRandomDevice")};Module["initRandomFill"]=initRandomFill;var randomFill=view=>(randomFill=initRandomFill())(view);Module["randomFill"]=randomFill;var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};Module["lengthBytesUTF8"]=lengthBytesUTF8;var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};Module["stringToUTF8Array"]=stringToUTF8Array;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};Module["FS_stdin_getChar"]=FS_stdin_getChar;var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};Module["TTY"]=TTY;var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size);return address};Module["zeroMemory"]=zeroMemory;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;Module["alignMemory"]=alignMemory;var mmapAlloc=size=>{abort()};Module["mmapAlloc"]=mmapAlloc;var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url,arrayBuffer=>{onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};Module["asyncLoad"]=asyncLoad;var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};Module["FS_createDataFile"]=FS_createDataFile;var preloadPlugins=Module["preloadPlugins"]||[];Module["preloadPlugins"]=preloadPlugins;var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};Module["FS_handledByPreloadPlugin"]=FS_handledByPreloadPlugin;var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,processData,onerror)}else{processData(url)}};Module["FS_createPreloadedFile"]=FS_createPreloadedFile;var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};Module["FS_modeStringToFlags"]=FS_modeStringToFlags;var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};Module["FS_getMode"]=FS_getMode;var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class{constructor(errno){this.name="ErrnoError";this.errno=errno}},genericErrors:{},filesystems:null,syncFSRequests:0,FSStream:class{constructor(){this.shared={}}get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev;this.readMode=292|73;this.writeMode=146}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;iFS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(){if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""});FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS:MEMFS}},init(input,output,error){FS.init.initialized=true;Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit(){FS.init.initialized=false;for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};Module["FS"]=FS;var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){var stat=func(path);SAFE_HEAP_STORE((buf>>2)*4,stat.dev,4);SAFE_HEAP_STORE((buf+4>>2)*4,stat.mode,4);SAFE_HEAP_STORE((buf+8>>2)*4,stat.nlink,4);SAFE_HEAP_STORE((buf+12>>2)*4,stat.uid,4);SAFE_HEAP_STORE((buf+16>>2)*4,stat.gid,4);SAFE_HEAP_STORE((buf+20>>2)*4,stat.rdev,4);tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+24>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+28>>2)*4,tempI64[1],4);SAFE_HEAP_STORE((buf+32>>2)*4,4096,4);SAFE_HEAP_STORE((buf+36>>2)*4,stat.blocks,4);var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+40>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+44>>2)*4,tempI64[1],4);SAFE_HEAP_STORE((buf+48>>2)*4,atime%1e3*1e3,4);tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+56>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+60>>2)*4,tempI64[1],4);SAFE_HEAP_STORE((buf+64>>2)*4,mtime%1e3*1e3,4);tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+72>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+76>>2)*4,tempI64[1],4);SAFE_HEAP_STORE((buf+80>>2)*4,ctime%1e3*1e3,4);tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+88>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+92>>2)*4,tempI64[1],4);return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};Module["SYSCALLS"]=SYSCALLS;function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;SAFE_HEAP_STORE((arg+offset>>1)*2,2,2);return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}Module["___syscall_fcntl64"]=___syscall_fcntl64;function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();SAFE_HEAP_STORE((argp>>2)*4,termios.c_iflag||0,4);SAFE_HEAP_STORE((argp+4>>2)*4,termios.c_oflag||0,4);SAFE_HEAP_STORE((argp+8>>2)*4,termios.c_cflag||0,4);SAFE_HEAP_STORE((argp+12>>2)*4,termios.c_lflag||0,4);for(var i=0;i<32;i++){SAFE_HEAP_STORE(argp+i+17,termios.c_cc[i]||0,1)}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=SAFE_HEAP_LOAD((argp>>2)*4,4,0);var c_oflag=SAFE_HEAP_LOAD((argp+4>>2)*4,4,0);var c_cflag=SAFE_HEAP_LOAD((argp+8>>2)*4,4,0);var c_lflag=SAFE_HEAP_LOAD((argp+12>>2)*4,4,0);var c_cc=[];for(var i=0;i<32;i++){c_cc.push(SAFE_HEAP_LOAD(argp+i+17,1,0))}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag:c_iflag,c_oflag:c_oflag,c_cflag:c_cflag,c_lflag:c_lflag,c_cc:c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();SAFE_HEAP_STORE((argp>>2)*4,0,4);return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();SAFE_HEAP_STORE((argp>>1)*2,winsize[0],2);SAFE_HEAP_STORE((argp+2>>1)*2,winsize[1],2)}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}Module["___syscall_ioctl"]=___syscall_ioctl;function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}Module["___syscall_openat"]=___syscall_openat;var __abort_js=()=>{abort("")};Module["__abort_js"]=__abort_js;var __emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);Module["__emscripten_memcpy_js"]=__emscripten_memcpy_js;var readEmAsmArgsArray=[];Module["readEmAsmArgsArray"]=readEmAsmArgsArray;var readEmAsmArgs=(sigPtr,buf)=>{readEmAsmArgsArray.length=0;var ch;while(ch=SAFE_HEAP_LOAD(sigPtr++,1,1)){var wide=ch!=105;wide&=ch!=112;buf+=wide&&buf%8?4:0;readEmAsmArgsArray.push(ch==112?SAFE_HEAP_LOAD((buf>>2)*4,4,1):ch==105?SAFE_HEAP_LOAD((buf>>2)*4,4,0):SAFE_HEAP_LOAD_D((buf>>3)*8,8,0));buf+=wide?8:4}return readEmAsmArgsArray};Module["readEmAsmArgs"]=readEmAsmArgs;var runEmAsmFunction=(code,sigPtr,argbuf)=>{var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code](...args)};Module["runEmAsmFunction"]=runEmAsmFunction;var _emscripten_asm_const_int=(code,sigPtr,argbuf)=>runEmAsmFunction(code,sigPtr,argbuf);Module["_emscripten_asm_const_int"]=_emscripten_asm_const_int;var getHeapMax=()=>2147483648;Module["getHeapMax"]=getHeapMax;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};Module["growMemory"]=growMemory;var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};Module["_emscripten_resize_heap"]=_emscripten_resize_heap;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}Module["_fd_close"]=_fd_close;var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2)*4,4,1);var len=SAFE_HEAP_LOAD((iov+4>>2)*4,4,1);iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2)*4,num,4);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}Module["_fd_read"]=_fd_read;var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;Module["convertI32PairToI53Checked"]=convertI32PairToI53Checked;function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((newOffset>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((newOffset+4>>2)*4,tempI64[1],4);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}Module["_fd_seek"]=_fd_seek;var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2)*4,4,1);var len=SAFE_HEAP_LOAD((iov+4>>2)*4,4,1);iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!="undefined"){offset+=curr}}return ret};Module["doWritev"]=doWritev;function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);SAFE_HEAP_STORE((pnum>>2)*4,num,4);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}Module["_fd_write"]=_fd_write;var _getentropy=(buffer,size)=>{randomFill(HEAPU8.subarray(buffer,buffer+size));return 0};Module["_getentropy"]=_getentropy;var getCFunc=ident=>{var func=Module["_"+ident];return func};Module["getCFunc"]=getCFunc;var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};Module["writeArrayToMemory"]=writeArrayToMemory;var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);Module["stringToUTF8"]=stringToUTF8;var stackAlloc=sz=>__emscripten_stack_alloc(sz);Module["stackAlloc"]=stackAlloc;var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};Module["stringToUTF8OnStack"]=stringToUTF8OnStack;var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};Module["cwrap"]=cwrap;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();var wasmImports={a:___assert_fail,h:___cxa_throw,g:___syscall_fcntl64,j:___syscall_ioctl,k:___syscall_openat,o:__abort_js,l:__emscripten_memcpy_js,c:alignfault,d:_emscripten_asm_const_int,p:_emscripten_resize_heap,e:_fd_close,i:_fd_read,m:_fd_seek,f:_fd_write,n:_getentropy,b:segfault};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["r"])();var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["t"])(a0);var _free=Module["_free"]=a0=>(_free=Module["_free"]=wasmExports["u"])(a0);var _ma_device__on_notification_unlocked=Module["_ma_device__on_notification_unlocked"]=a0=>(_ma_device__on_notification_unlocked=Module["_ma_device__on_notification_unlocked"]=wasmExports["v"])(a0);var _ma_malloc_emscripten=Module["_ma_malloc_emscripten"]=(a0,a1)=>(_ma_malloc_emscripten=Module["_ma_malloc_emscripten"]=wasmExports["w"])(a0,a1);var _ma_free_emscripten=Module["_ma_free_emscripten"]=(a0,a1)=>(_ma_free_emscripten=Module["_ma_free_emscripten"]=wasmExports["x"])(a0,a1);var _ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=(a0,a1,a2)=>(_ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=wasmExports["y"])(a0,a1,a2);var _ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=(a0,a1,a2)=>(_ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=wasmExports["z"])(a0,a1,a2);var _createWorkerInWasm=Module["_createWorkerInWasm"]=()=>(_createWorkerInWasm=Module["_createWorkerInWasm"]=wasmExports["A"])();var _sendToWorker=Module["_sendToWorker"]=(a0,a1)=>(_sendToWorker=Module["_sendToWorker"]=wasmExports["B"])(a0,a1);var _nativeFree=Module["_nativeFree"]=a0=>(_nativeFree=Module["_nativeFree"]=wasmExports["C"])(a0);var _voiceEndedCallback=Module["_voiceEndedCallback"]=a0=>(_voiceEndedCallback=Module["_voiceEndedCallback"]=wasmExports["D"])(a0);var _setDartEventCallback=Module["_setDartEventCallback"]=(a0,a1,a2)=>(_setDartEventCallback=Module["_setDartEventCallback"]=wasmExports["E"])(a0,a1,a2);var _initEngine=Module["_initEngine"]=(a0,a1,a2,a3)=>(_initEngine=Module["_initEngine"]=wasmExports["F"])(a0,a1,a2,a3);var _changeDevice=Module["_changeDevice"]=a0=>(_changeDevice=Module["_changeDevice"]=wasmExports["G"])(a0);var _listPlaybackDevices=Module["_listPlaybackDevices"]=(a0,a1,a2,a3)=>(_listPlaybackDevices=Module["_listPlaybackDevices"]=wasmExports["H"])(a0,a1,a2,a3);var _freeListPlaybackDevices=Module["_freeListPlaybackDevices"]=(a0,a1,a2,a3)=>(_freeListPlaybackDevices=Module["_freeListPlaybackDevices"]=wasmExports["I"])(a0,a1,a2,a3);var _dispose=Module["_dispose"]=()=>(_dispose=Module["_dispose"]=wasmExports["J"])();var _isInited=Module["_isInited"]=()=>(_isInited=Module["_isInited"]=wasmExports["K"])();var _loadFile=Module["_loadFile"]=(a0,a1)=>(_loadFile=Module["_loadFile"]=wasmExports["L"])(a0,a1);var _loadMem=Module["_loadMem"]=(a0,a1,a2,a3,a4)=>(_loadMem=Module["_loadMem"]=wasmExports["M"])(a0,a1,a2,a3,a4);var _loadWaveform=Module["_loadWaveform"]=(a0,a1,a2,a3,a4)=>(_loadWaveform=Module["_loadWaveform"]=wasmExports["N"])(a0,a1,a2,a3,a4);var _setWaveformScale=Module["_setWaveformScale"]=(a0,a1)=>(_setWaveformScale=Module["_setWaveformScale"]=wasmExports["O"])(a0,a1);var _setWaveformDetune=Module["_setWaveformDetune"]=(a0,a1)=>(_setWaveformDetune=Module["_setWaveformDetune"]=wasmExports["P"])(a0,a1);var _setWaveformFreq=Module["_setWaveformFreq"]=(a0,a1)=>(_setWaveformFreq=Module["_setWaveformFreq"]=wasmExports["Q"])(a0,a1);var _setSuperWave=Module["_setSuperWave"]=(a0,a1)=>(_setSuperWave=Module["_setSuperWave"]=wasmExports["R"])(a0,a1);var _setWaveform=Module["_setWaveform"]=(a0,a1)=>(_setWaveform=Module["_setWaveform"]=wasmExports["S"])(a0,a1);var _speechText=Module["_speechText"]=(a0,a1)=>(_speechText=Module["_speechText"]=wasmExports["T"])(a0,a1);var _pauseSwitch=Module["_pauseSwitch"]=a0=>(_pauseSwitch=Module["_pauseSwitch"]=wasmExports["U"])(a0);var _setPause=Module["_setPause"]=(a0,a1)=>(_setPause=Module["_setPause"]=wasmExports["V"])(a0,a1);var _getPause=Module["_getPause"]=a0=>(_getPause=Module["_getPause"]=wasmExports["W"])(a0);var _setRelativePlaySpeed=Module["_setRelativePlaySpeed"]=(a0,a1)=>(_setRelativePlaySpeed=Module["_setRelativePlaySpeed"]=wasmExports["X"])(a0,a1);var _getRelativePlaySpeed=Module["_getRelativePlaySpeed"]=a0=>(_getRelativePlaySpeed=Module["_getRelativePlaySpeed"]=wasmExports["Y"])(a0);var _play=Module["_play"]=(a0,a1,a2,a3,a4,a5,a6)=>(_play=Module["_play"]=wasmExports["Z"])(a0,a1,a2,a3,a4,a5,a6);var _stop=Module["_stop"]=a0=>(_stop=Module["_stop"]=wasmExports["_"])(a0);var _disposeSound=Module["_disposeSound"]=a0=>(_disposeSound=Module["_disposeSound"]=wasmExports["$"])(a0);var _disposeAllSound=Module["_disposeAllSound"]=()=>(_disposeAllSound=Module["_disposeAllSound"]=wasmExports["aa"])();var _getLooping=Module["_getLooping"]=a0=>(_getLooping=Module["_getLooping"]=wasmExports["ba"])(a0);var _setLooping=Module["_setLooping"]=(a0,a1)=>(_setLooping=Module["_setLooping"]=wasmExports["ca"])(a0,a1);var _getLoopPoint=Module["_getLoopPoint"]=a0=>(_getLoopPoint=Module["_getLoopPoint"]=wasmExports["da"])(a0);var _setLoopPoint=Module["_setLoopPoint"]=(a0,a1)=>(_setLoopPoint=Module["_setLoopPoint"]=wasmExports["ea"])(a0,a1);var _setVisualizationEnabled=Module["_setVisualizationEnabled"]=a0=>(_setVisualizationEnabled=Module["_setVisualizationEnabled"]=wasmExports["fa"])(a0);var _getVisualizationEnabled=Module["_getVisualizationEnabled"]=()=>(_getVisualizationEnabled=Module["_getVisualizationEnabled"]=wasmExports["ga"])();var _getFft=Module["_getFft"]=a0=>(_getFft=Module["_getFft"]=wasmExports["ha"])(a0);var _getWave=Module["_getWave"]=a0=>(_getWave=Module["_getWave"]=wasmExports["ia"])(a0);var _setFftSmoothing=Module["_setFftSmoothing"]=a0=>(_setFftSmoothing=Module["_setFftSmoothing"]=wasmExports["ja"])(a0);var _getAudioTexture=Module["_getAudioTexture"]=a0=>(_getAudioTexture=Module["_getAudioTexture"]=wasmExports["ka"])(a0);var _getAudioTexture2D=Module["_getAudioTexture2D"]=a0=>(_getAudioTexture2D=Module["_getAudioTexture2D"]=wasmExports["la"])(a0);var _getTextureValue=Module["_getTextureValue"]=(a0,a1)=>(_getTextureValue=Module["_getTextureValue"]=wasmExports["ma"])(a0,a1);var _getLength=Module["_getLength"]=a0=>(_getLength=Module["_getLength"]=wasmExports["na"])(a0);var _seek=Module["_seek"]=(a0,a1)=>(_seek=Module["_seek"]=wasmExports["oa"])(a0,a1);var _getPosition=Module["_getPosition"]=a0=>(_getPosition=Module["_getPosition"]=wasmExports["pa"])(a0);var _getGlobalVolume=Module["_getGlobalVolume"]=()=>(_getGlobalVolume=Module["_getGlobalVolume"]=wasmExports["qa"])();var _setGlobalVolume=Module["_setGlobalVolume"]=a0=>(_setGlobalVolume=Module["_setGlobalVolume"]=wasmExports["ra"])(a0);var _getVolume=Module["_getVolume"]=a0=>(_getVolume=Module["_getVolume"]=wasmExports["sa"])(a0);var _setVolume=Module["_setVolume"]=(a0,a1)=>(_setVolume=Module["_setVolume"]=wasmExports["ta"])(a0,a1);var _getPan=Module["_getPan"]=a0=>(_getPan=Module["_getPan"]=wasmExports["ua"])(a0);var _setPan=Module["_setPan"]=(a0,a1)=>(_setPan=Module["_setPan"]=wasmExports["va"])(a0,a1);var _setPanAbsolute=Module["_setPanAbsolute"]=(a0,a1,a2)=>(_setPanAbsolute=Module["_setPanAbsolute"]=wasmExports["wa"])(a0,a1,a2);var _getIsValidVoiceHandle=Module["_getIsValidVoiceHandle"]=a0=>(_getIsValidVoiceHandle=Module["_getIsValidVoiceHandle"]=wasmExports["xa"])(a0);var _getActiveVoiceCount=Module["_getActiveVoiceCount"]=()=>(_getActiveVoiceCount=Module["_getActiveVoiceCount"]=wasmExports["ya"])();var _countAudioSource=Module["_countAudioSource"]=a0=>(_countAudioSource=Module["_countAudioSource"]=wasmExports["za"])(a0);var _getVoiceCount=Module["_getVoiceCount"]=()=>(_getVoiceCount=Module["_getVoiceCount"]=wasmExports["Aa"])();var _getProtectVoice=Module["_getProtectVoice"]=a0=>(_getProtectVoice=Module["_getProtectVoice"]=wasmExports["Ba"])(a0);var _setProtectVoice=Module["_setProtectVoice"]=(a0,a1)=>(_setProtectVoice=Module["_setProtectVoice"]=wasmExports["Ca"])(a0,a1);var _getMaxActiveVoiceCount=Module["_getMaxActiveVoiceCount"]=()=>(_getMaxActiveVoiceCount=Module["_getMaxActiveVoiceCount"]=wasmExports["Da"])();var _setMaxActiveVoiceCount=Module["_setMaxActiveVoiceCount"]=a0=>(_setMaxActiveVoiceCount=Module["_setMaxActiveVoiceCount"]=wasmExports["Ea"])(a0);var _createVoiceGroup=Module["_createVoiceGroup"]=()=>(_createVoiceGroup=Module["_createVoiceGroup"]=wasmExports["Fa"])();var _destroyVoiceGroup=Module["_destroyVoiceGroup"]=a0=>(_destroyVoiceGroup=Module["_destroyVoiceGroup"]=wasmExports["Ga"])(a0);var _addVoiceToGroup=Module["_addVoiceToGroup"]=(a0,a1)=>(_addVoiceToGroup=Module["_addVoiceToGroup"]=wasmExports["Ha"])(a0,a1);var _isVoiceGroup=Module["_isVoiceGroup"]=a0=>(_isVoiceGroup=Module["_isVoiceGroup"]=wasmExports["Ia"])(a0);var _isVoiceGroupEmpty=Module["_isVoiceGroupEmpty"]=a0=>(_isVoiceGroupEmpty=Module["_isVoiceGroupEmpty"]=wasmExports["Ja"])(a0);var _fadeGlobalVolume=Module["_fadeGlobalVolume"]=(a0,a1)=>(_fadeGlobalVolume=Module["_fadeGlobalVolume"]=wasmExports["Ka"])(a0,a1);var _fadeVolume=Module["_fadeVolume"]=(a0,a1,a2)=>(_fadeVolume=Module["_fadeVolume"]=wasmExports["La"])(a0,a1,a2);var _fadePan=Module["_fadePan"]=(a0,a1,a2)=>(_fadePan=Module["_fadePan"]=wasmExports["Ma"])(a0,a1,a2);var _fadeRelativePlaySpeed=Module["_fadeRelativePlaySpeed"]=(a0,a1,a2)=>(_fadeRelativePlaySpeed=Module["_fadeRelativePlaySpeed"]=wasmExports["Na"])(a0,a1,a2);var _schedulePause=Module["_schedulePause"]=(a0,a1)=>(_schedulePause=Module["_schedulePause"]=wasmExports["Oa"])(a0,a1);var _scheduleStop=Module["_scheduleStop"]=(a0,a1)=>(_scheduleStop=Module["_scheduleStop"]=wasmExports["Pa"])(a0,a1);var _oscillateVolume=Module["_oscillateVolume"]=(a0,a1,a2,a3)=>(_oscillateVolume=Module["_oscillateVolume"]=wasmExports["Qa"])(a0,a1,a2,a3);var _oscillatePan=Module["_oscillatePan"]=(a0,a1,a2,a3)=>(_oscillatePan=Module["_oscillatePan"]=wasmExports["Ra"])(a0,a1,a2,a3);var _oscillateRelativePlaySpeed=Module["_oscillateRelativePlaySpeed"]=(a0,a1,a2,a3)=>(_oscillateRelativePlaySpeed=Module["_oscillateRelativePlaySpeed"]=wasmExports["Sa"])(a0,a1,a2,a3);var _oscillateGlobalVolume=Module["_oscillateGlobalVolume"]=(a0,a1,a2)=>(_oscillateGlobalVolume=Module["_oscillateGlobalVolume"]=wasmExports["Ta"])(a0,a1,a2);var _isFilterActive=Module["_isFilterActive"]=(a0,a1,a2)=>(_isFilterActive=Module["_isFilterActive"]=wasmExports["Ua"])(a0,a1,a2);var _getFilterParamNames=Module["_getFilterParamNames"]=(a0,a1,a2)=>(_getFilterParamNames=Module["_getFilterParamNames"]=wasmExports["Va"])(a0,a1,a2);var _addFilter=Module["_addFilter"]=(a0,a1)=>(_addFilter=Module["_addFilter"]=wasmExports["Wa"])(a0,a1);var _removeFilter=Module["_removeFilter"]=(a0,a1)=>(_removeFilter=Module["_removeFilter"]=wasmExports["Xa"])(a0,a1);var _setFilterParams=Module["_setFilterParams"]=(a0,a1,a2,a3)=>(_setFilterParams=Module["_setFilterParams"]=wasmExports["Ya"])(a0,a1,a2,a3);var _getFilterParams=Module["_getFilterParams"]=(a0,a1,a2,a3)=>(_getFilterParams=Module["_getFilterParams"]=wasmExports["Za"])(a0,a1,a2,a3);var _fadeFilterParameter=Module["_fadeFilterParameter"]=(a0,a1,a2,a3,a4)=>(_fadeFilterParameter=Module["_fadeFilterParameter"]=wasmExports["_a"])(a0,a1,a2,a3,a4);var _oscillateFilterParameter=Module["_oscillateFilterParameter"]=(a0,a1,a2,a3,a4,a5)=>(_oscillateFilterParameter=Module["_oscillateFilterParameter"]=wasmExports["$a"])(a0,a1,a2,a3,a4,a5);var _play3d=Module["_play3d"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)=>(_play3d=Module["_play3d"]=wasmExports["ab"])(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11);var _set3dSoundSpeed=Module["_set3dSoundSpeed"]=a0=>(_set3dSoundSpeed=Module["_set3dSoundSpeed"]=wasmExports["bb"])(a0);var _get3dSoundSpeed=Module["_get3dSoundSpeed"]=()=>(_get3dSoundSpeed=Module["_get3dSoundSpeed"]=wasmExports["cb"])();var _set3dListenerParameters=Module["_set3dListenerParameters"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)=>(_set3dListenerParameters=Module["_set3dListenerParameters"]=wasmExports["db"])(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11);var _set3dListenerPosition=Module["_set3dListenerPosition"]=(a0,a1,a2)=>(_set3dListenerPosition=Module["_set3dListenerPosition"]=wasmExports["eb"])(a0,a1,a2);var _set3dListenerAt=Module["_set3dListenerAt"]=(a0,a1,a2)=>(_set3dListenerAt=Module["_set3dListenerAt"]=wasmExports["fb"])(a0,a1,a2);var _set3dListenerUp=Module["_set3dListenerUp"]=(a0,a1,a2)=>(_set3dListenerUp=Module["_set3dListenerUp"]=wasmExports["gb"])(a0,a1,a2);var _set3dListenerVelocity=Module["_set3dListenerVelocity"]=(a0,a1,a2)=>(_set3dListenerVelocity=Module["_set3dListenerVelocity"]=wasmExports["hb"])(a0,a1,a2);var _set3dSourceParameters=Module["_set3dSourceParameters"]=(a0,a1,a2,a3,a4,a5,a6)=>(_set3dSourceParameters=Module["_set3dSourceParameters"]=wasmExports["ib"])(a0,a1,a2,a3,a4,a5,a6);var _set3dSourcePosition=Module["_set3dSourcePosition"]=(a0,a1,a2,a3)=>(_set3dSourcePosition=Module["_set3dSourcePosition"]=wasmExports["jb"])(a0,a1,a2,a3);var _set3dSourceVelocity=Module["_set3dSourceVelocity"]=(a0,a1,a2,a3)=>(_set3dSourceVelocity=Module["_set3dSourceVelocity"]=wasmExports["kb"])(a0,a1,a2,a3);var _set3dSourceMinMaxDistance=Module["_set3dSourceMinMaxDistance"]=(a0,a1,a2)=>(_set3dSourceMinMaxDistance=Module["_set3dSourceMinMaxDistance"]=wasmExports["lb"])(a0,a1,a2);var _set3dSourceAttenuation=Module["_set3dSourceAttenuation"]=(a0,a1,a2)=>(_set3dSourceAttenuation=Module["_set3dSourceAttenuation"]=wasmExports["mb"])(a0,a1,a2);var _set3dSourceDopplerFactor=Module["_set3dSourceDopplerFactor"]=(a0,a1)=>(_set3dSourceDopplerFactor=Module["_set3dSourceDopplerFactor"]=wasmExports["nb"])(a0,a1);var _readSamplesFromFile=Module["_readSamplesFromFile"]=(a0,a1,a2,a3,a4,a5)=>(_readSamplesFromFile=Module["_readSamplesFromFile"]=wasmExports["ob"])(a0,a1,a2,a3,a4,a5);var _readSamplesFromMem=Module["_readSamplesFromMem"]=(a0,a1,a2,a3,a4,a5,a6)=>(_readSamplesFromMem=Module["_readSamplesFromMem"]=wasmExports["pb"])(a0,a1,a2,a3,a4,a5,a6);var _emscripten_get_sbrk_ptr=()=>(_emscripten_get_sbrk_ptr=wasmExports["qb"])();var _sbrk=a0=>(_sbrk=wasmExports["rb"])(a0);var _emscripten_stack_get_base=()=>(_emscripten_stack_get_base=wasmExports["sb"])();var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["tb"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["ub"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["vb"])();var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["wb"])(a0);var dynCall_iiji=Module["dynCall_iiji"]=(a0,a1,a2,a3,a4)=>(dynCall_iiji=Module["dynCall_iiji"]=wasmExports["xb"])(a0,a1,a2,a3,a4);var dynCall_iiiji=Module["dynCall_iiiji"]=(a0,a1,a2,a3,a4,a5)=>(dynCall_iiiji=Module["dynCall_iiiji"]=wasmExports["yb"])(a0,a1,a2,a3,a4,a5);var dynCall_jii=Module["dynCall_jii"]=(a0,a1,a2)=>(dynCall_jii=Module["dynCall_jii"]=wasmExports["zb"])(a0,a1,a2);var dynCall_iij=Module["dynCall_iij"]=(a0,a1,a2,a3)=>(dynCall_iij=Module["dynCall_iij"]=wasmExports["Ab"])(a0,a1,a2,a3);var dynCall_jiji=Module["dynCall_jiji"]=(a0,a1,a2,a3,a4)=>(dynCall_jiji=Module["dynCall_jiji"]=wasmExports["Bb"])(a0,a1,a2,a3,a4);Module["ccall"]=ccall;Module["cwrap"]=cwrap;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); +var Module=typeof Module!="undefined"?Module:{};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");scriptDirectory=__dirname+"/";read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}process.on("uncaughtException",ex=>{if(ex!=="unwind"&&!(ex instanceof ExitStatus)&&!(ex.context instanceof ExitStatus)){throw ex}});quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{if(isFileURI(url)){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null);return}fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))}).then(onload,onerror)}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];function getSafeHeapType(bytes,isFloat){switch(bytes){case 1:return"i8";case 2:return"i16";case 4:return isFloat?"float":"i32";case 8:return isFloat?"double":"i64";default:abort(`getSafeHeapType() invalid bytes=${bytes}`)}}function SAFE_HEAP_STORE(dest,value,bytes,isFloat){if(dest<=0)abort(`segmentation fault storing ${bytes} bytes to address ${dest}`);if(dest%bytes!==0)abort(`alignment error storing to address ${dest}, which was expected to be aligned to a multiple of ${bytes}`);if(runtimeInitialized){var brk=_sbrk(0);if(dest+bytes>brk)abort(`segmentation fault, exceeded the top of the available dynamic heap when storing ${bytes} bytes to address ${dest}. DYNAMICTOP=${brk}`);if(brk<_emscripten_stack_get_base())abort(`brk >= _emscripten_stack_get_base() (brk=${brk}, _emscripten_stack_get_base()=${_emscripten_stack_get_base()})`);if(brk>wasmMemory.buffer.byteLength)abort(`brk <= wasmMemory.buffer.byteLength (brk=${brk}, wasmMemory.buffer.byteLength=${wasmMemory.buffer.byteLength})`)}setValue_safe(dest,value,getSafeHeapType(bytes,isFloat));return value}function SAFE_HEAP_STORE_D(dest,value,bytes){return SAFE_HEAP_STORE(dest,value,bytes,true)}function SAFE_HEAP_LOAD(dest,bytes,unsigned,isFloat){if(dest<=0)abort(`segmentation fault loading ${bytes} bytes from address ${dest}`);if(dest%bytes!==0)abort(`alignment error loading from address ${dest}, which was expected to be aligned to a multiple of ${bytes}`);if(runtimeInitialized){var brk=_sbrk(0);if(dest+bytes>brk)abort(`segmentation fault, exceeded the top of the available dynamic heap when loading ${bytes} bytes from address ${dest}. DYNAMICTOP=${brk}`);if(brk<_emscripten_stack_get_base())abort(`brk >= _emscripten_stack_get_base() (brk=${brk}, _emscripten_stack_get_base()=${_emscripten_stack_get_base()})`);if(brk>wasmMemory.buffer.byteLength)abort(`brk <= wasmMemory.buffer.byteLength (brk=${brk}, wasmMemory.buffer.byteLength=${wasmMemory.buffer.byteLength})`)}var type=getSafeHeapType(bytes,isFloat);var ret=getValue_safe(dest,type);if(unsigned)ret=unSign(ret,parseInt(type.substr(1),10));return ret}function SAFE_HEAP_LOAD_D(dest,bytes,unsigned){return SAFE_HEAP_LOAD(dest,bytes,unsigned,true)}function segfault(){abort("segmentation fault")}function alignfault(){abort("alignment fault")}var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="libflutter_soloud_plugin.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return new Promise((resolve,reject)=>{readAsync(binaryFile,response=>resolve(new Uint8Array(response)),error=>{try{resolve(getBinarySync(binaryFile))}catch(e){reject(e)}})})}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["q"];updateMemoryViews();addOnInit(wasmExports["r"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);return false}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;var tempI64;var ASM_CONSTS={86912:($0,$1,$2,$3,$4)=>{if(typeof window==="undefined"||(window.AudioContext||window.webkitAudioContext)===undefined){return 0}if(typeof window.miniaudio==="undefined"){window.miniaudio={referenceCount:0};window.miniaudio.device_type={};window.miniaudio.device_type.playback=$0;window.miniaudio.device_type.capture=$1;window.miniaudio.device_type.duplex=$2;window.miniaudio.device_state={};window.miniaudio.device_state.stopped=$3;window.miniaudio.device_state.started=$4;let miniaudio=window.miniaudio;miniaudio.devices=[];miniaudio.track_device=function(device){for(var iDevice=0;iDevice0){if(miniaudio.devices[miniaudio.devices.length-1]==null){miniaudio.devices.pop()}else{break}}};miniaudio.untrack_device=function(device){for(var iDevice=0;iDevice{_ma_device__on_notification_unlocked(device.pDevice)},error=>{console.error("Failed to resume audiocontext",error)})}}miniaudio.unlock_event_types.map(function(event_type){document.removeEventListener(event_type,miniaudio.unlock,true)})};miniaudio.unlock_event_types.map(function(event_type){document.addEventListener(event_type,miniaudio.unlock,true)})}window.miniaudio.referenceCount+=1;return 1},89090:()=>{if(typeof window.miniaudio!=="undefined"){miniaudio.unlock_event_types.map(function(event_type){document.removeEventListener(event_type,miniaudio.unlock,true)});window.miniaudio.referenceCount-=1;if(window.miniaudio.referenceCount===0){delete window.miniaudio}}},89380:()=>navigator.mediaDevices!==undefined&&navigator.mediaDevices.getUserMedia!==undefined,89484:()=>{try{var temp=new(window.AudioContext||window.webkitAudioContext);var sampleRate=temp.sampleRate;temp.close();return sampleRate}catch(e){return 0}},89655:($0,$1,$2,$3,$4,$5)=>{var deviceType=$0;var channels=$1;var sampleRate=$2;var bufferSize=$3;var pIntermediaryBuffer=$4;var pDevice=$5;if(typeof window.miniaudio==="undefined"){return-1}var device={};var audioContextOptions={};if(deviceType==window.miniaudio.device_type.playback&&sampleRate!=0){audioContextOptions.sampleRate=sampleRate}device.webaudio=new(window.AudioContext||window.webkitAudioContext)(audioContextOptions);device.webaudio.suspend();device.state=window.miniaudio.device_state.stopped;var channelCountIn=0;var channelCountOut=channels;if(deviceType!=window.miniaudio.device_type.playback){channelCountIn=channels}device.scriptNode=device.webaudio.createScriptProcessor(bufferSize,channelCountIn,channelCountOut);device.scriptNode.onaudioprocess=function(e){if(device.intermediaryBufferView==null||device.intermediaryBufferView.length==0){device.intermediaryBufferView=new Float32Array(HEAPF32.buffer,pIntermediaryBuffer,bufferSize*channels)}if(deviceType==window.miniaudio.device_type.capture||deviceType==window.miniaudio.device_type.duplex){for(var iChannel=0;iChannelwindow.miniaudio.get_device_by_index($0).webaudio.sampleRate,92605:$0=>{var device=window.miniaudio.get_device_by_index($0);if(device.scriptNode!==undefined){device.scriptNode.onaudioprocess=function(e){};device.scriptNode.disconnect();device.scriptNode=undefined}if(device.streamNode!==undefined){device.streamNode.disconnect();device.streamNode=undefined}device.webaudio.close();device.webaudio=undefined;device.pDevice=undefined},93005:$0=>{window.miniaudio.untrack_device_by_index($0)},93055:$0=>{var device=window.miniaudio.get_device_by_index($0);device.webaudio.resume();device.state=window.miniaudio.device_state.started},93194:$0=>{var device=window.miniaudio.get_device_by_index($0);device.webaudio.suspend();device.state=window.miniaudio.device_state.stopped},93334:()=>{if(!Module.wasmWorker){var workerUri="assets/packages/flutter_soloud/web/worker.dart.js";console.log("EM_ASM creating web worker!");Module.wasmWorker=new Worker(workerUri)}else{console.log("EM_ASM web worker already created!")}},93582:($0,$1)=>{if(Module.wasmWorker){console.log("EM_ASM posting message "+UTF8ToString($0)+" with value "+$1);Module.wasmWorker.postMessage(JSON.stringify({message:UTF8ToString($0),value:$1}))}else{console.error("Worker not found.")}},93834:($0,$1,$2,$3)=>{var functionName="dartOnBufferingCallback_"+$3;if(typeof window[functionName]==="function"){var buffering=$0==1?true:false;window[functionName](buffering,$1,$2)}else{console.log("EM_ASM 'dartOnBufferingCallback_$hash' not found.")}},94098:($0,$1,$2,$3)=>{var functionName="dartOnBufferingCallback_"+$3;if(typeof window[functionName]==="function"){var buffering=$0==1?true:false;window[functionName](buffering,$1,$2)}else{console.log("EM_ASM 'dartOnBufferingCallback_$hash' not found.")}}};function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}Module["ExitStatus"]=ExitStatus;var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};Module["callRuntimeCallbacks"]=callRuntimeCallbacks;function getValue(ptr,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":return SAFE_HEAP_LOAD(ptr,1,0);case"i8":return SAFE_HEAP_LOAD(ptr,1,0);case"i16":return SAFE_HEAP_LOAD((ptr>>1)*2,2,0);case"i32":return SAFE_HEAP_LOAD((ptr>>2)*4,4,0);case"i64":abort("to do getValue(i64) use WASM_BIGINT");case"float":return SAFE_HEAP_LOAD_D((ptr>>2)*4,4,0);case"double":return SAFE_HEAP_LOAD_D((ptr>>3)*8,8,0);case"*":return SAFE_HEAP_LOAD((ptr>>2)*4,4,1);default:abort(`invalid type for getValue: ${type}`)}}Module["getValue"]=getValue;function getValue_safe(ptr,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":return HEAP8[ptr];case"i8":return HEAP8[ptr];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":abort("to do getValue(i64) use WASM_BIGINT");case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];case"*":return HEAPU32[ptr>>2];default:abort(`invalid type for getValue: ${type}`)}}Module["getValue_safe"]=getValue_safe;var noExitRuntime=Module["noExitRuntime"]||true;Module["noExitRuntime"]=noExitRuntime;function setValue(ptr,value,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":SAFE_HEAP_STORE(ptr,value,1);break;case"i8":SAFE_HEAP_STORE(ptr,value,1);break;case"i16":SAFE_HEAP_STORE((ptr>>1)*2,value,2);break;case"i32":SAFE_HEAP_STORE((ptr>>2)*4,value,4);break;case"i64":abort("to do setValue(i64) use WASM_BIGINT");case"float":SAFE_HEAP_STORE_D((ptr>>2)*4,value,4);break;case"double":SAFE_HEAP_STORE_D((ptr>>3)*8,value,8);break;case"*":SAFE_HEAP_STORE((ptr>>2)*4,value,4);break;default:abort(`invalid type for setValue: ${type}`)}}Module["setValue"]=setValue;function setValue_safe(ptr,value,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":HEAP8[ptr]=value;break;case"i8":HEAP8[ptr]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":abort("to do setValue(i64) use WASM_BIGINT");case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;case"*":HEAPU32[ptr>>2]=value;break;default:abort(`invalid type for setValue: ${type}`)}}Module["setValue_safe"]=setValue_safe;var stackRestore=val=>__emscripten_stack_restore(val);Module["stackRestore"]=stackRestore;var stackSave=()=>_emscripten_stack_get_current();Module["stackSave"]=stackSave;var unSign=(value,bits)=>{if(value>=0){return value}return bits<=32?2*Math.abs(1<{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};Module["UTF8ArrayToString"]=UTF8ArrayToString;var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";Module["UTF8ToString"]=UTF8ToString;var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};Module["___assert_fail"]=___assert_fail;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){SAFE_HEAP_STORE((this.ptr+4>>2)*4,type,4)}get_type(){return SAFE_HEAP_LOAD((this.ptr+4>>2)*4,4,1)}set_destructor(destructor){SAFE_HEAP_STORE((this.ptr+8>>2)*4,destructor,4)}get_destructor(){return SAFE_HEAP_LOAD((this.ptr+8>>2)*4,4,1)}set_caught(caught){caught=caught?1:0;SAFE_HEAP_STORE(this.ptr+12,caught,1)}get_caught(){return SAFE_HEAP_LOAD(this.ptr+12,1,0)!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;SAFE_HEAP_STORE(this.ptr+13,rethrown,1)}get_rethrown(){return SAFE_HEAP_LOAD(this.ptr+13,1,0)!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){SAFE_HEAP_STORE((this.ptr+16>>2)*4,adjustedPtr,4)}get_adjusted_ptr(){return SAFE_HEAP_LOAD((this.ptr+16>>2)*4,4,1)}get_exception_ptr(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return SAFE_HEAP_LOAD((this.excPtr>>2)*4,4,1)}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}Module["ExceptionInfo"]=ExceptionInfo;var exceptionLast=0;Module["exceptionLast"]=exceptionLast;var uncaughtExceptionCount=0;Module["uncaughtExceptionCount"]=uncaughtExceptionCount;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};Module["___cxa_throw"]=___cxa_throw;function syscallGetVarargI(){var ret=SAFE_HEAP_LOAD((+SYSCALLS.varargs>>2)*4,4,0);SYSCALLS.varargs+=4;return ret}Module["syscallGetVarargI"]=syscallGetVarargI;var syscallGetVarargP=syscallGetVarargI;Module["syscallGetVarargP"]=syscallGetVarargP;var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};Module["PATH"]=PATH;var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("initRandomDevice")};Module["initRandomFill"]=initRandomFill;var randomFill=view=>(randomFill=initRandomFill())(view);Module["randomFill"]=randomFill;var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};Module["lengthBytesUTF8"]=lengthBytesUTF8;var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};Module["stringToUTF8Array"]=stringToUTF8Array;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};Module["FS_stdin_getChar"]=FS_stdin_getChar;var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};Module["TTY"]=TTY;var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size);return address};Module["zeroMemory"]=zeroMemory;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;Module["alignMemory"]=alignMemory;var mmapAlloc=size=>{abort()};Module["mmapAlloc"]=mmapAlloc;var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url,arrayBuffer=>{onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};Module["asyncLoad"]=asyncLoad;var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};Module["FS_createDataFile"]=FS_createDataFile;var preloadPlugins=Module["preloadPlugins"]||[];Module["preloadPlugins"]=preloadPlugins;var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};Module["FS_handledByPreloadPlugin"]=FS_handledByPreloadPlugin;var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,processData,onerror)}else{processData(url)}};Module["FS_createPreloadedFile"]=FS_createPreloadedFile;var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};Module["FS_modeStringToFlags"]=FS_modeStringToFlags;var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};Module["FS_getMode"]=FS_getMode;var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class{constructor(errno){this.name="ErrnoError";this.errno=errno}},genericErrors:{},filesystems:null,syncFSRequests:0,FSStream:class{constructor(){this.shared={}}get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev;this.readMode=292|73;this.writeMode=146}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;iFS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(){if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""});FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS:MEMFS}},init(input,output,error){FS.init.initialized=true;Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit(){FS.init.initialized=false;for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};Module["FS"]=FS;var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){var stat=func(path);SAFE_HEAP_STORE((buf>>2)*4,stat.dev,4);SAFE_HEAP_STORE((buf+4>>2)*4,stat.mode,4);SAFE_HEAP_STORE((buf+8>>2)*4,stat.nlink,4);SAFE_HEAP_STORE((buf+12>>2)*4,stat.uid,4);SAFE_HEAP_STORE((buf+16>>2)*4,stat.gid,4);SAFE_HEAP_STORE((buf+20>>2)*4,stat.rdev,4);tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+24>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+28>>2)*4,tempI64[1],4);SAFE_HEAP_STORE((buf+32>>2)*4,4096,4);SAFE_HEAP_STORE((buf+36>>2)*4,stat.blocks,4);var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+40>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+44>>2)*4,tempI64[1],4);SAFE_HEAP_STORE((buf+48>>2)*4,atime%1e3*1e3,4);tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+56>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+60>>2)*4,tempI64[1],4);SAFE_HEAP_STORE((buf+64>>2)*4,mtime%1e3*1e3,4);tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+72>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+76>>2)*4,tempI64[1],4);SAFE_HEAP_STORE((buf+80>>2)*4,ctime%1e3*1e3,4);tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((buf+88>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((buf+92>>2)*4,tempI64[1],4);return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};Module["SYSCALLS"]=SYSCALLS;function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;SAFE_HEAP_STORE((arg+offset>>1)*2,2,2);return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}Module["___syscall_fcntl64"]=___syscall_fcntl64;function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();SAFE_HEAP_STORE((argp>>2)*4,termios.c_iflag||0,4);SAFE_HEAP_STORE((argp+4>>2)*4,termios.c_oflag||0,4);SAFE_HEAP_STORE((argp+8>>2)*4,termios.c_cflag||0,4);SAFE_HEAP_STORE((argp+12>>2)*4,termios.c_lflag||0,4);for(var i=0;i<32;i++){SAFE_HEAP_STORE(argp+i+17,termios.c_cc[i]||0,1)}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=SAFE_HEAP_LOAD((argp>>2)*4,4,0);var c_oflag=SAFE_HEAP_LOAD((argp+4>>2)*4,4,0);var c_cflag=SAFE_HEAP_LOAD((argp+8>>2)*4,4,0);var c_lflag=SAFE_HEAP_LOAD((argp+12>>2)*4,4,0);var c_cc=[];for(var i=0;i<32;i++){c_cc.push(SAFE_HEAP_LOAD(argp+i+17,1,0))}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag:c_iflag,c_oflag:c_oflag,c_cflag:c_cflag,c_lflag:c_lflag,c_cc:c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();SAFE_HEAP_STORE((argp>>2)*4,0,4);return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();SAFE_HEAP_STORE((argp>>1)*2,winsize[0],2);SAFE_HEAP_STORE((argp+2>>1)*2,winsize[1],2)}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}Module["___syscall_ioctl"]=___syscall_ioctl;function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}Module["___syscall_openat"]=___syscall_openat;var __abort_js=()=>{abort("")};Module["__abort_js"]=__abort_js;var __emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);Module["__emscripten_memcpy_js"]=__emscripten_memcpy_js;var readEmAsmArgsArray=[];Module["readEmAsmArgsArray"]=readEmAsmArgsArray;var readEmAsmArgs=(sigPtr,buf)=>{readEmAsmArgsArray.length=0;var ch;while(ch=SAFE_HEAP_LOAD(sigPtr++,1,1)){var wide=ch!=105;wide&=ch!=112;buf+=wide&&buf%8?4:0;readEmAsmArgsArray.push(ch==112?SAFE_HEAP_LOAD((buf>>2)*4,4,1):ch==105?SAFE_HEAP_LOAD((buf>>2)*4,4,0):SAFE_HEAP_LOAD_D((buf>>3)*8,8,0));buf+=wide?8:4}return readEmAsmArgsArray};Module["readEmAsmArgs"]=readEmAsmArgs;var runEmAsmFunction=(code,sigPtr,argbuf)=>{var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code](...args)};Module["runEmAsmFunction"]=runEmAsmFunction;var _emscripten_asm_const_int=(code,sigPtr,argbuf)=>runEmAsmFunction(code,sigPtr,argbuf);Module["_emscripten_asm_const_int"]=_emscripten_asm_const_int;var getHeapMax=()=>2147483648;Module["getHeapMax"]=getHeapMax;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};Module["growMemory"]=growMemory;var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};Module["_emscripten_resize_heap"]=_emscripten_resize_heap;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}Module["_fd_close"]=_fd_close;var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2)*4,4,1);var len=SAFE_HEAP_LOAD((iov+4>>2)*4,4,1);iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2)*4,num,4);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}Module["_fd_read"]=_fd_read;var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;Module["convertI32PairToI53Checked"]=convertI32PairToI53Checked;function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],SAFE_HEAP_STORE((newOffset>>2)*4,tempI64[0],4),SAFE_HEAP_STORE((newOffset+4>>2)*4,tempI64[1],4);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}Module["_fd_seek"]=_fd_seek;var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2)*4,4,1);var len=SAFE_HEAP_LOAD((iov+4>>2)*4,4,1);iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!="undefined"){offset+=curr}}return ret};Module["doWritev"]=doWritev;function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);SAFE_HEAP_STORE((pnum>>2)*4,num,4);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}Module["_fd_write"]=_fd_write;var _getentropy=(buffer,size)=>{randomFill(HEAPU8.subarray(buffer,buffer+size));return 0};Module["_getentropy"]=_getentropy;var getCFunc=ident=>{var func=Module["_"+ident];return func};Module["getCFunc"]=getCFunc;var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};Module["writeArrayToMemory"]=writeArrayToMemory;var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);Module["stringToUTF8"]=stringToUTF8;var stackAlloc=sz=>__emscripten_stack_alloc(sz);Module["stackAlloc"]=stackAlloc;var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};Module["stringToUTF8OnStack"]=stringToUTF8OnStack;var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};Module["cwrap"]=cwrap;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();var wasmImports={a:___assert_fail,h:___cxa_throw,g:___syscall_fcntl64,j:___syscall_ioctl,k:___syscall_openat,o:__abort_js,l:__emscripten_memcpy_js,c:alignfault,d:_emscripten_asm_const_int,p:_emscripten_resize_heap,e:_fd_close,i:_fd_read,m:_fd_seek,f:_fd_write,n:_getentropy,b:segfault};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["r"])();var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["t"])(a0);var _free=Module["_free"]=a0=>(_free=Module["_free"]=wasmExports["u"])(a0);var _ma_device__on_notification_unlocked=Module["_ma_device__on_notification_unlocked"]=a0=>(_ma_device__on_notification_unlocked=Module["_ma_device__on_notification_unlocked"]=wasmExports["v"])(a0);var _ma_malloc_emscripten=Module["_ma_malloc_emscripten"]=(a0,a1)=>(_ma_malloc_emscripten=Module["_ma_malloc_emscripten"]=wasmExports["w"])(a0,a1);var _ma_free_emscripten=Module["_ma_free_emscripten"]=(a0,a1)=>(_ma_free_emscripten=Module["_ma_free_emscripten"]=wasmExports["x"])(a0,a1);var _ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=(a0,a1,a2)=>(_ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=wasmExports["y"])(a0,a1,a2);var _ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=(a0,a1,a2)=>(_ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=wasmExports["z"])(a0,a1,a2);var _createWorkerInWasm=Module["_createWorkerInWasm"]=()=>(_createWorkerInWasm=Module["_createWorkerInWasm"]=wasmExports["A"])();var _sendToWorker=Module["_sendToWorker"]=(a0,a1)=>(_sendToWorker=Module["_sendToWorker"]=wasmExports["B"])(a0,a1);var _nativeFree=Module["_nativeFree"]=a0=>(_nativeFree=Module["_nativeFree"]=wasmExports["C"])(a0);var _voiceEndedCallback=Module["_voiceEndedCallback"]=a0=>(_voiceEndedCallback=Module["_voiceEndedCallback"]=wasmExports["D"])(a0);var _setDartEventCallback=Module["_setDartEventCallback"]=(a0,a1,a2)=>(_setDartEventCallback=Module["_setDartEventCallback"]=wasmExports["E"])(a0,a1,a2);var _initEngine=Module["_initEngine"]=(a0,a1,a2,a3)=>(_initEngine=Module["_initEngine"]=wasmExports["F"])(a0,a1,a2,a3);var _changeDevice=Module["_changeDevice"]=a0=>(_changeDevice=Module["_changeDevice"]=wasmExports["G"])(a0);var _listPlaybackDevices=Module["_listPlaybackDevices"]=(a0,a1,a2,a3)=>(_listPlaybackDevices=Module["_listPlaybackDevices"]=wasmExports["H"])(a0,a1,a2,a3);var _freeListPlaybackDevices=Module["_freeListPlaybackDevices"]=(a0,a1,a2,a3)=>(_freeListPlaybackDevices=Module["_freeListPlaybackDevices"]=wasmExports["I"])(a0,a1,a2,a3);var _dispose=Module["_dispose"]=()=>(_dispose=Module["_dispose"]=wasmExports["J"])();var _isInited=Module["_isInited"]=()=>(_isInited=Module["_isInited"]=wasmExports["K"])();var _loadFile=Module["_loadFile"]=(a0,a1)=>(_loadFile=Module["_loadFile"]=wasmExports["L"])(a0,a1);var _loadMem=Module["_loadMem"]=(a0,a1,a2,a3,a4)=>(_loadMem=Module["_loadMem"]=wasmExports["M"])(a0,a1,a2,a3,a4);var _setBufferStream=Module["_setBufferStream"]=(a0,a1,a2,a3,a4,a5,a6)=>(_setBufferStream=Module["_setBufferStream"]=wasmExports["N"])(a0,a1,a2,a3,a4,a5,a6);var _addAudioDataStream=Module["_addAudioDataStream"]=(a0,a1,a2)=>(_addAudioDataStream=Module["_addAudioDataStream"]=wasmExports["O"])(a0,a1,a2);var _setDataIsEnded=Module["_setDataIsEnded"]=a0=>(_setDataIsEnded=Module["_setDataIsEnded"]=wasmExports["P"])(a0);var _getBufferSize=Module["_getBufferSize"]=(a0,a1)=>(_getBufferSize=Module["_getBufferSize"]=wasmExports["Q"])(a0,a1);var _loadWaveform=Module["_loadWaveform"]=(a0,a1,a2,a3,a4)=>(_loadWaveform=Module["_loadWaveform"]=wasmExports["R"])(a0,a1,a2,a3,a4);var _setWaveformScale=Module["_setWaveformScale"]=(a0,a1)=>(_setWaveformScale=Module["_setWaveformScale"]=wasmExports["S"])(a0,a1);var _setWaveformDetune=Module["_setWaveformDetune"]=(a0,a1)=>(_setWaveformDetune=Module["_setWaveformDetune"]=wasmExports["T"])(a0,a1);var _setWaveformFreq=Module["_setWaveformFreq"]=(a0,a1)=>(_setWaveformFreq=Module["_setWaveformFreq"]=wasmExports["U"])(a0,a1);var _setSuperWave=Module["_setSuperWave"]=(a0,a1)=>(_setSuperWave=Module["_setSuperWave"]=wasmExports["V"])(a0,a1);var _setWaveform=Module["_setWaveform"]=(a0,a1)=>(_setWaveform=Module["_setWaveform"]=wasmExports["W"])(a0,a1);var _speechText=Module["_speechText"]=(a0,a1)=>(_speechText=Module["_speechText"]=wasmExports["X"])(a0,a1);var _pauseSwitch=Module["_pauseSwitch"]=a0=>(_pauseSwitch=Module["_pauseSwitch"]=wasmExports["Y"])(a0);var _setPause=Module["_setPause"]=(a0,a1)=>(_setPause=Module["_setPause"]=wasmExports["Z"])(a0,a1);var _getPause=Module["_getPause"]=a0=>(_getPause=Module["_getPause"]=wasmExports["_"])(a0);var _setRelativePlaySpeed=Module["_setRelativePlaySpeed"]=(a0,a1)=>(_setRelativePlaySpeed=Module["_setRelativePlaySpeed"]=wasmExports["$"])(a0,a1);var _getRelativePlaySpeed=Module["_getRelativePlaySpeed"]=a0=>(_getRelativePlaySpeed=Module["_getRelativePlaySpeed"]=wasmExports["aa"])(a0);var _play=Module["_play"]=(a0,a1,a2,a3,a4,a5,a6)=>(_play=Module["_play"]=wasmExports["ba"])(a0,a1,a2,a3,a4,a5,a6);var _stop=Module["_stop"]=a0=>(_stop=Module["_stop"]=wasmExports["ca"])(a0);var _disposeSound=Module["_disposeSound"]=a0=>(_disposeSound=Module["_disposeSound"]=wasmExports["da"])(a0);var _disposeAllSound=Module["_disposeAllSound"]=()=>(_disposeAllSound=Module["_disposeAllSound"]=wasmExports["ea"])();var _getLooping=Module["_getLooping"]=a0=>(_getLooping=Module["_getLooping"]=wasmExports["fa"])(a0);var _setLooping=Module["_setLooping"]=(a0,a1)=>(_setLooping=Module["_setLooping"]=wasmExports["ga"])(a0,a1);var _getLoopPoint=Module["_getLoopPoint"]=a0=>(_getLoopPoint=Module["_getLoopPoint"]=wasmExports["ha"])(a0);var _setLoopPoint=Module["_setLoopPoint"]=(a0,a1)=>(_setLoopPoint=Module["_setLoopPoint"]=wasmExports["ia"])(a0,a1);var _setVisualizationEnabled=Module["_setVisualizationEnabled"]=a0=>(_setVisualizationEnabled=Module["_setVisualizationEnabled"]=wasmExports["ja"])(a0);var _getVisualizationEnabled=Module["_getVisualizationEnabled"]=()=>(_getVisualizationEnabled=Module["_getVisualizationEnabled"]=wasmExports["ka"])();var _getFft=Module["_getFft"]=a0=>(_getFft=Module["_getFft"]=wasmExports["la"])(a0);var _getWave=Module["_getWave"]=a0=>(_getWave=Module["_getWave"]=wasmExports["ma"])(a0);var _setFftSmoothing=Module["_setFftSmoothing"]=a0=>(_setFftSmoothing=Module["_setFftSmoothing"]=wasmExports["na"])(a0);var _getAudioTexture=Module["_getAudioTexture"]=a0=>(_getAudioTexture=Module["_getAudioTexture"]=wasmExports["oa"])(a0);var _getAudioTexture2D=Module["_getAudioTexture2D"]=a0=>(_getAudioTexture2D=Module["_getAudioTexture2D"]=wasmExports["pa"])(a0);var _getTextureValue=Module["_getTextureValue"]=(a0,a1)=>(_getTextureValue=Module["_getTextureValue"]=wasmExports["qa"])(a0,a1);var _getLength=Module["_getLength"]=a0=>(_getLength=Module["_getLength"]=wasmExports["ra"])(a0);var _seek=Module["_seek"]=(a0,a1)=>(_seek=Module["_seek"]=wasmExports["sa"])(a0,a1);var _getPosition=Module["_getPosition"]=a0=>(_getPosition=Module["_getPosition"]=wasmExports["ta"])(a0);var _getGlobalVolume=Module["_getGlobalVolume"]=()=>(_getGlobalVolume=Module["_getGlobalVolume"]=wasmExports["ua"])();var _setGlobalVolume=Module["_setGlobalVolume"]=a0=>(_setGlobalVolume=Module["_setGlobalVolume"]=wasmExports["va"])(a0);var _getVolume=Module["_getVolume"]=a0=>(_getVolume=Module["_getVolume"]=wasmExports["wa"])(a0);var _setVolume=Module["_setVolume"]=(a0,a1)=>(_setVolume=Module["_setVolume"]=wasmExports["xa"])(a0,a1);var _getPan=Module["_getPan"]=a0=>(_getPan=Module["_getPan"]=wasmExports["ya"])(a0);var _setPan=Module["_setPan"]=(a0,a1)=>(_setPan=Module["_setPan"]=wasmExports["za"])(a0,a1);var _setPanAbsolute=Module["_setPanAbsolute"]=(a0,a1,a2)=>(_setPanAbsolute=Module["_setPanAbsolute"]=wasmExports["Aa"])(a0,a1,a2);var _getIsValidVoiceHandle=Module["_getIsValidVoiceHandle"]=a0=>(_getIsValidVoiceHandle=Module["_getIsValidVoiceHandle"]=wasmExports["Ba"])(a0);var _getActiveVoiceCount=Module["_getActiveVoiceCount"]=()=>(_getActiveVoiceCount=Module["_getActiveVoiceCount"]=wasmExports["Ca"])();var _countAudioSource=Module["_countAudioSource"]=a0=>(_countAudioSource=Module["_countAudioSource"]=wasmExports["Da"])(a0);var _getVoiceCount=Module["_getVoiceCount"]=()=>(_getVoiceCount=Module["_getVoiceCount"]=wasmExports["Ea"])();var _getProtectVoice=Module["_getProtectVoice"]=a0=>(_getProtectVoice=Module["_getProtectVoice"]=wasmExports["Fa"])(a0);var _setProtectVoice=Module["_setProtectVoice"]=(a0,a1)=>(_setProtectVoice=Module["_setProtectVoice"]=wasmExports["Ga"])(a0,a1);var _getMaxActiveVoiceCount=Module["_getMaxActiveVoiceCount"]=()=>(_getMaxActiveVoiceCount=Module["_getMaxActiveVoiceCount"]=wasmExports["Ha"])();var _setMaxActiveVoiceCount=Module["_setMaxActiveVoiceCount"]=a0=>(_setMaxActiveVoiceCount=Module["_setMaxActiveVoiceCount"]=wasmExports["Ia"])(a0);var _createVoiceGroup=Module["_createVoiceGroup"]=()=>(_createVoiceGroup=Module["_createVoiceGroup"]=wasmExports["Ja"])();var _destroyVoiceGroup=Module["_destroyVoiceGroup"]=a0=>(_destroyVoiceGroup=Module["_destroyVoiceGroup"]=wasmExports["Ka"])(a0);var _addVoiceToGroup=Module["_addVoiceToGroup"]=(a0,a1)=>(_addVoiceToGroup=Module["_addVoiceToGroup"]=wasmExports["La"])(a0,a1);var _isVoiceGroup=Module["_isVoiceGroup"]=a0=>(_isVoiceGroup=Module["_isVoiceGroup"]=wasmExports["Ma"])(a0);var _isVoiceGroupEmpty=Module["_isVoiceGroupEmpty"]=a0=>(_isVoiceGroupEmpty=Module["_isVoiceGroupEmpty"]=wasmExports["Na"])(a0);var _fadeGlobalVolume=Module["_fadeGlobalVolume"]=(a0,a1)=>(_fadeGlobalVolume=Module["_fadeGlobalVolume"]=wasmExports["Oa"])(a0,a1);var _fadeVolume=Module["_fadeVolume"]=(a0,a1,a2)=>(_fadeVolume=Module["_fadeVolume"]=wasmExports["Pa"])(a0,a1,a2);var _fadePan=Module["_fadePan"]=(a0,a1,a2)=>(_fadePan=Module["_fadePan"]=wasmExports["Qa"])(a0,a1,a2);var _fadeRelativePlaySpeed=Module["_fadeRelativePlaySpeed"]=(a0,a1,a2)=>(_fadeRelativePlaySpeed=Module["_fadeRelativePlaySpeed"]=wasmExports["Ra"])(a0,a1,a2);var _schedulePause=Module["_schedulePause"]=(a0,a1)=>(_schedulePause=Module["_schedulePause"]=wasmExports["Sa"])(a0,a1);var _scheduleStop=Module["_scheduleStop"]=(a0,a1)=>(_scheduleStop=Module["_scheduleStop"]=wasmExports["Ta"])(a0,a1);var _oscillateVolume=Module["_oscillateVolume"]=(a0,a1,a2,a3)=>(_oscillateVolume=Module["_oscillateVolume"]=wasmExports["Ua"])(a0,a1,a2,a3);var _oscillatePan=Module["_oscillatePan"]=(a0,a1,a2,a3)=>(_oscillatePan=Module["_oscillatePan"]=wasmExports["Va"])(a0,a1,a2,a3);var _oscillateRelativePlaySpeed=Module["_oscillateRelativePlaySpeed"]=(a0,a1,a2,a3)=>(_oscillateRelativePlaySpeed=Module["_oscillateRelativePlaySpeed"]=wasmExports["Wa"])(a0,a1,a2,a3);var _oscillateGlobalVolume=Module["_oscillateGlobalVolume"]=(a0,a1,a2)=>(_oscillateGlobalVolume=Module["_oscillateGlobalVolume"]=wasmExports["Xa"])(a0,a1,a2);var _isFilterActive=Module["_isFilterActive"]=(a0,a1,a2)=>(_isFilterActive=Module["_isFilterActive"]=wasmExports["Ya"])(a0,a1,a2);var _getFilterParamNames=Module["_getFilterParamNames"]=(a0,a1,a2)=>(_getFilterParamNames=Module["_getFilterParamNames"]=wasmExports["Za"])(a0,a1,a2);var _addFilter=Module["_addFilter"]=(a0,a1)=>(_addFilter=Module["_addFilter"]=wasmExports["_a"])(a0,a1);var _removeFilter=Module["_removeFilter"]=(a0,a1)=>(_removeFilter=Module["_removeFilter"]=wasmExports["$a"])(a0,a1);var _setFilterParams=Module["_setFilterParams"]=(a0,a1,a2,a3)=>(_setFilterParams=Module["_setFilterParams"]=wasmExports["ab"])(a0,a1,a2,a3);var _getFilterParams=Module["_getFilterParams"]=(a0,a1,a2,a3)=>(_getFilterParams=Module["_getFilterParams"]=wasmExports["bb"])(a0,a1,a2,a3);var _fadeFilterParameter=Module["_fadeFilterParameter"]=(a0,a1,a2,a3,a4)=>(_fadeFilterParameter=Module["_fadeFilterParameter"]=wasmExports["cb"])(a0,a1,a2,a3,a4);var _oscillateFilterParameter=Module["_oscillateFilterParameter"]=(a0,a1,a2,a3,a4,a5)=>(_oscillateFilterParameter=Module["_oscillateFilterParameter"]=wasmExports["db"])(a0,a1,a2,a3,a4,a5);var _play3d=Module["_play3d"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)=>(_play3d=Module["_play3d"]=wasmExports["eb"])(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11);var _set3dSoundSpeed=Module["_set3dSoundSpeed"]=a0=>(_set3dSoundSpeed=Module["_set3dSoundSpeed"]=wasmExports["fb"])(a0);var _get3dSoundSpeed=Module["_get3dSoundSpeed"]=()=>(_get3dSoundSpeed=Module["_get3dSoundSpeed"]=wasmExports["gb"])();var _set3dListenerParameters=Module["_set3dListenerParameters"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)=>(_set3dListenerParameters=Module["_set3dListenerParameters"]=wasmExports["hb"])(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11);var _set3dListenerPosition=Module["_set3dListenerPosition"]=(a0,a1,a2)=>(_set3dListenerPosition=Module["_set3dListenerPosition"]=wasmExports["ib"])(a0,a1,a2);var _set3dListenerAt=Module["_set3dListenerAt"]=(a0,a1,a2)=>(_set3dListenerAt=Module["_set3dListenerAt"]=wasmExports["jb"])(a0,a1,a2);var _set3dListenerUp=Module["_set3dListenerUp"]=(a0,a1,a2)=>(_set3dListenerUp=Module["_set3dListenerUp"]=wasmExports["kb"])(a0,a1,a2);var _set3dListenerVelocity=Module["_set3dListenerVelocity"]=(a0,a1,a2)=>(_set3dListenerVelocity=Module["_set3dListenerVelocity"]=wasmExports["lb"])(a0,a1,a2);var _set3dSourceParameters=Module["_set3dSourceParameters"]=(a0,a1,a2,a3,a4,a5,a6)=>(_set3dSourceParameters=Module["_set3dSourceParameters"]=wasmExports["mb"])(a0,a1,a2,a3,a4,a5,a6);var _set3dSourcePosition=Module["_set3dSourcePosition"]=(a0,a1,a2,a3)=>(_set3dSourcePosition=Module["_set3dSourcePosition"]=wasmExports["nb"])(a0,a1,a2,a3);var _set3dSourceVelocity=Module["_set3dSourceVelocity"]=(a0,a1,a2,a3)=>(_set3dSourceVelocity=Module["_set3dSourceVelocity"]=wasmExports["ob"])(a0,a1,a2,a3);var _set3dSourceMinMaxDistance=Module["_set3dSourceMinMaxDistance"]=(a0,a1,a2)=>(_set3dSourceMinMaxDistance=Module["_set3dSourceMinMaxDistance"]=wasmExports["pb"])(a0,a1,a2);var _set3dSourceAttenuation=Module["_set3dSourceAttenuation"]=(a0,a1,a2)=>(_set3dSourceAttenuation=Module["_set3dSourceAttenuation"]=wasmExports["qb"])(a0,a1,a2);var _set3dSourceDopplerFactor=Module["_set3dSourceDopplerFactor"]=(a0,a1)=>(_set3dSourceDopplerFactor=Module["_set3dSourceDopplerFactor"]=wasmExports["rb"])(a0,a1);var _readSamplesFromFile=Module["_readSamplesFromFile"]=(a0,a1,a2,a3,a4,a5)=>(_readSamplesFromFile=Module["_readSamplesFromFile"]=wasmExports["sb"])(a0,a1,a2,a3,a4,a5);var _readSamplesFromMem=Module["_readSamplesFromMem"]=(a0,a1,a2,a3,a4,a5,a6)=>(_readSamplesFromMem=Module["_readSamplesFromMem"]=wasmExports["tb"])(a0,a1,a2,a3,a4,a5,a6);var _emscripten_get_sbrk_ptr=()=>(_emscripten_get_sbrk_ptr=wasmExports["ub"])();var _sbrk=a0=>(_sbrk=wasmExports["vb"])(a0);var _emscripten_stack_get_base=()=>(_emscripten_stack_get_base=wasmExports["wb"])();var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["xb"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["yb"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["zb"])();var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["Ab"])(a0);var dynCall_iiji=Module["dynCall_iiji"]=(a0,a1,a2,a3,a4)=>(dynCall_iiji=Module["dynCall_iiji"]=wasmExports["Bb"])(a0,a1,a2,a3,a4);var dynCall_iiiji=Module["dynCall_iiiji"]=(a0,a1,a2,a3,a4,a5)=>(dynCall_iiiji=Module["dynCall_iiiji"]=wasmExports["Cb"])(a0,a1,a2,a3,a4,a5);var dynCall_jii=Module["dynCall_jii"]=(a0,a1,a2)=>(dynCall_jii=Module["dynCall_jii"]=wasmExports["Db"])(a0,a1,a2);var dynCall_iij=Module["dynCall_iij"]=(a0,a1,a2,a3)=>(dynCall_iij=Module["dynCall_iij"]=wasmExports["Eb"])(a0,a1,a2,a3);var dynCall_jiji=Module["dynCall_jiji"]=(a0,a1,a2,a3,a4)=>(dynCall_jiji=Module["dynCall_jiji"]=wasmExports["Fb"])(a0,a1,a2,a3,a4);Module["ccall"]=ccall;Module["cwrap"]=cwrap;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); diff --git a/web/libflutter_soloud_plugin.wasm b/web/libflutter_soloud_plugin.wasm index 131d42b..379e8fb 100755 Binary files a/web/libflutter_soloud_plugin.wasm and b/web/libflutter_soloud_plugin.wasm differ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 75260e5..c2e915d 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -41,6 +41,7 @@ list(APPEND PLUGIN_SOURCES "${SRC_DIR}/analyzer.cpp" "${SRC_DIR}/synth/basic_wave.cpp" "${SRC_DIR}/waveform/waveform.cpp" + "${SRC_DIR}/audiobuffer/audiobuffer.cpp" "${SRC_DIR}/filters/filters.cpp" "${SRC_DIR}/filters/pitch_shift_filter.cpp" "${SRC_DIR}/filters/smbPitchShift.cpp"