Page 1 of 1

How to play sound from C?

PostPosted: 05 Nov 2021, 21:46
by PeterX
Hi, fellow developers!

How do I play a sound(file) from a C console program on Linux?

I have a simple textonly program that should play a sound file. (No synchronizing, no music, no reacting to game status.)

I found this, but it is overly complicated and long:
https://stackoverflow.com/questions/265 ... c-on-linux

EDIT: Ok, I could use
{l Code}: {l Select All Code}
system("paplay sound.wav");
But that seems unelegant to me.
And if I use SDL, I can't use printf() anymore?

Greetings
Peter

Re: How to play sound from C?

PostPosted: 06 Nov 2021, 01:25
by dulsi
libao, mentioned in your link, looks pretty easy. It is available on Fedora.

Re: How to play sound from C?

PostPosted: 06 Nov 2021, 05:10
by PeterX
Sorry, I didn't see that. And thanks, at first glance that seems to be exactly what I was looking for. And additionally it is quite portable!

Greetings
Peter

Re: How to play sound from C?

PostPosted: 06 Nov 2021, 14:00
by bzt
PeterX {l Wrote}:How do I play a sound(file) from a C console program on Linux?
Back in the old days when people were stupid and dumb so couldn't understand how magnificent pulseaudio is, there was a /dev/dsp device file. You could just write the raw data into that file. Like this:
{l Code}: {l Select All Code}
cat sound.wav > /dev/dsp
If your distro ships a kernel that provides the dsp device file, you can still do this.

Sadly these days /dev/dsp is missing, and you must use a library which hides OSS / ALSA / whatever kernel interface details, libao is good. I'd also point out that SDL can handle audio natively just fine with the low-level SDL_OpenAudioDevice interface. The reason why people don't use this directly is because it can only play one audio stream (which is exactly what you want).

For playing multiple sounds at once, one have to mix those streams into a single stream first. Basically that's all what SDL_mixer does, but that library's source is relatively complicated and complex. Here's a simple mixer library that does that too, but it is useful to learn how to use SDL's low-level audio interface (NOTE: since this is the simplest possible mixer with the simplest code base, its features are very limited, but, single C file, easy to learn from it, and you'll only need one sound anyway).

PeterX {l Wrote}:I have a simple textonly program that should play a sound file. (No synchronizing, no music, no reacting to game status.)
That would be as simple as
{l Code}: {l Select All Code}
playSound("sound.wav", SDL_MIX_MAXVOLUME);
Without a mixer library, using only SDL's low-level interface, see this gist. It plays an ogg file (with stb_vorbis), but you could fill up the audiodata[] buffer using the native SDL_LoadWav() function too if you only need .wav sounds.

PeterX {l Wrote}:And if I use SDL, I can't use printf() anymore?
Nope, you can. Here's an example console app that plays some music and sounds from command line, it has no issues with printf at all. Try it out, add some printf in that code. The gist link above also contains some printf calls.

Cheers,
bzt

Re: How to play sound from C?

PostPosted: 06 Nov 2021, 18:53
by smcameron
Portaudio is not too bad. http://www.portaudio.com/ though you do have to write your own mixer code.

I use it in Space Nerds in Space with a little library I built on top of it to make things easier + for some special crap I needed for voice chat.

header file: https://github.com/smcameron/space-nerd ... wviaudio.h
implementation: https://github.com/smcameron/space-nerd ... wviaudio.c

Re: How to play sound from C?

PostPosted: 07 Nov 2021, 14:08
by bzt
So to summarize, you have to use some kind of library, but as a silver lining, that opens up the way for portability.
Here are some useful links for audio programming (I've tried to link tutorials with example code for each library. Some examples are C++, but the library works with C no probs):
  • PortAudio, no mixer, portable, relatively simple (additional ogg mixer example)
  • SDL, no mixer, portable, simple to use (additional mixer libraries SDL_mixer, Simple-SDL2-Audio)
  • libao, has a mixer, portable, simple to use (probably the most portable of these)
  • libasound2, has a mixer, semi-portable (built on ALSA, so: Linux, Android, some BSDs, but no Win), quite complex API
  • libpulse, has a mixer, portable, very complex API and complex running environment (but provides a simplified API too)
  • OpenAL, has a mixer, portable, very complex API, proprietary (but there's an Open Source software-only implementation too)
Cheers,
bzt

Re: How to play sound from C?

PostPosted: 09 Nov 2021, 18:41
by drummyfish
Hey, I just quickly smashed together this code that plays any array of bytes, it isn't using any library, just the aplay utility:

{l Code}: {l Select All Code}
#include <stdio.h>
#include <stdlib.h>
 
#define SAMPLES 1024
#define N (SAMPLES * 4 + 18)
 
char command[N] = "echo -e \'\' | aplay";

char valToHex(int v)
{
  return (v < 10 ? '0' : ('a' - 10)) + v;
}

int main(void)
{
  for (int i = 0; i < 10; ++i)
    command[N - i] = command[18 - i];

  char *p = command + 9;

  for (int i = 0; i < SAMPLES; ++i)
  {
    unsigned char val = i;

    *p = '\\';
    p++;
    *p = 'x';
    p++;
    *p = valToHex(val / 16);
    p++;
    *p = valToHex(val % 16);
    p++;
  }

  puts(command);
  system(command);

  return 0;
}

Re: How to play sound from C?

PostPosted: 09 Nov 2021, 22:06
by bzt
drummyfish {l Wrote}:Hey, I just quickly smashed together this code that plays any array of bytes, it isn't using any library, just the aplay utility:
This technically isn't "playing sound from C", rather just executing a 3rd party tool (which might not be installed). That, and you have missed this sentence in the OP:
PeterX {l Wrote}:Ok, I could use [...] system [...] But that seems unelegant to me.
So solutions which use "system()" aren't the ones he's after.

Cheers,
bzt

Re: How to play sound from C?

PostPosted: 10 Nov 2021, 15:51
by drummyfish
C can't play sounds, you always have to use 3rd party tools, libraries are completely the same in this -- a library or it's dependency may also be missing from the user's system.

Re: How to play sound from C?

PostPosted: 10 Nov 2021, 16:21
by PeterX
drummyfish {l Wrote}:C can't play sounds, you always have to use 3rd party tools, libraries are completely the same in this -- a library or it's dependency may also be missing from the user's system.

You are right, but I think it's okay to use libraries, I just want to be careful to not pull in dozens of obscure and bloated libraries. And it's still C, just with a library.

Thanks to everybody for the suggestions. I think, I'll use libao. It's portable and it seems to be easy to use.

Greetings
Peter

Re: How to play sound from C?

PostPosted: 10 Nov 2021, 18:26
by drummyfish
Yeah, the /dev/esp would be the best, most beautiful way, the Unix way, but sometimes we just need to adapt to current systems I guess.