Flutter Audioplayers delay - flutter

I'm coding a small game with the Flutter Framework.
I'm using audioplayers for the Sounds.
It works fine like this, when calling it for example 2 times a second.
But whenn I call it more than 5 times and again in the next second at some point the sound has like a delay and then after a second or so all the sounds play at once :) That sounds weired.
I also tested the audioplayers example from github on my iphone. Repeating the sounds in low frequency is ok, but when I repeat clicking the button as fast as possible at some point it gets some delay and the same thing is happening.
Is there some way to stop the previous Sound before and then playing the next one or isnt this possible?
Or is there some other Idea how to deal with the sounds?
This is how I use it:
AudioCache upgradeSound = new AudioCache();
void playUpgradeSound() {
_playUpgradeSound(upgradeSound);
}
void _playUpgradeSound(AudioCache ac) async{
await ac.play('audio/upgr.mp3');
}
Thank you very much in advance

I solve similar problem by having singleton class, and after first play I can get the state, and I can stop previous play.
class Audio {
static final playerCache = AudioCache();
static AudioPlayer audioPlayer;
static void play(String audioName) async {
audioPlayer = await playerCache.play('$audioName.mp3');
}
static void stop() {
audioPlayer.stop();
}
}
...
child: IconButton(
onPressed: () {
try {
if (Audio.audioPlayer.state ==
AudioPlayerState.PLAYING) {
Audio.stop();
} else {
Audio.play('bid');
}
} catch (e) {
Audio.play('bid');
}
},
...

There is a line of code in its own documentation.
To use the low latency API, better for gaming sounds, use:
AudioPlayer audioPlayer = AudioPlayer(mode: PlayerMode.LOW_LATENCY);
In this mode the backend won't fire any duration or position updates. Also, it is not possible to use the seek method to set the audio a specific position. This mode is also not available on web.
I hope it is useful.

Related

CameraController not starting video recording instantly Flutter

I am trying to play a beep sound with vibration before starting video recording. However, there is a delay for _cameraController.startVideoRecording()
to start video recording and this delay is not constant. Each time I try recording the delay is different.
How can I do this in a way that recording starts instantly after the beep sound finishes.
my code:
Future _handleRecording() async {
try {
await _audioCache.play(_soundPath);
Vibration.vibrate(duration: 350);
await _cameraController.startVideoRecording();
} catch (e) {
throw (e);
}
}
I am using camera: ^0.8.1+7 dependency the CameraController class.
The problem here is you are calling the startVideoRecording after initiating the play function
You have two options since your audio duration is fixed :
First one is to surround you startVideoRecording with delay like that:
Future.delay(Duration(seconds:"You audio time"),(){
await _cameraController.startVideoRecording();
} catch (e) {
throw (e);
}
});
and the second one is to check when play finish then call startVideoRecording

Flutter: AudioPlayers how to stop multiple sounds at once?

I use AudioPlayers package.
I have Button1 that plays the sounds. (Code Below)
AudioCache playerCache = new AudioCache(); // you already initialized this
AudioPlayer player = new AudioPlayer();
void _playFile(String yol, String name) async {
player = await playerCache.play(yol);
}
But there is another button which calling "Button2" has to stop all of the sounds at once. I wrote this :
void cancelPlay() {
print("stop");
playSounds.removeRange(0, playSounds.length);
player.stop();
player.stop();
}
However , when user click Button2 , it only stops the last sound. I want that to stop all of the sounds. How to do that ?
I guess The problem is, that every time i call _playFile() (press Button 1) a new instance of AudioPlayer is assigned to the player variable, hence in cancelPlay() the player variable holds only the last instance of AudiPlayer.
How can i do to store the instances in a list.
Thank you.
make a variable
List<AudioPlayer> audioPlayers = [];
every time you tap button1, add new audioPlayer
audioPlayers.add(new AudioPlayer());
then when you tap on button2, do something like this to stop every audioPlayer
audioPlayers.forEach((audioPlayer) => audioPlayer.stop());
or even better would be function to toggle the AudioPlaybackState of audioPlayers, so if they are paused then play and vice versa. Ofcourse this example is based on presumption that every audioPlayer controller has same AudioPlaybackState as first:
void toggleAudioPlayers() {
if (audioPlayers.first.playbackState == AudioPlaybackState.playing) {
audioPlayers.forEach((audioPlayer) => audioPlayer.stop());
} else {
audioPlayers.forEach((audioPlayer) => audioPlayer.play());
}
}
Dont forget to dispose every audioPlayer controller to prevent memory leaks:
audioPlayers.forEach((audioPlayer) => audioPlayer.dispose());
AudioPlayer.players.forEach((key, value) {
value.stop();
});
when you play another audio you need to call this code before

Flutter - Stop audio playback from recorded video in the background

Essentially the app is like snapchat. I take pics and reset back to camera mode, the issue comes when I record video and reset, it goes back to camera mode but the audio form the video keeps playing in the background. The functions are somwhat exactly like the camera doc, with a few addition to reset the camera.
I added this:
_reset() {
if (mounted)
setState(() {
if (this._didCapture) {
this._didCapture = false;
this._isRecording = false;
this._isPosting = false;
this._file = File('');
this._fileType = null;
this._captions.clear();
this._textEditingControllers.clear();
this._videoController = null;
this._videoPlayerListener = null;
}
});
}
It works just fine but the audio in the background is still on. Also wondering if the video/picture is saved on the phone, which I don't want to...
i had been looking for a similar answer, but i didn´t find it. You could try to stop it adding this to your function:
this._controller.setVolume(0.0);
that´s what i did in my app

Unity: LoadScene does not work when fired from timer

in my game, when the player dies, a dying sound is played and once the sound is over, the scene is supposed to be reloaded when the user still has enough lives.
Before I had the sound, the play died instantly upon calling the death() function:
public static void Death()
{
AddCoinScript.coinCounter = 0;
LivesScript.livesCounter--;
if (LivesScript.livesCounter > -1)//to get 0 live
{
Debug.Log("TIMER");
var currentScene = SceneManager.GetActiveScene();
SceneManager.LoadScene(currentScene.name);
}
else
{
//TO DO GameOver
}
}
This worked like a charm.
But now I added a death sound to it. Unfortunately, unity doesnt provide an event handler for when the sound is done playing (I want the scene to be reloaded not instantly anymore, but after the death sound is done playing), so I have decided to take it upon myself to just build a timer. The timer fires right after the death sound is over. This is what this function has become:
public static void Death()
{
AddCoinScript.coinCounter = 0;
LivesScript.livesCounter--;
PlayDeathSound();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = aSDeath.clip.length * 1000;
timer.Start();
timer.Elapsed += delegate
{
timer.Stop();
if (LivesScript.livesCounter > -1)//to get 0 live
{
Debug.Log("TIMER");
var currentScene = SceneManager.GetActiveScene();
SceneManager.LoadScene(currentScene.name);
}
else
{
//TO DO GameOver
}
};
}
As you can see, to make sure the timer REALLY fires, I set up a "debug.Log("TIMER")" to see, if it really works. And guess what: it does. The debug now shows "TIMER" in its console. But you know what doesnt work anymore? The two lines of code right beneath that.
var currentScene = SceneManager.GetActiveScene();
SceneManager.LoadScene(currentScene.name);
It's the same exact lines that worked just before - but when fired from the timer, they just get ignored? How is this even possible?
When I change it all back, it works again. Only when the timer fires the two lines, they get ignored.
This is totally odd or am I missing something? Thank you!
Okay I am not an expert on C# and delegate but apparently it creates a separate thread and you can only use SceneManager.GetActiveScene on main thread.
Since i am not so sure about delegate i will offer an easier solution. You can use a coroutine since you know how much you have to wait like this:
public void Death()
{
StartCoroutine(DeathCoroutine());
}
IEnumerator DeathCoroutine()
{
AddCoinScript.coinCounter = 0;
LivesScript.livesCounter--;
PlayDeathSound();
// wait for duration of the clip than continue executing rest of the code
yield return new WaitForSeconds(aSDeath.clip.length);
if (LivesScript.livesCounter > -1)//to get 0 live
{
Debug.Log("TIMER");
var currentScene = SceneManager.GetActiveScene();
SceneManager.LoadScene(currentScene.name);
}
else
{
//TO DO GameOver
}
}
What about using a coroutine ? You just start it when the player dies, and yield while your sound is still playing.

html5 audio tag playing audio when it is load audio

i have html5 audio player like play, pause, stop buttons.
function onUpdate()
{
var isPlaying = (!getAudioElement().paused);
document.getElementById("playerplay").style.display = (isPlaying)?"none":"block";
document.getElementById("playerpause").style.display = (isPlaying)?"block":"none";
};
function getAudioElement()
{
return document.getElementById("id_audio_element");
}
function play() {
getAudioElement().play();
onUpdate();
}
function pause() {
getAudioElement().pause();
onUpdate();
}
function stop() {
getAudioElement().pause();
getAudioElement().currentTime=0;
onUpdate();
getAudioElement().load();
}
And audio tag:
<audio id="id_audio_element" onended="onUpdate();load();"><source src="105.ogg" type="audio/ogg"></audio>
it works all on browsers perfectly, exept iPhone and iPad's Safari and Chrome. When I call load() , audio starts playing, although I don't call play().
Anybody has a solution? Thanks!
If the source is not changing, there is no need to call load(). If it is changing, try calling pause() after it loads.