GSM(3)

πŸ“¦
version 1.0.24 Β· 2 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, centos-stream 9, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0

🌸 GSM(3) β€” the library functions manual, but make it cute 🌸

okay bestie, sit down, hydrate, and let me tell you about GSM(3) β€” a whole manual page living in the Library Functions Manual section. it's giving "vintage codec lore" and honestly? we're obsessed. πŸŽ€


✨ NAME ✨

gsm_create, gsm_destroy, gsm_encode, gsm_decode β€” GSM 06.10 lossy sound compression. that's the whole vibe. compression, but make it speech. πŸ—£οΈπŸ’…


✨ SYNOPSIS ✨

#include "gsm.h"

gsm gsm_create();

void gsm_encode(handle, src, dst)
gsm handle;
gsm_signal src[160];
gsm_frame dst;

int gsm_decode(handle, src, dst)
gsm handle;
gsm_frame src;
gsm_signal dst[160];

void gsm_destroy(handle)
gsm handle;

look at these little K&R-style signatures, they're so retro. no cap. πŸ¦‹


✨ DESCRIPTION ✨

okay so Gsm is a whole implementation of the final draft GSM 06.10 standard for full-rate speech transcoding. yes, that's a real sentence. yes, it's iconic. ✨

  • gsm_create() β€” initializes a gsm pass and hands you back a 'gsm' object. that object is your ✨handle✨, and you'll be passing it to gsm_decode(), gsm_encode() or gsm_destroy() later. main character object, fr fr.
  • gsm_encode() β€” takes an array of 160 13-bit samples (given as gsm_signal's, which are signed integral values of at least 16 bits) and squishes them down into a gsm_frame of 33 bytes. and btw, gsm_frame is a type defined in gsm.h as an array of 33 gsm_bytes. πŸ’–
  • gsm_decode() β€” the reverse bestie. decodes a gsm_frame back into an array of 160 13-bit samples (given as gsm_signals). and honestly? they sound rather like what you handed to gsm_encode() on the other side of the wire. 😭 lowkey magic.
  • gsm_destroy() β€” finishes a gsm pass and frees all storage associated with it. say goodbye, clean up your mess, we love a responsible queen. 🫢

πŸŽ€ Sample format πŸŽ€

here's the scaling that's assumed for input to the algorithm:

   0  1                             11 12
   S..v..v..v..v..v..v..v..v..v..v..v..v..*..*..*

so the tea is: only the top 13 bits get used as a signed input value. ⭐

and the output of gsm_decode() has the three lower bits set to zero. noted. not negotiable. πŸ’…


✨ RETURN VALUE ✨

  • gsm_create() returns an opaque handle object of type gsm, or 0 on error. so like, check it. please. πŸ™ˆ
  • gsm_decode() returns -1 if the frame you passed is invalid, else 0. simple as that. πŸ’€

✨ EXAMPLE ✨

here's the whole thing in action, bestie β€” read it slow, it's actually so satisfying:

#include "gsm.h"

gsm handle;
gsm_frame buf;
gsm_signal sample[160];
int cc, soundfd;

play() {  /* read compressed data from standard input, write to soundfd */

     if (!(handle = gsm_create())) error...
     while (cc = read(0, (char *)buf, sizeof buf)) {
          if (cc != sizeof buf) error...
          if (gsm_decode(handle, buf, sample) < 0) error...
          if (write(soundfd, sample, sizeof sample) != sizeof sample)
               error...
     }
     gsm_destroy(handle);
}

record() {     /* read from soundfd, write compressed to standard output */

     if (!(handle = gsm_create())) error...
     while (cc = read(soundfd, sample, sizeof sample)) {
          if (cc != sizeof sample) error...
          gsm_encode(handle, sample, buf);
          if (write(1, (char *)buf, sizeof buf) != sizeof sample)
               error...
     }
     gsm_destroy(handle);
}

play() and record() are literally the duo of the century. one reads compressed data from standard input and writes to soundfd, the other reads from soundfd and writes compressed to standard output. symmetrical queens. πŸ‘‘πŸŒˆ


πŸ’€ BUGS πŸ’€

found a bug? don't be shy. please direct bug reports to jutta@pobox.com and cabo@tzi.org. they're waiting. be nice. πŸ“


✨ SEE ALSO ✨

go read those too, iykyk. 🧚


and that's the whole page!! this little GSM(3) manual page is filed under the Library Functions Manual section, and it's signed off at the bottom with GSM(3) β€” that's the manual, that's the version, that's the whole era. periodt. πŸ’œβœ¨