[BUG]:Crash when play from stream, stream is generate sine wave buffer
Flutter Sound Version : flutter_sound: ^9.16.3
-
FULL or LITE flavor ?
-
Important: Result of the command :
flutter pub deps | grep flutter_sound
Severity
-
Crash ? Yes
-
Result is not what expected ?
-
Cannot build my App ? No
-
Minor issue ?
Platforms you faced the error
-
iOS ? Yes
-
Android ?
-
Flutter Web ?
-
Emulator ?
-
Real device ? Yes
Describe the bug A clear and concise description of what the bug is.
To Reproduce Steps to reproduce the behavior:
- Generate sine wave buffer
- Play from stream
- Wait...
- See error
Logs!!!!
(This is very important. Most of the time we cannot do anything if we do not have information on your bug).
To activate the logs, you must instantiate your modules with the Log Level set to Level.debug :
final FlutterSoundPlayer _player = FlutterSoundPlayer(logLevel: Level.error);
Future<void> startPlaying() async {
try {
print('_player isOpen:${_player.isOpen()}');
await _player.startPlayerFromStream(
codec: Codec.pcm16,
sampleRate: _sampleRate.toInt(), // _sampleRate = 48000;
bufferSize: 20480,
numChannels: 1,
whenFinished: () {
FlutterSoundPlayer().logger.i("FINISHED!");
}
);
_isPlaying = true;
// 定期生成超声波数据并播放
_playbackTimer =
Timer.periodic(Duration(milliseconds: 100), (timer) async {
if (_isPlaying) {
Uint8List audioData = generateSineWaveBuffer(100);
print('audioData length:${audioData.length}');
await _player.feedFromStream(audioData);
} else {
timer.cancel();
}
});
} catch (e) {
_player.logger.e('startPlaying error: $e');
_isPlaying = false;
}
}
Uint8List generateSineWaveBuffer(int durationMs) {
int frameCount = ((_sampleRate * durationMs) / 1000).toInt();
Float32List buffer = Float32List(frameCount);
double amplitude = 1.0; // [-1, 1]
for (int i = 0; i < frameCount; i++) {
buffer[i] = amplitude * sin(_phase);
_phase += (2 * pi * _frequency) / _sampleRate; // _frequency = 18000;
if (_phase >= 2 * pi) {
_phase -= 2 * pi;
}
}
return Uint8List.view(buffer.buffer);
}
See this Assertion failed: (waitingBlock == nil), function -[AudioEngine feed:], file FlautoPlayerEngine.mm, line 372.
- thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x000000020eb8f198 libsystem_kernel.dylib
__pthread_kill + 8 libsystem_kernel.dylib: -> 0x20eb8f198 <+8>: b.lo 0x20eb8f1b4 ; <+36> 0x20eb8f19c <+12>: stp x29, x30, [sp, #-0x10]! 0x20eb8f1a0 <+16>: mov x29, sp 0x20eb8f1a4 <+20>: bl 0x20eb8ab70 ; cerror_nocancel Target 0: (Runner) stopped.
The problem is that you feed the iOS driver too quickly. You have two choices:
- play with back pressure (flow control)
- Play without back pressure (you will feed the flutter sound stream)
the big issue for you is that you send data to the driver every 100ms, without knowing if the driver is ready to accept the data and if the previous buffer has been played.
i think that you should not generate data on a timer, but react on the event "needSomeData". Look to the example "play from stream with back pressure"
Hi @Larpoux I'm facing the same kind of problem where feedFromStream takes forever, and never ends on Ios when there's some type of interruptions. but when I put a timeout on feedFromStream's execution, there is some scenarios where it crashes, do you have any idea on how to fix this? How long feedFromStream is suppose to take to execute?