igorski / MWEngine

Audio engine and DSP library for Android, written in C++ providing low latency performance within a musical context, while providing a Java/Kotlin API. Supports both OpenSL and AAudio.
MIT License
257 stars 45 forks source link

Crashes when muting/unmuting #145

Closed vustav closed 2 years ago

vustav commented 2 years ago

In the drum machine I'm working on you have a set of tracks with events in them. There's an option to switch to another set of tracks with their events (for a chorus or w.e). The way I do it now is I mute the set of tracks that shouldn't play any more and unmute the set that should (setMute(true) on the instruments audioChannel). This sometimes crashes.

First of all, is this a viable way of handling this? Are muted intruments events removed from the sequencer or do they keep playing with volume at 0? Should I do a proper removal of all events and effects and all that from the sequencer instead?

And second how do you want the crash report? Copy+paste from logcat or the whole tombstone or something else? I'm not very well versed in C and debugging and all that =)

Another detail is that the tracks have two instruments each, one for SampleEvents and one for SynthEvents, only one of them unmuted at a time.

igorski commented 2 years ago

Hi there!

Well that behaviour is odd to say the least.

Are muted intruments events removed from the sequencer or do they keep playing with volume at 0? Should I do a proper removal of all events and effects and all that from the sequencer instead?

Muted instruments are ignored by the sequencer. As such you can keep all events and processors for that instrument active without any impact.

I do wonder if your approach is the correct one, if I understand correctly you are switching to a different pattern ? If that pattern is to be played by the same instrument with the same config I would merely replace the audio events of the instrument.

You can do this while the sequencer is running by invoking event.enqueueRemoval() (which will remove the from the Sequencer on the next run). You can then either hold a reference to these events (perhaps in a list for the sequence) so you can reuse them later, or you can dispose them. At the same time you enqueue all events from the pattern you are loading as usual. (I should probably dedicate a Wiki page on this)

I would like to see the crash report though as muting an instrument essentially leads to a no-op, so if this is broken that is bad news 🙈 The logcat output is fine, I'm assuming a SIGSEV11 or similar segmentation fault is at play here. If you can provide the stack trace I can have a look.

vustav commented 2 years ago

2022-01-29 10:04:59.575 22933-22992/? A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x1 in tid 22992 (Thread-7) 2022-01-29 10:04:59.695 23499-23499/? A/DEBUG: 2022-01-29 10:04:59.695 23499-23499/? A/DEBUG: Build fingerprint: 'google/sdk_gphone_x86/generic_x86:8.0.0/OSR1.170901.043/4456315:user/release-keys' 2022-01-29 10:04:59.695 23499-23499/? A/DEBUG: Revision: '0' 2022-01-29 10:04:59.695 23499-23499/? A/DEBUG: ABI: 'x86' 2022-01-29 10:04:59.695 23499-23499/? A/DEBUG: pid: 22933, tid: 22992, name: Thread-7 >>> com.kiefer.llppdrums <<< 2022-01-29 10:04:59.695 23499-23499/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x1 2022-01-29 10:04:59.695 23499-23499/? A/DEBUG: Cause: null pointer dereference 2022-01-29 10:04:59.696 23499-23499/? A/DEBUG: eax 917f9c08 ebx 917fd74c ecx 9f17ee80 edx 0000003c 2022-01-29 10:04:59.696 23499-23499/? A/DEBUG: esi 00000000 edi 9ef540e0 2022-01-29 10:04:59.696 23499-23499/? A/DEBUG: xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b 2022-01-29 10:04:59.696 23499-23499/? A/DEBUG: eip 00000001 ebp 915c23e8 esp 915c238c flags 00010246 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: backtrace: 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #00 pc 00000001 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #01 pc 000708f0 /data/app/com.kiefer.llppdrums-hrBNBkrB2E3jVtZWHH_JDw==/base.apk (offset 0xc00000) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #02 pc 0006d208 /data/app/com.kiefer.llppdrums-hrBNBkrB2E3jVtZWHH_JDw==/base.apk (offset 0xc00000) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #03 pc 0007251e /data/app/com.kiefer.llppdrums-hrBNBkrB2E3jVtZWHH_JDw==/base.apk (offset 0xc00000) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #04 pc 00072396 /data/app/com.kiefer.llppdrums-hrBNBkrB2E3jVtZWHH_JDw==/base.apk (offset 0xc00000) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #05 pc 00013b89 /system/lib/libaaudio.so (_ZN6aaudio17AudioStreamLegacy21processCallbackCommonEiPv+201) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #06 pc 000153eb /system/lib/libaaudio.so (_ZN6aaudio16AudioStreamTrack15processCallbackEiPv+59) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #07 pc 000139f7 /system/lib/libaaudio.so (_ZL26AudioStreamLegacycallbackiPvS+39) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #08 pc 00046ea1 /system/lib/libaudioclient.so (_ZN7android10AudioTrack18processAudioBufferEv+2465) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #09 pc 000491df /system/lib/libaudioclient.so (_ZN7android10AudioTrack16AudioTrackThread10threadLoopEv+207) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #10 pc 0001044f /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+207) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #11 pc 0000fca6 /system/lib/libutils.so (_ZN13thread_datat10trampolineEPKS+246) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #12 pc 000709b5 /system/lib/libc.so (_ZL15pthread_startPv+53) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #13 pc 0002050b /system/lib/libc.so (__start_thread+75) 2022-01-29 10:04:59.711 23499-23499/? A/DEBUG: #14 pc 0001eda6 /system/lib/libc.so (bionic_clone+70) 2022-01-29 10:05:00.777 1558-1558/? E//system/bin/tombstoned: Tombstone written to: /data/tombstones//tombstone_05

vustav commented 2 years ago

With how everything is build letting every track have its own instrument just seems easier. This happens while the engine is running btw.

vustav commented 2 years ago

That might have come off as arrogant! Didn't mean that ofc. If there's performance reasons to do it that way I will obviously!

igorski commented 2 years ago

That might have come off as arrogant! Didn't mean that ofc. If there's performance reasons to do it that way I will obviously!

Haha no worries, I don't take offense that easily :) (also if something is up for improvement, I will definitely take all into consideration).

The only performance reason would be related to minimizing memory usage, and to be honest creating instances of instruments, channels and processors isn't allocating that much memory (their runtime impact is a different story, but if you are muting instruments they are basically not doing anything during render, so in your scenario the only impact is slightly more memory usage). I would still argue that the collection of events define what a track/pattern is, but your approach isn't "wrong" either, so its up to your discretion.

Thanks for the stacktrace. I will have some time the coming period to look into this. I will create a small activity that does what you are describing and see if I can reproduce and take it from there.

vustav commented 2 years ago

Tried on my phone today and no crashes as of yet, so this might be the emulator or something else outside of the engine

igorski commented 2 years ago

I have only been able to look into this now, but I struggle to reproduce. Have you experienced the issue since your last reply (regardless of emulator or physical device) ?

vustav commented 2 years ago

No and to be honest I'm not even sure it was muting that caused it to begin with. Lots of things happened and whatever it was is fixed now. Sorry if time was wasted on this.

igorski commented 2 years ago

No worries. We can treat any future occurrance as a new issue.