roartut(7)

πŸ“¦ version 1.0~beta12, in ubuntu jammy

🌈 bestie, you found roartut(7) 🌈

okay so this whole page is roartut, and it lives in section 7 β€” the System Manager's Manual: RoarAudio. (The header line at the top spells it "RoarAuido" and honestly? we respect the hustle πŸ’….) It's a developer tutorial, it's for you, and we're gonna have a good time.


πŸ’– NAME πŸ’–

roartut β€” RoarAudio sound library developer tutorial. it's giving "learn libroar with me" energy and I am obsessed 🫢

✨ DESCRIPTION ✨

So this tutorial walks you through some basics of working with libroar. We're gonna build a simple application that can play a file, and another one that can play some sines. No cap. πŸŽ€

And listen β€” a LOT more examples are hanging out in RoarAudio's sources, in the roarclients directory. Go look, it's a whole vibe.

This tutorial covers the basics of the so-called VS API. The VS API is an abstract layer sitting on top of the normal API. It's designed to be simple yet powerful, and fr fr, the VS API is all you need for most applications. πŸ’…

  • If you need more control over what you're doing? you gotta use the normal one.
  • If you need only a little of that extra power? you can mix the VS API and the normal API. iconic. no rules. ✨

🎧 PLAYING A FILE 🎧

Playing back a file is an easy task with libroar. The VS API has some special support to play back files in a very simple way, and that's exactly what we're doing here. 🌸

First things first, we need to include the needed header files:

#include <roaraudio.h>  /* libroar */

This main header already includes all we need to use the VS API. one include, everything slays.

Now we can start our main(). We need to declare an object for the VS API, because it's object oriented. This object is what we use to interact with the server and send all our audio data to it:

roar_vs_t * vss;
int err; /* see later */

Next we need to open the connection to the server. The most simple function to do this is roar_vs_new_from_file(3) if we're going to play a file. It takes the following arguments:

  • server address β€” the address of the server. In the general case this should be set to NULL.
  • program name β€” the name of our program. This should be set to some name the user will recognize, like "some App", "some Game". It should not contain the filename of the process like /usr/bin/someapp.bin.
  • file name β€” the name of the file we want to play. In fact this is a URL. The VS API uses the so-called DSTR API to open files, and DSTR API supports local files as well as, for example, HTTP. Examples include: "somefile.ogg", "file:///data/bla.wav", "http://radiostation.org:8000/bla.ogg".
  • error var β€” a pointer to an int used to store the error value in case of error. This can be set to NULL but it should not be. The function roar_vs_strerr(3) can be used to get a readable string of the error.

Our call to roar_vs_new_from_file(3) will look like this:

vss = roar_vs_new_from_file(NULL, "some App", "somefile.ogg", &err);
if ( vss == NULL ) {
 roar_vio_printf(roar_stderr, "Error: Can not connect to server: %s0, roar_vs_strerr(err));
 return 1;
}

Next we need to continuously feed in the data so the server can do the playback. Again, the most simple way is to use roar_vs_run(3).

if ( roar_vs_run(vss, &err) == -1 ) {
 roar_vio_printf(roar_stderr, "Error: can not loop: %s0, roar_vs_strerr(err));
}

This will block until all of the file is played. so sit tight bestie, it's doing its thing. πŸ’œ

After it returned we must close the VS object. This should be done directly after roar_vs_run(3) returned. It's done this way:

if ( roar_vs_close(vss, ROAR_VS_FALSE, &err) == -1 ) {
 roar_vio_printf(roar_stderr, "Error: Can not close connection to server: %s0, roar_vs_strerr(err));
 return 1;
}

After adding some standard main() construct we should have something like this:

//vsfile.c:

#include <roaraudio.h>

int main (void) {
 roar_vs_t * vss;
 int err; /* see later */

 vss = roar_vs_new_from_file(NULL, "some App", "somefile.ogg", &err);
 if ( vss == NULL ) {
  roar_vio_printf(roar_stderr, "Error: Can not connect to server: %s0, roar_vs_strerr(err));
  return 1;
 }

 if ( roar_vs_run(vss, &err) == -1 ) {
  roar_vio_printf(roar_stderr, "Error: can not loop: %s0, roar_vs_strerr(err));
 }

 if ( roar_vs_close(vss, ROAR_VS_FALSE, &err) == -1 ) {
  roar_vio_printf(roar_stderr, "Error: Can not close connection to server: %s0, roar_vs_strerr(err));
  return 1;
 }

 return 0;
}

//ll

To compile and link we can use a command like this one:

cc -o vsfile vsfile.c `roar-config --libs --cflags`

The tool roar-config(1) will keep care for us about all flags needed for libroar. we love a tool that handles the boring parts for us. πŸ‘‘


🌊 PLAYING A SINE 🌊

Now we want to write an application playing a sine for some secs. We start the same way, by including the correct header files:

#include <math.h>       /* sin() */
#include <roaraudio.h>  /* libroar */

After that we need some basic variables with data about the audio we want to play back:

int rate     = ROAR_RATE_DEFAULT;
int bits     = 16;
int channels =  1; /* mono */

Next we need to set the 'codec'. The codec is how the data is encoded. We want PCM as signed ints in the native byte order of our machine.

int codec    = ROAR_CODEC_DEFAULT;

Now we need to store the frequency of our sine:

float freq = 523.2;            /* middle C */
float step = M_PI*2*freq/rate; /* how much time per sample we have to encode ... */

In addition we need some variables to store the current time and the length of time sine:

float t      = 0; /* current time */
float length = 5; /* 5 sec */

Next we need the buffer to hold the data, as well as a variable used to go thru the buffer on generation of data.

int16_t out[1024];
int i;

last we need the VS object again, as well as our error var:

roar_vs_t * vss;
int err;

This time we open the connection to the server using roar_vs_new_playback(3). It's similar to roar_vs_new_from_file(3) but takes some other options:

  • server address β€” same as above.
  • program name β€” same as above.
  • sample rate β€” the number of audio frames per sec.
  • channels β€” the number of samples (one per channel) per audio frame.
  • codec β€” the codec to be used. This is one of ROAR_CODEC_*. In our case we use ROAR_CODEC_DEFAULT, which is signed PCM in CPU native format.
  • bits β€” the number of bits per sample.
  • error var β€” same as above.

The call looks like this:

vss = roar_vs_new_playback(NULL, "vssin", rate, channels, codec, bits, &err);
if ( vss == NULL ) {
 roar_vio_printf(roar_stderr, "Error: Can not connect to server: %s0, roar_vs_strerr(err));
 return 1;
}

Now we want to loop for length seconds:

while (t < 2*M_PI*freq*length) {
}

In this loop we need to calculate our samples:

 for (i = 0; i < (sizeof(out)/sizeof(*out)); i++) {
  out[i] = 32767.f*sin(t);
  t += step;
 }

The sine is multiplyed by 32767 as our amplitude range for 16 bit signed int is from -32768 to +32767.

After we have our current data in out we want to write them to the server:

 if ( roar_vs_write(vss, out, sizeof(out), &err) == -1 ) {
  roar_vio_printf(roar_stderr, "Error: Can not write audio data to server: %s0, roar_vs_strerr(err));
  break;
 }
NOTE: In a real application you may want to check the return value for short writes: those are writes shorter than the requested amount of data to be written. If you got any short writes you should try to rewrite the rest of your buffer later. This is not an error case. πŸ™ˆ

After we are finished with our main loop we have to close the connection to the server. This is done by roar_vs_close(3), as we already done in the file playback example:

if ( roar_vs_close(vss, ROAR_VS_FALSE, &err) == -1 ) {
 roar_vio_printf(roar_stderr, "Error: Can not close connection to server: %s0, roar_vs_strerr(err));
 return 1;
}

After adding some standard main() construct we should have something like this:

//vssin.c:

#include <roaraudio.h>
#include <math.h>

int main (void) {
 roar_vs_t * vss;
 int rate     = ROAR_RATE_DEFAULT;
 int bits     = 16;
 int channels =  1; /* mono */
 int codec    = ROAR_CODEC_DEFAULT;
 float freq = 523.2;            /* middle C */
 float step = M_PI*2*freq/rate; /* how much time per sample we have to encode ... */
 float t      = 0; /* current time */
 float length = 5; /* 5 sec */
 int16_t out[1024];
 size_t i;
 int err;

 vss = roar_vs_new_playback(NULL, "vssin", rate, channels, codec, bits, &err);
 if ( vss == NULL ) {
  roar_vio_printf(roar_stderr, "Error: Can not connect to server: %s0, roar_vs_strerr(err));
  return 1;
 }

 while (t < 2*M_PI*freq*length) {
  for (i = 0; i < (sizeof(out)/sizeof(*out)); i++) {
   out[i] = 32768.f*sin(t);
   t += step;
  }

  if ( roar_vs_write(vss, out, sizeof(out), &err) == -1 ) {
   roar_vio_printf(roar_stderr, "Error: Can not write audio data to server: %s0, roar_vs_strerr(err));
   break;
  }
 }

 if ( roar_vs_close(vss, ROAR_VS_FALSE, &err) == -1 ) {
  roar_vio_printf(roar_stderr, "Error: Can not close connection to server: %s0, roar_vs_strerr(err));
  return 1;
 }

 return 0;
}

//ll

(and yes, the full listing above says 32768.f while the little snippet earlier says 32767.f β€” I am simply reporting what the page says, no notes πŸ’€)

To compile and link we can use a command like this one:

cc -o vssin vssin.c -lm `roar-config --libs --cflags`

We need to use -lm to link the math library for sin(). The tool roar-config(1) will keep care for us about all flags needed for libroar.

Now we should have a working binary vssin playing a sin() for 5 sec. slay. πŸŽ€

Happy hacking! πŸ’–


πŸ‘€ SEE ALSO πŸ‘€

roar-config(1), roarcat(1), libroar(7). RoarAudio(7).


okay and that's the whole page bestie πŸ¦‹ β€” it came to you from RoarAudio, dated November 2010, and it's been serving ever since. go make something that beeps. πŸ’…βœ¨

πŸ“¦ where this page comes from