C [C] Writing to the soundcard

I want to write a program that sends a sine wave to a soundcard output.

I was hoping to avoid installing SDL or something like that - I'd just like to access /dev/dsp directly and maybe use ioctl(2) calls to query the soundcard for the bitrate etc.

I found some documentation here and read sound(4), and the header file soundcard.h is missing.

Does anybody know if I have to install a particular library? I could be searching wrong but it seems quite lightly documented.
 
Check the OSS API reference at [1] and the sample programs at [2]. They contain an example sine generator.

Though IMHO there is nothing wrong with using the audio API from SDL2. It's actually quite good, easier to use, and better documented.

EDIT: Ok I didn't see you already linked to [1]. Linking or installing an extra library is not necessary. soundcard.h can be found at /usr/include/sys/soundcard.h on FreeBSD.

[1] http://manuals.opensound.com/developer/programming.html
[2] http://manuals.opensound.com/developer/sample_programs.html
 
It's all part of the base OS. So there's nothing to install.

Code:
dice@armitage:~ % ll /usr/include/sys/soundcard.h
-r--r--r--  1 root  wheel  71098 Mar 12  2014 /usr/include/sys/soundcard.h
 
A few years ago a played around with the dsp device just for curiosity and I got it to play a sinus in C:
Code:
// compile: clang dsp-sinus.c -lm -o dsp-sinus
//
// usage:   dsp-sinus [freq] [level]      (default freq. is 1000 Hz and default level is 0.5)
// example: dsp-sinus 5000 0.75

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>


#define pi2 6.2831853071795865

int main(int argc, const char *argv[])
{
   int dsp = open("/dev/dsp0", O_RDWR);
   if (dsp != -1)
   {
      unsigned param;

      param = AFMT_S32_LE;
      if (ioctl(dsp, SNDCTL_DSP_SETFMT, &param) == -1 || param != AFMT_S32_LE)
      {
         close(dsp);
         printf("Error setting the input format (0x%X)\n", param);
         return -1;
      }

      param = 2;
      if (ioctl(dsp, SNDCTL_DSP_CHANNELS, &param) == -1 || param != 2)
      {
         close(dsp);
         printf("Error setting stereo output %d\n", param);
         return -2;
      }

      // force a sampling rate of 48 kHz
      param = 48000;
      if (ioctl(dsp, SNDCTL_DSP_SPEED, &param) != -1)
         printf("Sampling rate set to: %d Hz\n", param);
      else
      {
         close(dsp);
         printf("Error setting sampling rate %d\n", param);
         return -3;
      }

      // 24bit stereo sinus generation; default frequency = 1000 Hz, default level = 0.5 (half scale)
      int    i, L, R;
      double dt = 1.0/param;
      double f  = (argc > 1) ? strtod(argv[1], NULL) : 1000.0;
      double l  = (argc > 2) ? strtod(argv[2], NULL) : 0.5;

      if (f < 0.0 || 20000.0 < f)
         f = 1000.0;

      if (l < 0.0 || 1.0 < l)
         l = 0.5;

      for (i = 0; i < 30*param; i++)
      {
         L = R = lround(l*0x7FFFFF*sin(pi2*f * i*dt)) << 8;
         write(dsp, &L, 4);
         write(dsp, &R, 4);
      }

      close(dsp);
   }

   return 0;
}
This still does compile, however, I cannot tell if this still produces a sound on the output, since I cannot easily connect any speakers in the moment.


PS: Corrected missing semicolon on line 58, as reported by Beastie (s. below).
 
This still does compile, however, I cannot tell if this still produces a sound on the output, since I cannot easily connect any speakers in the moment.
It still generates a nice sinewave. But you're missing a semicolon terminator on line 58. ;)
 
Thanks Obsignia, that's saved me some trouble. For some reason I'd assumed the soundcard was 16bit not 24!
 
Back
Top