📄 sndplay.c
字号:
/* sndPlay.c - Audio file playing demonstration *//* Copyright 2000-2003 Wind River Systems, Inc. *//*modification history--------------------01i,03apr03,jlb Correct Diab compile warning (prototype match)01h,14nov01,jlb Fix fragment size setting (SPR 69972)01g,20dec00,gav Missed change to variable name.01f,20dec00,gav Entry point identical to filename w/o extension.01e,06dec00,jlb Open sound device read/write, fix compile warnings01d,22nov00,gav Added entry point using same form as other examples.01c,14nov00,jlb Changed name of wavplay.c to sndPlay.c and added support for au (Sun) type of audio files01b,11sep00,jlb Use soundcard.h verses sound.h01a,15mar00,jlb written*//*DESCRIPTIONThis file provides a demonstration of the use of the audio devicedriver. An audio file formatted as an <au> or a <wav> file is played onthe audio device. *//* Includes */#include <vxWorks.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <ioLib.h>#include <unistd.h>#include <string.h>#include <selectLib.h>#include <ugl/ugl.h>#include <ugl/uglos.h>#include <ugl/audio/soundcard.h>#include <ugl/audio/sndWave.h>#include <ugl/audio/sndAu.h>#define AUDIO_DEVICE "/sound/dsp"#define MIXER_DEVICE "/sound/mixer"#define USE_SELECTSTATUS soundPlay (char *);/******************************************************************************* wexSndPlay - play an audio stream ** This routine spawns a task to play an audio stream contained within the file* specified by <filename>. The audio stream may be formatted as either an* <au> or a <wav> file.*** This program demonstrates the method to open the audio and mixer* devices and to:**\ml*\m Determine whether the audio stream is formatted as an <au> or a <wav> file*\m Identify characteristics of the audio stream, such as number of channels, * number of samples, and size of each sample *\m Set the volume*\m Select the number of audio channels*\m Select the sample rate for the audio stream*\m Select the size of a sample*\m Initialize the buffering (set size of each fragment) and send audio fragments* to the sound device.*\me** * This demonstration program may be used with or without the use of select(). ** RETURNS: OK ** ERRNO: N/A** SEE ALSO: **/int sndPlay ( char *filename /* Name of audio file to play */ ) { uglOSTaskCreate("tWindMLSnd", (UGL_FPTR)soundPlay, 110, 0, 10240, (int)filename, 0,0,0,0); return (OK); }/******************************************************************************* soundPlay - play a sound file ** This routine plays the sound file <filename> on an audio device. The audio* file is read to obtain the header information. The audio stream is checked* to see if the file is formated as a wav or an au file. Using the header* information the audio device is placed in the proper mode and then the* audio stream is sent to the audio device .** RETURNS: OK when the audio file was successfully played; otherwise ERROR** ERRNO: N/A*** SEE ALSO: *** NOMANUAL*/STATUS soundPlay ( char *filename /* Audio file */ ) { unsigned char *buffer; int buffer_size, samplebits, i, blockSize; int size = 0; int fd, sd, md; int channels; UINT32 format; UINT32 samplerate, samples, datastart; audio_buf_info info; int maxVol = (100 << 8) | 100;#ifdef USE_SELECT fd_set writeFD;#endif /* USE_SELECT */ /* Initialize WindML */ uglInitialize(); /* Open the audio file */ fd = open (filename, O_RDONLY, 0666); if (fd < 0) { printf ("Error opening file %s\n", filename); return (ERROR); } /* Assume a wav file and read the wav form header file */ if (wavHeaderRead (fd, &channels, &samplerate, &samplebits, &samples, &datastart) == OK) { /* Set the audio format */ if (samplebits == 16) format = AFMT_S16_LE; else format = AFMT_U8; } else /* Error, try to read as an au type file */ auHeaderRead (fd, (UINT32 *)&channels, &samplerate, &format, &samples, &datastart); /* if format was set, then sound format was recognized */ if (format == -1) { printf ("Sound file format not recognized\n"); close (fd); return (ERROR); } /* Position to the start of the audio data */ if (lseek (fd, datastart, SEEK_SET) != datastart) { printf ("Sound file is corrupted\n"); close (fd); return (ERROR); } /* Open the audio device */ sd = open (AUDIO_DEVICE, O_RDWR, 0666); if (sd < 0) { printf("Unable to open the sound device - %s\n",AUDIO_DEVICE); close (fd); return (ERROR); } /* Open the mixer device */ md = open (MIXER_DEVICE, O_RDWR, 0666); if (md < 0) { printf("Unable to open the mixer device - %s\n",MIXER_DEVICE); close (fd); close (sd); return (ERROR); } /* Print characteristics of the sound data stream */ printf ("File name: %s\n", filename); switch (format) { case AFMT_S16_LE: printf("WAV file - 16 bit signed little endian\n"); size = samples * channels * (samplebits >> 3); break; case AFMT_U8: printf("WAV file - 8 bit unsigned\n"); size = samples * channels * (samplebits >> 3); break; case AFMT_MU_LAW: printf("AU file - 8 bit muLaw\n"); size = samples * channels; samplebits = 8; break; } printf ("Channels: %d\n", channels); printf ("Sample Rate: %d\n", (int)samplerate); printf ("Sample Bits: %d\n", samplebits); printf ("samples: %d\n", (int)samples); /* Although the mixer has default volume settings, lets set the * volume for both channels to max */ ioctl (md, SOUND_MIXER_WRITE_VOLUME, (int)&maxVol); /* Set the device in proper mode for audio form characteristics */ ioctl (sd, SNDCTL_DSP_CHANNELS, (int)&channels); ioctl (sd, SNDCTL_DSP_SPEED, (int)&samplerate); ioctl (sd, SNDCTL_DSP_SETFMT, (int)&format); /* Although the driver has a default fragment size, lets set * to a size of 4k and use 2 fragments. * The argument to this call is an integer encoded as 0xMMMMSSSS * (in hex). The 16 least significant bits determine the * fragment size. The size is 2^SSSS. For example SSSS=0008 gives * fragment size of 256 bytes (2^8). The minimum is 16 bytes (SSSS=4) * and the maximum is total buffer size/2. Some devices or processor * architectures may require larger fragments - in this case the * requested fragment size is automatically increased. */ blockSize = (2 << 16) | 12; ioctl (sd, SNDCTL_DSP_SETFRAGMENT, (int)&blockSize); /* get the maximum data transfer size and allocate buffer. The * size of the buffer to pass to the audio device is such that * each buffer is the maximum that the audio device can handle * without blocking. It is important that the buffer size * be a multiple of the fragment size. */ ioctl (sd, SNDCTL_DSP_GETOSPACE, (int)&info); blockSize = info.fragstotal * info.fragsize; buffer = malloc (blockSize); if (!buffer) { close (fd); return -1; } /* Loop reading audio file and sending to audio device */ while (size > 0) { /* If the audio stream has more than the block size, then * select a read of the block size, otherwise only * read the remaining data from the audio stream. */ buffer_size = size > blockSize ? blockSize : size; /* Read a block of audio data */ i = read (fd, (char *)buffer, buffer_size); /* Send audio data to audio device */ write (sd, (char *)buffer, buffer_size); /* Optionally use the select processing */#ifdef USE_SELECT /* Pend until write complete */ FD_ZERO (&writeFD); FD_SET (sd, &writeFD); select (FD_SETSIZE, NULL, &writeFD, NULL, NULL);#endif /* USE_SELECT */ /* Update remaining size of audio data */ size -= buffer_size; } /* Close the audio file and the audio device */ free (buffer); close (fd); close (sd); close (md); return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -