[LAD] starting out with tux audio

Jens M Andreasen jens.andreasen at comhem.se
Sun Jun 15 16:10:01 UTC 2008


On Sun, 2008-06-15 at 09:38 +0530, AlgoMantra wrote:
>         Whoo, that text is from 2000, when Bill Clinton was president.
>         A lot
>         has changed since then.
> 
> 
> ....but we still play musical instruments that are 5000 years old.
> Some things
> don't have to change much to survive. Lets just say I have a
> retro-fetish...
> 

Uhmm ... But if you want to do raw sinewaves big time, you'll really
need another approach if you are not to run out of CPU. That piece of
code you linked to is in desperate need of an update, so that it will
auto-vectorize and so that we can get rid of the expensive call to
sin(). The following should do just about the same but without mathlib
and generally accellerated by some insane percentage:

-8<-- sound.c
-----------------------------------------------------------

// Compile with for example
// gcc4.3 -O3 -msse  -ftree-vectorize -o sound sound.c

#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>


#define PI 3.14159f

/* Inverse of the odd factorials (n!) 1 - 9
 */
#define IF_1 (1.f)
#define IF_3 (1.f/6.f)
#define IF_5 (1.f/120.f)
#define IF_7 (1.f/5040.f) 
#define IF_9 (1.f/362880.f)

/* -------------------------------------
 * 16 bit Taylor approximation of sin()
 * ------------------------------------ */

float tsin(float x) 
{ 
  float x2 = x*x;
  float rt = IF_9;

  rt *= x2;
  rt -= IF_7;
  rt *= x2; 
  rt += IF_5;
  rt *= x2;
  rt -= IF_3;
  rt *= x2; 
  rt += IF_1;
  rt *= x;

  return rt;
}

int main(void)
{
  unsigned short int wave[44100*5]; /* our wavetable */
  int i,j; /* two counters */
  int out; /* audio out */
  /* open /dev/dsp for write only */
  out = open("/dev/dsp",O_WRONLY);
  /* now we use ioctl to set audio quality */
  i=16; /* 16 bits */
  ioctl(out,SOUND_PCM_WRITE_BITS,&i);
  i=1;  /* 1 channel */
  ioctl(out,SOUND_PCM_WRITE_CHANNELS,&i);
  i=44100; /* 44.1KHz */
  ioctl(out,SOUND_PCM_WRITE_RATE,&i);

 

#define OSC 4

  float x[OSC] = {0,0,0,0};
  float y[OSC] = {1,1,1,1};
  float w[OSC] = {220, 277,330,440};
  float a[OSC] = {8000,7000,6000,5000};
  float r[OSC];

  for (i = 0; i < OSC;++i)
    w[i] = tsin(w[i]*2*PI/44100);

  for(i = 0;i < (44100*5); ++i)
    {
      for(j=0;j < OSC; ++j)
	{
	  x[j] -= w[j] * y[j];
	  y[j] += w[j] * x[j];
	  r[j]  = x[j] * a[j];
	}
      wave[i] = r[0] + r[1] + r[2] + r[3];
    }



  /* now we write the wavetable to /dev/dsp
   * as though writing to a simple file
   * we'll loop for 5 seconds of sheer joy
   */

  write(out, wave, sizeof(wave));
  close(out); /* close /dev/dsp ! */
  return 0; /* satisfy gcc */
}






More information about the Linux-audio-dev mailing list