vtest.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include <fcntl.h>
00005 #include <errno.h>
00006 #include <string.h>
00007 #include <sys/ioctl.h>
00008 #include <sys/time.h>
00009 
00010 #include <alsa/asoundlib.h>
00011 
00012 int xrun_count;
00013 
00014 int dsp_fd;
00015 
00016 static int buffer_size;
00017 static int period_size;
00018 
00019 static void
00020 set_hwparams(snd_pcm_t *handle)
00021 {
00022         snd_pcm_uframes_t size;
00023         int dir;
00024         snd_pcm_hw_params_t *hwparams;
00025     unsigned int uval;
00026 
00027         snd_pcm_hw_params_malloc(&hwparams);
00028 
00029         snd_pcm_hw_params_any(handle, hwparams);
00030 
00031         snd_pcm_hw_params_set_rate_resample(handle, hwparams, 1);
00032 
00033         snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
00034         snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_U8);
00035         snd_pcm_hw_params_set_channels(handle, hwparams, 1);
00036 
00037     uval = 11025;
00038         snd_pcm_hw_params_set_rate_near(handle, hwparams, &uval, 0);
00039 
00040     uval = 500 * 1000; /* usecs */
00041         snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &uval, &dir);
00042         snd_pcm_hw_params_get_buffer_size(hwparams, &size);
00043     buffer_size = size;
00044 
00045     uval = 100 * 1000;
00046         snd_pcm_hw_params_set_period_time_near(handle, hwparams, &uval, &dir);
00047         snd_pcm_hw_params_get_period_size(hwparams, &size, &dir);
00048     period_size = size;
00049 
00050         snd_pcm_hw_params(handle, hwparams);
00051 
00052     printf ("buffer_size %d; period_size %d\n", buffer_size, period_size);
00053 }
00054 
00055 static void
00056 set_swparams(snd_pcm_t *handle)
00057 {
00058         snd_pcm_sw_params_t *swparams;
00059 
00060         snd_pcm_sw_params_malloc(&swparams);
00061 
00062         snd_pcm_sw_params_current(handle, swparams);
00063 
00064         /* start the transfer when the buffer is almost full: */
00065         /* (buffer_size / avail_min) * avail_min */
00066         snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
00067 
00068         /* allow the transfer when at least period_size samples can be processed */
00069         snd_pcm_sw_params_set_avail_min(handle, swparams, period_size);
00070 
00071         /* align all transfers to 1 sample */
00072         snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
00073 
00074         snd_pcm_sw_params(handle, swparams);
00075 }
00076 
00077 snd_pcm_t *pcm;
00078 
00079 void
00080 sound_init (void)
00081 {
00082     int err;
00083     char *device;
00084 
00085     device = "plughw:0,0";
00086 
00087     printf ("opening pcm device %s\n", device);
00088         if ((err = snd_pcm_open(&pcm, device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
00089                 printf("Playback open error: %s\n", snd_strerror(err));
00090         exit (1);
00091         }
00092 
00093     set_hwparams(pcm);
00094     set_swparams(pcm);
00095 }
00096 
00097 int soundbuf_size;
00098 unsigned char *soundbuf;
00099 int soundbuf_used;
00100 int soundbuf_off;
00101 int soundbuf_playing;
00102 
00103 /* return 0 when there is nothing left to play */
00104 int
00105 sound_step (void)
00106 {
00107     int avail, n;
00108 
00109     if (soundbuf_playing == 0)
00110         return (0);
00111 
00112     if ((avail = soundbuf_used - soundbuf_off) == 0) {
00113         soundbuf_playing = 0;
00114 
00115         snd_pcm_drain (pcm);
00116         return (0);
00117     }
00118 
00119     if (avail > period_size)
00120         avail = period_size;
00121 
00122     n = snd_pcm_writei (pcm, soundbuf + soundbuf_off, avail);
00123 
00124     if (n < 0) {
00125         if (n == -EAGAIN) {
00126             usleep (1);
00127             return (1);
00128         }
00129         if (n == -EPIPE) {
00130             xrun_count++;
00131             snd_pcm_prepare (pcm);
00132             return (1);
00133         }
00134         
00135         printf ("sound write error: %s\n", 
00136             snd_strerror(n));
00137         exit (1);
00138     }
00139 
00140 //  printf ("used %d (xrun %d)\n", n, xrun_count);
00141 
00142 
00143     soundbuf_off += n;
00144 
00145     return (1);
00146 }
00147 
00148 void
00149 sound_play (unsigned char *buf, int size)
00150 {
00151     unsigned char *start_buf;
00152 
00153     if (size > soundbuf_size) {
00154         if (soundbuf)
00155             free (soundbuf);
00156         soundbuf_size = size;
00157         if ((soundbuf = malloc (soundbuf_size)) == NULL) {
00158             fprintf (stderr, "out of memory\n");
00159             exit (1);
00160         }
00161     }
00162 
00163     memcpy (soundbuf, buf, size);
00164 
00165     soundbuf_used = size;
00166     soundbuf_off = 0;
00167     soundbuf_playing = 1;
00168 
00169     snd_pcm_start (pcm);
00170     snd_pcm_prepare (pcm);
00171 
00172     start_buf = malloc (buffer_size);
00173     memset (start_buf, 0x80, buffer_size);
00174     snd_pcm_writei (pcm, start_buf, buffer_size);
00175     free (start_buf);
00176 
00177     sound_step ();
00178 }
00179 
00180 double
00181 get_time (void)
00182 {
00183     struct timeval tv;
00184     gettimeofday (&tv, NULL);
00185     return (tv.tv_sec + tv.tv_usec / 1e6);
00186 }
00187 
00188 void
00189 busywait (double secs)
00190 {
00191     double start;
00192     start = get_time ();
00193     while (get_time () - start < secs)
00194         ;
00195 }
00196 
00197 void
00198 usage (void)
00199 {
00200     fprintf (stderr, "usage: vtest idx\n");
00201     exit (1);
00202 }
00203 
00204 int
00205 main (int argc, char **argv)
00206 {
00207     int c;
00208     char *filename;
00209     int idx;
00210     FILE *f;
00211     char *rawbuf;
00212     FILE *outf;
00213     int i;
00214 
00215     struct TM {
00216         long offset;
00217         long size;
00218     } ABSnd;
00219 
00220     filename = "/l/baris/gamedat/unews.cdr";
00221 
00222     while ((c = getopt (argc, argv, "")) != EOF) {
00223         switch (c) {
00224         default:
00225             usage ();
00226         }
00227     }
00228 
00229     if (optind >= argc)
00230         usage ();
00231 
00232     idx = atoi (argv[optind++]);
00233 
00234     if (optind != argc)
00235         usage ();
00236 
00237     if ((f = fopen (filename, "rb")) == NULL) {
00238         fprintf (stderr, "can't open %s\n", filename);
00239         exit (1);
00240     }
00241 
00242     fseek (f, idx * sizeof (ABSnd), SEEK_SET);
00243     fread (&ABSnd, sizeof ABSnd, 1, f);
00244 
00245     printf ("offset %ld; size %ld\n", ABSnd.offset, ABSnd.size);
00246 
00247     if ((rawbuf = malloc (ABSnd.size)) == NULL) {
00248         fprintf (stderr, "out of memory\n");
00249         exit (1);
00250     }
00251 
00252     fseek (f, ABSnd.offset, SEEK_SET);
00253     fread (rawbuf, 1, ABSnd.size, f);
00254 
00255     outf = fopen ("x", "wb");
00256     fwrite (rawbuf, 1, ABSnd.size, outf);
00257     fclose (outf);
00258 
00259     outf = fopen ("y", "wb");
00260     for (i = 0; i < ABSnd.size; i++)
00261         fprintf (outf, "%d\n", rawbuf[i] & 0xff);
00262     fclose (outf);
00263 
00264     sound_init ();
00265 
00266     usleep (250 * 1000);
00267 
00268     sound_play ((unsigned char *)rawbuf, ABSnd.size);
00269     while (sound_step ())
00270         ;
00271 
00272     usleep (250 * 1000);
00273 
00274     printf ("total xruns %d\n", xrun_count);
00275 
00276     return (0);
00277 }
00278 

Generated on Fri Sep 28 00:35:28 2007 for raceintospace by  doxygen 1.5.3