Why Same code of SDL C++ works fine in windows but in Linux it is producing delay

Hi Everyone,

I am new in SDL2 . I want to play a sound file (sound.wav) when I push the button on my screen . I pick SDL lib for that task . It works fine on windows but on linux it is producing delay . I mean when I pushing key on my screen it plays the file after some nano seconds . But on windows it works very decently . Please anyone help me for that .

Anyone please answer me .

It would help if you could provide some example code.
From what you say id expect that you only load the file when the button is pressed instead from preloading it at some point and only playing it, but without any code we cant really help you.

~mkalte

@mkalte Please Check

if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_EVENTS) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, “Couldn’t initialize SDL: %s\n”, SDL_GetError());
return (1);
}

SDL_LoadWAV(“sample.wav”, &audioSpec, &soundData, &uSoundLen);

device = SDL_OpenAudioDevice(NULL, SDL_FALSE, &audioSpec, NULL, 0);
if (!device) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, “Couldn’t open audio: %s\n”, SDL_GetError());
SDL_FreeWAV(soundData);
Quit(2);
}
SDL_ClearQueuedAudio(device);
SDL_PauseAudioDevice(device, SDL_FALSE);

SDL_Delay(300);

Something is definitely missing there. Are you running all of this when the button is clicked? Because then, there is your problem. You should init SDL together with your application, and terminate it when your application quits. Never on the main loop, during something expected to be interactive. Also, why is there a delay at the end? Why pause the device?

You might have misunderstood the basics of SDL. It is also worth noting that pure SDL_Audio* stuff is a very low level API. It has low latency and allows you to play a constant stream of audio data, but nothing more. I would urge you to look at an SDL_mixer example such as this: https://gist.github.com/armornick/3497064

Then, the only thing you would have to do on button click is Mix_PlayChannel(…). All the rest, is library initialization, and later, termination :slight_smile:

@cmakeshift Thank you for your quick reply . Delay is used for wait to play audio file . Which link you sent I will see that and try to understand it . Thank you !!:blush:

@cmakeshift : https://gist.github.com/armornick/3497064 That link code have two sources of audio one is WAV_PATH and second is MUS_PATH . I am not getting how it is fit for me as per my requirement . Can you please little bit elaborate . it would be helpful for me .

As you can see in the first lines of the source file, MUS_PATH is just a define to a file path containing a music file. This example plays music as well as an audio effect. Since all you need is to play a sound, you could just ignore those parts about music loading and playback.

Just to clarify, you say that the sound must play when a button is pressed on the screen. What are you using to make the button? By that I mean, are you using some framework, or pure SDL? Do you have a screenshot of the program? You could post the whole thing on pastebin and I could take a look.

@cmakeshift : thanks for quick reply !! No I am not using SDL for design a button . I am using SDL just for play audio when I push the button . But audio is playing with little delay after pushing the button .

I just commented that stuff which is using for MUS_PATH . But I am unable to play audio.wav file with this example .

Thank you

@cmakeshift : I am able to play wav file in my small test case using that link which you mentioned above . But I putted while (1) at the end of code just for playback . In code you have used Mix_PlayingMusic , Is there any other function related for Mix_PlayChannel .

Oh no, that is not my code.It’s just a sample I got from the web, that is very representative of basic usage of SDL_mixer.

Did you put the whole thing verbatim on the button event handler? It sounds to me that you are dismantling SDL before there was enough time for the audio to play. In the example, the program would run for as long as the music was playing. Remember, Mix_PlayChannel(…) does not block, the audio micer does its thing on a separate thread.

What you have to do: everything from SDL_Init up to and including Mix_LoadWav, you do as the first thing in your main function. That starts up SDL for the entirety of your application, and keeps the sound loaded in memory. When your button is clicked, call Mix_PlayChannel as you were doing before.

You can probably get by without shutting down SDL when your program exits. Buf if you want to do it, as the last thing before returning from main (or calling exit), call Mix_FreeChunk and Mix_CloseAudio.

@cmakeshift : Thank you so much for that information . Yes I will put SDL_init and Mix_LoadWav inside my applications main function and will call the Mix_PlayChannel from my button handler . I will return back after that experiment .

I want to know one more thing : As you said Mix_PlayChannel is a non-blocking function and I am not using the Mix_PlayingMusic which makes block until the the end of wav file . How I can block till file play . Is there any useful function in SDL because before that I was using SDL_Delay , I don’t want to use it .

Yes, which is why I would expect it to be more suitable for the OP’s task than SDL_mixer. I would suggest using the most basic core SDL2 functions: SDL_LoadWAV(), SDL_OpenAudioDevice(), SDL_QueueAudio() and SDL_PauseAudioDevice().

To minimise latency, ensure that the WAV file uses a format that the hardware audio backend supports. For example if the hardware runs at 48 kHz sampling rate, use a 48 kHz-sampled WAV file; if it runs at 44.1 kHz, use a 44.1 kHz file. Converting from one sampling rate to another is very likely to increase latency.

To minimise latency, ensure that the WAV file uses a format that the hardware audio backend supports. For example if the hardware runs at 48 kHz sampling rate, use a 48 kHz-sampled WAV file; if it runs at 44.1 kHz, use a 44.1 kHz file. Converting from one sampling rate to another is very likely to increase latency.

This is the thing I’d worry about right here. SDL_QueueAudio() expects you to queue audio in the format obtained when the device was opened. So that would imply checking if the format in which the device was opened is the same as the format that was desired, and if needed, make use of SDL_BuildAudioCVT() and SDL_ConvertAudio().

I believe that is fine if you are implementing an output backend for a mixer or a player for a single stream, but that is still more complicated than using SDL_mixer. For the OP’s purposes, SDL_mixer would do everything just fine and much more easily. The problems with delay (300ms!) are certainly unrelated to SDL_mixer. That was related to initializing the audio subsystem in the wrong place.

How I can block till file play . Is there any useful function in SDL because before that I was using SDL_Delay , I don’t want to use it .

Out of curiosity, why would you want to do that? Blocking the main thread in a GUI application is not good practice. But anyway, here is a way to do it:

You can retrieve the channel being used as such: int usedCh = Mix_PlayChannel(...); And then, to block until the sample is done playing, just use while(Mix_Playing(usedCh)) {}. Although keep in mind that busy-waiting like that is pretty ugly.

@cmakeshift : Iwas waiting for your reply !! Thank you for that information .

 why would you want to do that? Blocking the main thread in a GUI application is not good practice. But anyway, here is a way to do it

Actually without blocking the sound it not played . function is going exit without playing the audio , But while(Mix_Playing(usedCh)) {}. working fine in test case . I did not put it in my application but right now I am going to merge that code with my application .

I we play the file without using that “while loop” (which I am using for blocking purpose) .

Thank you !!

@cmakeshift , I integrate that SDL_mixer in my application that working fine as per delay perspective and I want to say you thank you for that .

But there have one more problem , when I am pressing same key very fast for multiple times it is producing long sound but I want it play just once at the last press . Is that possible ?

I want it play just once at the last press . Is that possible ?

Well, this is very specific to your program. Which I know nothing about. So, I cant’ help with that., sorry :frowning:

@cmakeshift : You don’t need to say sorry . Thank you so much for that help . I have just basic question about what I was doing and what I am doing now ?

>     Is SDL_mixer better always for single audio playback as compare to SDL_LoadWAV,SDL_OpenAudioDevice, SDL_FreeWAV which I was doing before that .

>     Can I load file in memory using SDL_mixer (I mean buffer like SDL_LoadWAV(“sample.wav”, &audioSpec, &soundData, &uSoundLen);) 

>     Is that functions parameter makes any impact on SDL audio playback performance > Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ).

>     Last one , @rtrussell said I need to check sampling rate , Is it really makes any impact on audio playback with SDL . 

Thank you !! :slight_smile:

The OP said “it plays the file after some nano seconds” so my assumption is that the latency that he is concerned about is quite short (not hundreds of milliseconds) and could be a result of using SDL_mixer.

More easily, open the device with the format of the file (if it’s a format the device is capable of). The only way to keep latency as low as possible is to avoid any ‘real time’ format conversion.

The OP said “ it plays the file after some nano seconds ” so my assumption is that the latency that he is concerned about is quite short (not hundreds of milliseconds) and could be a result of using SDL_mixer.

Fair enough, I had that wrong number in my mind because of the SDL_Delay() up there in the OP’s code. My bad. Then again, I very much doubt a delay of “some nanoseconds” would be measurable, let alone avoidable.

More easily, open the device with the format of the file (if it’s a format the device is capable of). The only way to keep latency as low as possible is to avoid any ‘real time’ format conversion.

Sure, if you know your runtime environment and can control the format of the file, this is a good solution. And avoids a dependency. I suggested SDL_mixer because it is a nice, well-rounded solution that satisfies the needs of most people. If the latency provided by SDL_mixer is not good enough for something, it is usually a very specialized thing. Which brings us to the following:

The real issue I am having with this thread is that the OP does not seem to know what needs to be accomplished, and does not paint a good picture for us to arrive at a good solution. So, @cadsys, what is it that your application does? What is it? Why does it need to play the sound? What is the framework or library you re using to create the interface? First you said button, afterwards you said key. So it is a keyboard key, then? Is it all done with SDL? Without you better explaining what you want to accomplish, and why, advice based on speculation can only go so far.

Please, help us help you :slight_smile: