mertguner / sound_generator

This plugin is a procedural sound generator.
MIT License
29 stars 27 forks source link

Fatal Exception: java.lang.OutOfMemoryError #3

Open leidig54 opened 3 years ago

leidig54 commented 3 years ago

Hi @mertguner

I am getting the following error through firebase crashlytics on some devices.

Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 124606360 byte allocation with 25165824 free bytes and 108MB until OOM, max allowed footprint 112613568, growth limit 201326592
       at java.util.Arrays.copyOf(Arrays.java:3139)
       at java.util.Arrays.copyOf(Arrays.java:3109)
       at java.util.ArrayList.grow(ArrayList.java:275)
       at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:249)
       at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:241)
       at java.util.ArrayList.add(ArrayList.java:467)
       at io.github.mertguner.sound_generator.generators.signalDataGenerator.createOneCycleData(signalDataGenerator.java:60)
       at io.github.mertguner.sound_generator.generators.signalDataGenerator.createOneCycleData(signalDataGenerator.java:1)
       at io.github.mertguner.sound_generator.generators.signalDataGenerator.setFrequency(signalDataGenerator.java:2)
       at io.github.mertguner.sound_generator.SoundGenerator.setFrequency(SoundGenerator.java:4)
       at io.github.mertguner.sound_generator.SoundGeneratorPlugin.onMethodCall(SoundGeneratorPlugin.java:159)
       at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:17)
       at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:57)
       at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:4)
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:325)
       at android.os.Looper.loop(Looper.java:142)
       at android.app.ActivityThread.main(ActivityThread.java:7000)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)

Screenshot 2021-05-11 at 07 37 03 Screenshot 2021-05-11 at 07 36 58

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.0.6, on macOS 11.3.1 20E241
    darwin-arm, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK
    version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.56.0)
[✓] Connected device (3 available)

• No issues found!

No issues on my own test device.

Any suggestions?

ryanheise commented 3 years ago

The Android implementation looks like it internally creates a list of integer objects for the generated wave data to send over the method channel to the plugin's Flutter front-end. This is very memory-inefficent, particularly at low frequencies and a high sample rate which results in a long list of individual heap-allocated Integer objects. And these get recreated each time the frequency changes which is not good if the user can adjust the frequency with a Slider and cause this to get recreated many times per second.

Instead, it would be better to use a normal Java array - see the documentation for StandardMessageCodecStandardMessageCodec . A Java byte array is received on the Flutter side as a Uint8List. If the audio data is 16 bit, that data needs to be packed into a byte array where adjacent bytes make up a short, as long as the same endian-ness is used on both sides of the platform channel.