#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <sys/time.h>
static long ms(struct timeval *a, struct timeval *b){
  return (b->tv_sec-a->tv_sec)*1000+(b->tv_usec-a->tv_usec)/1000;
}
int main(int argc, char **argv){
  const char *dev = argc>1?argv[1]:"/dev/dsp0";
  int fd=open(dev,O_WRONLY);
  if(fd<0){perror("open");return 1;}
  int fmt=AFMT_U8, speed=8000, ch=1;
  ioctl(fd,SNDCTL_DSP_SETFMT,&fmt);
  ioctl(fd,SNDCTL_DSP_CHANNELS,&ch);
  ioctl(fd,SNDCTL_DSP_SPEED,&speed);
  int frag = 0x0010000D;  /* 2^13 bytes * 16 blocks */
  ioctl(fd,SNDCTL_DSP_SETFRAGMENT,&frag);
  audio_buf_info bi;
  ioctl(fd,SNDCTL_DSP_GETOSPACE,&bi);
  fprintf(stderr,"frag=%d bytes=%d frags=%d fragsize=%d\n",
      frag, bi.bytes, bi.fragments, bi.fragsize);
  char buf[4096]; memset(buf,0x80,sizeof buf);
  struct timeval a,b,c;
  long wr=0;
  gettimeofday(&a,NULL);
  /* fill until nearly full */
  while(wr<200000){
    ioctl(fd,SNDCTL_DSP_GETOSPACE,&bi);
    if((int)bi.bytes < 4096) break;
    ssize_t n=write(fd,buf,4096); if(n<=0)break; wr+=n;
  }
  gettimeofday(&b,NULL);
  close(fd);
  gettimeofday(&c,NULL);
  printf("wrote %ld in %ld ms; close() drain %ld ms\n", wr, ms(&a,&b), ms(&b,&c));
  return 0;
}
