Re: [linux-audio-dev] EVO 0.0.5 released , resampling (interpolation) support added

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] EVO 0.0.5 released , resampling (interpolation) support added
From: Paul Barton-Davis (pbd_AT_Op.Net)
Date: Tue Sep 19 2000 - 17:56:50 EEST


OK, first, here is the original "oscillates", written by an unknown
author, with an RT modification by me.

----------------------------------------------------------------------

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

#define BUFSIZE 8192
#define SR_RATE 44100
#define NBUFS 4
#define WTABLESIZE 1000
#define FREQ 278.0
#define NOSCILS 1000
#define PI 3.1415926

/*-------------------------------------------*/

#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>

int goRT (void)

{
    int retval = 1;

    /* Configures calling process to be as real-time as Linux currently
       allows. The process will run whenever it is ready, and no page
       faults will ever occur, because its entire memory map is wired
       down.

       Removes all root priviledges after being called.
    */

    seteuid (0);

    if (geteuid () == 0) {

        struct sched_param sp;

        memset (&sp, 0, sizeof sp);
        sp.sched_priority = 10;

        if (sched_setscheduler (0, SCHED_FIFO, &sp) != 0) {
                fprintf (stderr, "cannot set RT FIFO priority\n");
                retval = -1;
                goto cleanup;
        }
        
        if (mlockall (MCL_CURRENT | MCL_FUTURE) != 0) {
                fprintf (stderr, "cannot lock pages\n");
                
                retval = -1;
                goto cleanup;
        }

        retval = 0;
        
      cleanup:
        seteuid (getuid());
    }

    return retval;
}
/*---------------------------------------*/

void makewave(short wtable[])
{
  int i;

  for(i = 0; i < WTABLESIZE; i++) {
    wtable[i] = sin((double) (2*PI * (float)i/WTABLESIZE)) * 32767.0;
  }
  return;
}

short oscil(float si, short wave[], float *phs)
{
  int i;

  i = *phs;
  *phs += si;
  if(*phs >= WTABLESIZE) *phs -= WTABLESIZE;
  return(wave[i]);
}

main ()
{
  int len,format,stereo,speed,cycle,frag_size;
  int audio_fd;
  int arg;
  short waveform[WTABLESIZE];
  short sampbuff[NBUFS][BUFSIZE];
  int i,j,k,bufno;
  int active;
  float si[NOSCILS],phase[NOSCILS];

  goRT ();

  /* Open the audio port */
  if ((audio_fd = open("/dev/dsp", O_WRONLY, 0)) == -1) {
    perror("/dev/dsp");
    exit(1);
  }

  /* Set the fragment size */
  arg = 0x777f000d;
  if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &arg)==-1) {
    perror("incorrect fragment size");
    exit(1);
  }

  /* Put the audio port in "sync" mode */
  ioctl(audio_fd, SNDCTL_DSP_SYNC, 0);

  /* Set the format for output samples */
  format = AFMT_S16_LE;
  if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1) {
    perror("SNDCTL_DSP_SETFMT");
    exit(1);
  }

  /* Set stereo / mono (1/0) */
  stereo = 0;
  if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1) {
    perror("SNDCTL_DSP_STEREO");
    exit(1);
  }

  /* Set sample rate */
  speed = SR_RATE;
  if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
    { /* Fatal error */
      perror("SNDCTL_DSP_SPEED");
      exit(1);
    }

  /* Get the size of the audio buffer */
  /* Note that the driver computes this optimally */
  if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1) {
    exit(1);
  }
  printf("Audio buffer: %d\n",frag_size);

  /* make a wavetable for the oscillator */
  makewave(waveform);

  /* load buffers and write them to the audio port */

  for (i = 0; i < NOSCILS; i++) {
    si[i] = (FREQ + (i*5)) * WTABLESIZE/SR_RATE;
    phase[i] = 0.0;
  }

  bufno = 0;
  active = 1;
  for (i = 0; i < 99999; i++) {

    /* fill a buffer with sound */
    for (k = 0; k < active; k++) {

      if (k == 0) {
        for (j = 0; j < BUFSIZE; j++) {
          sampbuff[bufno][j] = oscil(si[k],waveform,&phase[k]) * 1.0/active;
        }
      }
      else {
        for (j = 0; j < BUFSIZE; j++) {
          sampbuff[bufno][j] += oscil(si[k],waveform,&phase[k]) * 1.0/active;
        }
      }

    }

    if ((len = write(audio_fd, sampbuff[bufno], 2*BUFSIZE)) == -1) {
      perror("audio write");
      exit(1);
    }

    /* shift to the next buffer */
    if (++bufno > 3) {
      if (++active > NOSCILS)
        active -= 1;
      printf("%d oscillators, daddy-oh!\n",active);
      bufno = 0;
    }
  }

  /* Close the audio port */
  close(audio_fd);
}

----------------------------------------------------------------------

Here is Ed Hall's first iteration:

----------------------------------------------------------------------

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

#define BUFSIZE 8192
#define SR_RATE 44100
#define NBUFS 4
#define WTABLESIZE 1000
#define FREQ 278.0
#define NOSCILS 1000
#define PI 3.1415926

void makewave(float wtable[])
{
  int i;

  for(i = 0; i < WTABLESIZE; i++) {
    wtable[i] = sin((double) (2*PI * (float)i/WTABLESIZE)) * 32767.0;
  }
  return;
}

float oscil(float si, float wave[], int *phs)
{
  int i;

  i = *phs;
  *phs += (int) si;
  if(*phs >= WTABLESIZE) *phs -= WTABLESIZE;
  return(wave[i]);
}

main ()
{
  int len,format,stereo,speed,cycle,frag_size;
  int audio_fd;
  int arg;
  float waveform[WTABLESIZE];
  short sampbuff[NBUFS][BUFSIZE];
  float accum[BUFSIZE];
  int i,j,k,bufno;
  int active;
  float scale;
  float si[NOSCILS];
  int phase[NOSCILS];

  /* Open the audio port */
  if ((audio_fd = open("/dev/dsp", O_WRONLY, 0)) == -1) {
    perror("/dev/dsp");
    exit(1);
  }

  /* Set the fragment size */
  arg = 0x777f000d;
  if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &arg)==-1) {
    perror("incorrect fragment size");
    exit(1);
  }

  /* Put the audio port in "sync" mode */
  ioctl(audio_fd, SNDCTL_DSP_SYNC, 0);

  /* Set the format for output samples */
  format = AFMT_S16_LE;
  if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1) {
    perror("SNDCTL_DSP_SETFMT");
    exit(1);
  }

  /* Set stereo / mono (1/0) */
  stereo = 0;
  if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1) {
    perror("SNDCTL_DSP_STEREO");
    exit(1);
  }

  /* Set sample rate */
  speed = SR_RATE;
  if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
    { /* Fatal error */
      perror("SNDCTL_DSP_SPEED");
      exit(1);
    }

  /* Get the size of the audio buffer */
  /* Note that the driver computes this optimally */
  if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1) {
    exit(1);
  }
  printf("Audio buffer: %d\n",frag_size);

  /* make a wavetable for the oscillator */
  makewave(waveform);

  /* load buffers and write them to the audio port */

  for (i = 0; i < NOSCILS; i++) {
    si[i] = (FREQ + (i*5)) * WTABLESIZE/SR_RATE;
    phase[i] = 0;
  }

  bufno = 0;
  active = 100;
  scale = 1.0f / (float)active;
  for (i = 0; i < 99999; i++) {

    /* fill a buffer with sound */
    for (k = 0; k < active; k++) {

      if (k == 0) {
        for (j = 0; j < BUFSIZE; j++) {
          accum[j] = oscil(si[k],waveform,&phase[k]) * scale;
        }
      }
      else {
        for (j = 0; j < BUFSIZE; j++) {
          accum[j] += oscil(si[k],waveform,&phase[k]) * scale;
        }
      }

    }

    for (j = 0; j < BUFSIZE; j++) {
      sampbuff[bufno][j] = (short)accum[j];
    }

    if ((len = write(audio_fd, sampbuff[bufno], 2*BUFSIZE)) == -1) {
      perror("audio write");
      exit(1);
    }

    /* shift to the next buffer */
    if (++bufno > 3) {
      if (++active > NOSCILS)
        active -= 1;
      scale = 1.0f / (float)active;
      printf("%d oscillators, daddy-oh!\n",active);
      bufno = 0;
    }
  }

  /* Close the audio port */
  close(audio_fd);
}

----------------------------------------------------------------------

Here is Ed's second iteration

----------------------------------------------------------------------

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

#define BUFSIZE 8192
#define SR_RATE 44100
#define NBUFS 4
#define WTABLESIZE 1024
#define WTABLE2PWR 10
#define UINTBITS 32
#define FREQ 278.0
#define NOSCILS 1000
#define PI 3.1415926

void makewave(float wtable[])
{
  int i;

  for(i = 0; i < WTABLESIZE; i++) {
    wtable[i] = sin((double) (2*PI * (float)i/WTABLESIZE)) * 32767.0;
  }
  return;
}

float oscil(unsigned int si, float wave[], unsigned int *phs)
{
  int i;

  i = (*phs >> (UINTBITS - WTABLE2PWR));
  *phs += si;
  return(wave[i]);
}

main ()
{
  int len,format,stereo,speed,cycle,frag_size;
  int audio_fd;
  int arg;
  float waveform[WTABLESIZE];
  short sampbuff[NBUFS][BUFSIZE];
  float accum[BUFSIZE];
  int i,j,k,bufno;
  int active;
  float ampscale;
  double phasescale;
  unsigned int si[NOSCILS],phase[NOSCILS];

  /* Open the audio port */
  if ((audio_fd = open("/dev/dsp", O_WRONLY, 0)) == -1) {
    perror("/dev/dsp");
    exit(1);
  }

  /* Set the fragment size */
  arg = 0x777f000d;
  if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &arg)==-1) {
    perror("incorrect fragment size");
    exit(1);
  }

  /* Put the audio port in "sync" mode */
  ioctl(audio_fd, SNDCTL_DSP_SYNC, 0);

  /* Set the format for output samples */
  format = AFMT_S16_LE;
  if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1) {
    perror("SNDCTL_DSP_SETFMT");
    exit(1);
  }

  /* Set stereo / mono (1/0) */
  stereo = 0;
  if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1) {
    perror("SNDCTL_DSP_STEREO");
    exit(1);
  }

  /* Set sample rate */
  speed = SR_RATE;
  if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
    { /* Fatal error */
      perror("SNDCTL_DSP_SPEED");
      exit(1);
    }

  /* Get the size of the audio buffer */
  /* Note that the driver computes this optimally */
  if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1) {
    exit(1);
  }
  printf("Audio buffer: %d\n",frag_size);

  /* make a wavetable for the oscillator */
  makewave(waveform);

  /* load buffers and write them to the audio port */

  phasescale = (1 << (UINTBITS - WTABLE2PWR)) * (double)WTABLESIZE/SR_RATE;
  for (i = 0; i < NOSCILS; i++) {
    si[i] = (FREQ + (i*5)) * phasescale;
    phase[i] = 0;
  }

  bufno = 0;
  active = 1;
  ampscale = 1.0f / (float)active;
  for (i = 0; i < 99999; i++) {

    /* fill a buffer with sound */
    for (k = 0; k < active; k++) {

      if (k == 0) {
        for (j = 0; j < BUFSIZE; j++) {
          accum[j] = oscil(si[k],waveform,&phase[k]) * ampscale;
        }
      }
      else {
        for (j = 0; j < BUFSIZE; j++) {
          accum[j] += oscil(si[k],waveform,&phase[k]) * ampscale;
        }
      }

    }

    for (j = 0; j < BUFSIZE; j++) {
      sampbuff[bufno][j] = (short)accum[j];
    }

    if ((len = write(audio_fd, sampbuff[bufno], 2*BUFSIZE)) == -1) {
      perror("audio write");
      exit(1);
    }

    /* shift to the next buffer */
    if (++bufno > 3) {
      if (++active > NOSCILS)
        active -= 1;
      ampscale = 1.0f / (float)active;
      printf("%d oscillators, daddy-oh!\n",active);
      bufno = 0;
    }
  }

  /* Close the audio port */
  close(audio_fd);
}


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Tue Sep 19 2000 - 19:23:21 EEST