return to first page linux journal archive
keywordscontents

Listing 4. Stage 2 and 3 in C, integrator.c

#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
#define SAMPLE_RATE 44100
#define BLOCKS_PER_SECOND 50
#if defined(LINUX)
#include <sys/soundcard.h>
int SoundFD;
#elif  defined(IRIX)
#include <audio.h>
ALconfig Irix_AL_config;
ALport   SoundFD;
#elif defined(CYGWIN)
#include <windows.h>
#define NONAMELESSUNION
#define _stdcall STDCALL
typedef HANDLE HTASK;
#include <semaphore.h>
#include <mmsystem.h>
static HWAVEOUT WaveDevice = NULL;
static sem_t WavBufSema;
static void CALLBACK WaveCallBack(HWAVE hWave,
  UINT uMsg, DWORD dwInstance,
  DWORD dwParam1, DWORD dwParam2) {
  if (uMsg == WOM_DONE) {
    WAVEHDR * wh = (WAVEHDR *) dwParam1;
    HGLOBAL hg;
    waveOutUnprepareHeader(WaveDevice, wh,
                           sizeof(WAVEHDR));
    hg = GlobalHandle(wh->lpData);
    GlobalUnlock(hg); GlobalFree(hg); 
    hg = GlobalHandle(hg); GlobalUnlock(hg);
    GlobalFree(hg);
    sem_post (& WavBufSema);
} }
#endif
int InitSoundSystem(int SampleRate) {
  int OK = -1;
#if defined(LINUX)
  if ((SoundFD=open("/dev/dsp", O_WRONLY)) >=0) {
    int OSS_format = AFMT_S16_LE;
    int OSS_speed  = SampleRate;
    ioctl(SoundFD, SNDCTL_DSP_RESET, 0);
    if ((ioctl(SoundFD, SNDCTL_DSP_SETFMT,
               &OSS_format) != -1)  &&
        (OSS_format == AFMT_S16_LE) &&
        (ioctl(SoundFD, SNDCTL_DSP_SPEED,
               &OSS_speed ) != -1)  &&
        (OSS_speed  == SampleRate)) {
      OK = SoundFD;
  } }
#elif defined(IRIX)
  long PV [10] = {
    AL_LEFT_SPEAKER_GAIN,        10,
    AL_RIGHT_SPEAKER_GAIN,       10,
    AL_OUTPUT_RATE,              
  };
  PV [5] = AL_RATE_44100;
  if ((ALsetparams(AL_DEFAULT_DEVICE,PV,6)==0) &&
      ((Irix_AL_config = ALnewconfig()) != NULL)){
    ALsetchannels  (Irix_AL_config, AL_STEREO);
    ALsetqueuesize (Irix_AL_config, SAMPLE_RATE);
    ALsetwidth     (Irix_AL_config, AL_SAMPLE_16);
    if (((SoundFD=ALopenport("Speaker","w",
            Irix_AL_config)) != NULL)) OK = 0;
  }
#elif defined(CYGWIN)
  WaveDevice = NULL;
  sem_init (& WavBufSema, 0, BLOCKS_PER_SECOND);
  if (waveOutGetNumDevs() > 0) {
    WAVEFORMATEX outFormatex;
    outFormatex.wFormatTag      = WAVE_FORMAT_PCM;
    outFormatex.wBitsPerSample  =              16;
    outFormatex.nChannels       =               1;
    outFormatex.nSamplesPerSec  =     SAMPLE_RATE;
    outFormatex.nBlockAlign   = sizeof(short int);
    outFormatex.nAvgBytesPerSec =
  outFormatex.nSamplesPerSec * sizeof(short int);
    if (waveOutOpen(&WaveDevice, WAVE_MAPPER,
          &outFormatex, (DWORD) WaveCallBack, 0,
          CALLBACK_FUNCTION) == MMSYSERR_NOERROR)
      OK = 0;
  }
#endif
  return OK;
}
void SoundOutAndWait(short int * Sample,
                           int HowMany) {
  int HowManyBytes = HowMany * sizeof(short int);
#if defined(LINUX)
  write(SoundFD, Sample, HowManyBytes);
#elif defined(IRIX)
  ALwritesamps (SoundFD, Sample, HowMany);
#elif defined(CYGWIN)
  HGLOBAL HGheader = GlobalAlloc (GMEM_MOVEABLE |
    GMEM_ZEROINIT, sizeof(WAVEHDR));
  HGLOBAL HGdata   = GlobalAlloc (GMEM_MOVEABLE,
                      HowManyBytes);
  LPWAVEHDR WaveHeaderPtr = GlobalLock(HGheader);
  WaveHeaderPtr->dwBufferLength =   HowManyBytes;
  WaveHeaderPtr->lpData   =   GlobalLock(HGdata);
  CopyMemory(WaveHeaderPtr->lpData, Sample,
                                   HowManyBytes);
  waveOutPrepareHeader(WaveDevice, WaveHeaderPtr,
                                sizeof(WAVEHDR));
  waveOutWrite        (WaveDevice, WaveHeaderPtr,
                                sizeof(WAVEHDR));
  sem_wait (& WavBufSema);
#endif
}
int main (int argc, char *argv[]) {
  double k=0.05, B=7.5, x1=3.0, dx=4.0,
         dt=M_PI/100.0, ddt, x0, x2;
  int i, j = 0;
  if (InitSoundSystem(SAMPLE_RATE) < 0) exit(0);
  ddt = dt * dt; x0 = x1 - dx*dt;
  while (1) {
    short int SampleBuffer[SAMPLE_RATE /
                           BLOCKS_PER_SECOND];
    fd_set stdin_set;
    struct timeval timeout = { 0, 0 };
    FD_ZERO(& stdin_set); /* non-blocking read */
    FD_SET(fileno(stdin), & stdin_set);
    if (select(fileno(stdin)+1, & stdin_set,
               NULL, NULL, & timeout) > 0) {
      char line[128], Name[128];
      float Value;
      fgets(line, sizeof(line), stdin);
      sscanf (line, "%s %f", Name, &Value);
      if (strcmp(Name,"k")==0) k=(double) Value;
      if (strcmp(Name,"B")==0) B=(double) Value;
    }
    for (i=0; i<(SAMPLE_RATE/BLOCKS_PER_SECOND);
         i++, j++) {
      SampleBuffer[i] = 4096 * x1;
      x2 = (ddt*B * cos(j*dt) + (2+dt*k)*x1 -
            x0 - ddt*x1*x1*x1) / (1 + dt * k);
      if ((j%1000) == 0)  /* Poincare section */
        printf("%f %f\n", x2, (x2-x1)/dt);
      x0=x1; x1=x2;
    }
    SoundOutAndWait(SampleBuffer,
      SAMPLE_RATE / BLOCKS_PER_SECOND);
  }
  return 0;
}