Update of /cvsroot/alsa/alsa-oss/test
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7159/test
Modified Files:
mmap_test.c
Log Message:
Converted mmap_test to normal coding style; some mmap cleanups
Index: mmap_test.c
===================================================================
RCS file: /cvsroot/alsa/alsa-oss/test/mmap_test.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- mmap_test.c 12 Feb 2004 17:16:07 -0000 1.2
+++ mmap_test.c 12 Feb 2004 18:51:37 -0000 1.3
@@ -1,297 +1,149 @@
-/*
- * This is a simple program which demonstrates use of mmapped DMA buffer
- * of the sound driver directly from application program.
- *
- * This sample program works (currently) only with Linux, FreeBSD and BSD/OS
- * (FreeBSD and BSD/OS require OSS version 3.8-beta16 or later.
- *
- * Note! Don't use mmapped DMA buffers (direct audio) unless you have
- * very good reasons to do it. Programs using this feature will not
- * work with all soundcards. GUS (GF1) is one of them (GUS MAX works).
- *
- * This program requires version 3.5-beta7 or later of OSS
- * (3.8-beta16 or later in FreeBSD and BSD/OS).
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/soundcard.h>
-#include <sys/time.h>
-
-main()
-{
- int fd, sz, fsz, i, tmp, n, l, have_data=0, nfrag;
- int caps, idx;
-
- int sd, sl=0, sp;
-
- unsigned char data[500000], *dp = data;
-
- struct buffmem_desc imemd, omemd;
- caddr_t buf;
- struct timeval tim;
-
- unsigned char *op;
-
- struct audio_buf_info info;
-
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/soundcard.h>
+#include <sys/time.h>
+#include <oss-redir.h>
+
+int main(void)
+{
+ int fd, sz, fsz, i, tmp, n, l, have_data=0, nfrag;
+ int caps, idx;
+
+ int sd, sl=0, sp;
+
+ unsigned char data[500000], *dp = data;
+
+ struct buffmem_desc imemd, omemd;
+ caddr_t buf;
+ struct timeval tim;
+
+ unsigned char *op;
+
+ struct audio_buf_info info;
+
int frag = 0xffff000c; /* Max # periods of 2^13=8k bytes */
-
- fd_set writeset;
-
- close(0);
- if ((fd=oss_pcm_open("/dev/dsp", O_RDWR, 0))==-1)
- {
- perror("/dev/dsp");
- exit(-1);
- }
-/*
- * Then setup sampling parameters. Just sampling rate in this case.
- */
-
- tmp = 48000;
- oss_pcm_ioctl(fd, SNDCTL_DSP_SPEED, &tmp);
- printf("Speed set to %d\n", tmp);
-
-/*
- * Load some test data.
- */
-
- sl = sp = 0;
- if ((sd=open("smpl", O_RDONLY, 0))!=-1)
- {
- sl = read(sd, data, sizeof(data));
- printf("%d bytes read from file.\n", sl);
- close(sd);
- }
- else perror("smpl");
-
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
- {
- perror("/dev/dsp");
- fprintf(stderr, "Sorry but your sound driver is too old\n");
- exit(-1);
- }
-
-/*
- * Check that the device has capability to do this. Currently just
- * CS4231 based cards will work.
- *
- * The application should also check for DSP_CAP_MMAP bit but this
- * version of driver doesn't have it yet.
- */
-/* oss_pcm_ioctl(fd, SNDCTL_DSP_SETSYNCRO, 0); */
-
-/*
- * You need version 3.5-beta7 or later of the sound driver before next
- * two lines compile. There is no point to modify this program to
- * compile with older driver versions since they don't have working
- * mmap() support.
- */
- if (!(caps & DSP_CAP_TRIGGER) ||
- !(caps & DSP_CAP_MMAP))
- {
- fprintf(stderr, "Sorry but your soundcard can't do this\n");
- exit(-1);
- }
-
-/*
- * Select the period size. This is propably important only when
- * the program uses select(). Period size defines how often
- * select call returns.
- */
-
- oss_pcm_ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);
-
-/*
- * Compute total size of the buffer. It's important to use this value
- * in mmap() call.
- */
-
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
- {
- perror("GETOSPACE");
- exit(-1);
- }
-
- sz = info.fragstotal * info.fragsize;
- fsz = info.fragsize;
- printf( "info.fragstotal = %i\n", info.fragstotal );
- printf( "info.fragsize = %i\n", info.fragsize );
- printf( "info.periods = %i\n", info.fragments );
- printf( "info.bytes = %i\n", info.bytes );
-
-/*
- * Call mmap().
- *
- * IMPORTANT NOTE!!!!!!!!!!!
- *
- * Full duplex audio devices have separate input and output buffers.
- * It is not possible to map both of them at the same mmap() call. The buffer
- * is selected based on the prot argument in the following way:
- *
- * - PROT_READ (alone) selects the input buffer.
- * - PROT_WRITE (alone) selects the output buffer.
- * - PROT_WRITE|PROT_READ together select the output buffer. This combination
- * is required in BSD to make the buffer accessible. With just PROT_WRITE
- * every attempt to access the returned buffer will result in segmentation/bus
- * error. PROT_READ|PROT_WRITE is also permitted in Linux with OSS version
- * 3.8-beta16 and later (earlier versions don't accept it).
- *
- * Non duplex devices have just one buffer. When an application wants to do both
- * input and output it's recommended that the device is closed and re-opened when
- * switching between modes. PROT_READ|PROT_WRITE can be used to open the buffer
- * for both input and output (with OSS 3.8-beta16 and later) but the result may be
- * unpredictable.
- */
-
-#if 1
- if ((buf=mmap(NULL, sz, PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0))==(caddr_t)-1)
- {
- perror("mmap (write)");
- exit(-1);
- }
- printf("mmap (out) returned %08x\n", buf);
-#else
- buf=data;
+
+ fd_set writeset;
+
+ if ((fd=oss_pcm_open("/dev/dsp", O_RDWR, 0))==-1) {
+ perror("/dev/dsp");
+ exit(-1);
+ }
+ tmp = 48000;
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_SPEED, &tmp) < 0) {
+ perror("SNDCTL_DSP_SPEED\n");
+ exit(EXIT_FAILURE);
+ }
+ printf("Speed set to %d\n", tmp);
+
+ sl = sp = 0;
+ if ((sd=open("smpl", O_RDONLY, 0)) >= 0) {
+ sl = read(sd, data, sizeof(data));
+ printf("%d bytes read from file.\n", sl);
+ close(sd);
+ } else
+ perror("smpl");
+
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) < 0) {
+ perror("/dev/dsp");
+ fprintf(stderr, "Sorry but your sound driver is too old\n");
+ exit(EXIT_FAILURE);
+ }
+ if (!(caps & DSP_CAP_TRIGGER) ||
+ !(caps & DSP_CAP_MMAP))
+ {
+ fprintf(stderr, "Sorry but your soundcard can't do this\n");
+ exit(EXIT_FAILURE);
+ }
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag) < 0)
+ perror("SNDCTL_DSP_SETFRAGMENT");
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
+ perror("SNDCTL_DSP_GETOSPACE");
+ exit(EXIT_FAILURE);
+ }
+ sz = info.fragstotal * info.fragsize;
+ fsz = info.fragsize;
+ printf("info.fragstotal = %i\n", info.fragstotal);
+ printf("info.fragsize = %i\n", info.fragsize);
+ printf("info.periods = %i\n", info.fragments);
+ printf("info.bytes = %i\n", info.bytes);
+ if ((buf=mmap(NULL, sz, PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED) {
+ perror("mmap (write)");
+ exit(-1);
+ }
+ printf("mmap (out) returned %08x\n", buf);
+ op=buf;
+
+ tmp = 0;
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0) {
+ perror("SNDCTL_DSP_SETTRIGGER");
+ exit(EXIT_FAILURE);
+ }
+ printf("Trigger set to %08x\n", tmp);
+
+ tmp = PCM_ENABLE_OUTPUT;
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0) {
+ perror("SNDCTL_DSP_SETTRIGGER");
+ exit(EXIT_FAILURE);
+ }
+ printf("Trigger set to %08x\n", tmp);
+
+ nfrag = 0;
+ for (idx=0; idx<40; idx++) {
+ struct count_info count;
+ int p, l, extra;
+
+ FD_ZERO(&writeset);
+ FD_SET(fd, &writeset);
+
+ tim.tv_sec = 10;
+ tim.tv_usec= 0;
+
+ select(fd+1, NULL, &writeset, NULL, NULL);
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOPTR, &count) < 0) {
+ perror("GETOPTR");
+ exit(EXIT_FAILURE);
+ }
+ nfrag += count.blocks;
+#ifdef VERBOSE
+ printf("Total: %09d, Period: %03d, Ptr: %06d", count.bytes, nfrag,
count.ptr);
+ fflush(stdout);
+#endif
+ count.ptr = (count.ptr/fsz)*fsz;
+
+#ifdef VERBOSE
+ printf(" memcpy(%6d, %4d)\n", (dp-data), fsz);
+ fflush(stdout);
#endif
- op=buf;
-
-/*
- * op contains now a pointer to the DMA buffer
- */
-
-/*
- * Then it's time to start the engine. The driver doesn't allow read() and/or
- * write() when the buffer is mapped. So the only way to start operation is
- * to togle device's enable bits. First set them off. Setting them on enables
- * recording and/or playback.
- */
-
- tmp = 0;
- oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp);
- printf("Trigger set to %08x\n", tmp);
-
-/*
- * It might be usefull to write some data to the buffer before starting.
- */
-
- tmp = PCM_ENABLE_OUTPUT;
- oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp);
- printf("Trigger set to %08x\n", tmp);
-
-/*
- * The machine is up and running now. Use SNDCTL_DSP_GETOPTR to get the
- * buffer status.
- *
- * NOTE! The driver empties each buffer fragmen after they have been
- * played. This prevents looping sound if there are some performance problems
- * in the application side. For similar reasons it recommended that the
- * application uses some amout of play ahead. It can rewrite the unplayed
- * data later if necessary.
- */
-
- nfrag = 0;
- for (idx=0; idx<40; idx++)
- {
- struct count_info count;
- int p, l, extra;
-
- FD_ZERO(&writeset);
- FD_SET(fd, &writeset);
-
- tim.tv_sec = 10;
- tim.tv_usec= 0;
-
- select(fd+1, NULL, &writeset, NULL, NULL);
-/*
- * SNDCTL_DSP_GETOPTR (and GETIPTR as well) return three items. The
- * bytes field returns number of bytes played since start. It can be used
- * as a real time clock.
- *
- * The blocks field returns number of period transitions (interrupts) since
- * previous GETOPTR call. It can be used as a method to detect underrun
- * situations.
- *
- * The ptr field is the DMA pointer inside the buffer area (in bytes from
- * the beginning of total buffer area).
- */
-
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOPTR, &count)==-1)
- {
- perror("GETOPTR");
- exit(-1);
- }
-
- nfrag += count.blocks;
-
-#ifdef VERBOSE
-
- printf("Total: %09d, Period: %03d, Ptr: %06d",
- count.bytes, nfrag, count.ptr);
- fflush(stdout);
-#endif
-
-/*
- * Caution! This version doesn't check for bounds of the DMA
- * memory area. It's possible that the returned pointer value is not aligned
- * to period boundaries. It may be several samples behind the boundary
- * in case there was extra delay between the actual hardware interrupt and
- * the time when DSP_GETOPTR was called.
- *
- * Don't just call memcpy() with length set to 'period_size' without
- * first checking that the transfer really fits to the buffer area.
- * A mistake of just one byte causes seg fault. It may be easiest just
- * to align the returned pointer value to period boundary before using it.
- *
- * It would be very good idea to write few extra samples to next period
- * too. Otherwise several (uninitialized) samples from next period
- * will get played before your program gets chance to initialize them.
- * Take in count the fact thaat there are other processes batling about
- * the same CPU. This effect is likely to be very annoying if period
- * size is decreased too much.
- */
-
-/*
- * Just a minor clarification to the above. The following line alings
- * the pointer to period boundaries. Note! Don't trust that period
- * size is always a power of 2. It may not be so in future.
- */
- count.ptr = (count.ptr/fsz)*fsz;
-
-#ifdef VERBOSE
- printf(" memcpy(%6d, %4d)\n", (dp-data), fsz);
- fflush(stdout);
-#endif
-
-/*
+
+/*
* Set few bytes in the beginning of next period too.
- */
- if ((count.ptr+fsz+16) < sz) /* Last period? */
- extra = 16;
- else
- extra = 0;
-
- memcpy(op+count.ptr, dp, fsz+extra);
-
- dp += fsz;
- if (dp > (data+sl-fsz))
- dp = data;
- }
-
- close(fd);
+ */
+ if ((count.ptr+fsz+16) < sz) /* Last period? */
+ extra = 16;
+ else
+ extra = 0;
+
+ memcpy(op+count.ptr, dp, fsz+extra);
- printf( ">>>> open (2)\n" ); fflush( stdout );
+ dp += fsz;
+ if (dp > (data+sl-fsz))
+ dp = data;
+ }
- if ((fd=oss_pcm_open("/dev/dsp", O_RDWR, 0))==-1)
- {
- perror("/dev/dsp");
- exit(-1);
- }
- close( fd );
+ close(fd);
+
+ printf("second open test:\n");
+ if ((fd=oss_pcm_open("/dev/dsp", O_RDWR, 0))==-1) {
+ perror("/dev/dsp");
+ exit(-1);
+ }
+ close(fd);
+ printf("second open test passed\n");
- exit(0);
-}
+ exit(0);
+}
-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog