FreeBSD Bugzilla – Attachment 6699 Details for
Bug 14990
new-pcm caveats
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
file.shar
file.shar (text/plain), 18.59 KB, created by
Vladimir N.Silyaev
on 1999-11-19 02:30:00 UTC
(
hide
)
Description:
file.shar
Filename:
MIME Type:
Creator:
Vladimir N.Silyaev
Created:
1999-11-19 02:30:00 UTC
Size:
18.59 KB
patch
obsolete
># This is a shell archive. Save it in a file, remove anything before ># this line, and then unpack it by entering "sh file". Note, it may ># create directories; files and directories will be owned by you and ># have default permissions. ># ># This archive contains: ># ># Makefile ># README ># sound.c ># >echo x - Makefile >sed 's/^X//' >Makefile << 'END-of-Makefile' >XPROG= sound >XSRCS= sound.c >XLDADD= -lm >XNOMAN= yes >X#DEBUG_FLAGS= -g >XCFLAGS= -Wall >X >X.include <bsd.prog.mk> >END-of-Makefile >echo x - README >sed 's/^X//' >README << 'END-of-README' >XSound driver testing utility. >X >XThis program simple produce series of harmonic signals and silence to >Xsoundcard. When program launched without arguments, it's produce >X5 secs 1KHz tone, than 3 secs pause, and than again tone and pause. >XWhen tone produced status changed from 'sound playing' to 'sound sync', >Xand when pause status changed to 'silent'. When sound card's working >Xproperly the signal must be to have right tone frequency and changing >Xstatus must be synchronized within change of soundcard output. >X >XThis program have the following command line arguments: >X-h - Print short information about command line arguments >X-? - the same >X-i - Catch INT signal, so you may press Ctrl-C, and sound output must >X my stay the same, without any clicks or noise. >X-d <device> >X Change device to 'device', default /dev/dsp >X-T <periods> >X Change number of tone/pause to 'periods', default 2 >X-a <nsec> >X Change duration of tone to 'nsec', default 5 >X-s <nsec> >X Change duration of pause to 'nsec', default 2 >X-p <freq> >X Change frequency of generated tone, default 1000Hz >X-f <formats> >X Set list of formats, delimited by coma (','), for each of >X which the sound card will be tested, for example U8,STEREO|U16_LE. >X Default STEREO|U16_LE >X-r <rates> >X Set list of rates, delimited by coma (','), for each of >X which the sound card will be tested, for example 8000,11050. >X Default 44100. >X-b <blocksize> >X Set the size of blocks, which will be used as arg to write routine. >X >X >XAuthor: >XVladimir N. Silyaev vns@delta.odessa.ua >X >END-of-README >echo x - sound.c >sed 's/^X//' >sound.c << 'END-of-sound.c' >X/* >X * sound.c >X * >X * Soundcard/driver testing utility >X * >X * Copyright by Vladimir N. Silyaev 1999 >X * >X * Redistribution and use in source and binary forms, with or without >X * modification, are permitted provided that the following conditions are >X * met: 1. Redistributions of source code must retain the above copyright >X * notice, this list of conditions and the following disclaimer. 2. >X * Redistributions in binary form must reproduce the above copyright notice, >X * this list of conditions and the following disclaimer in the documentation >X * and/or other materials provided with the distribution. >X * >X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY >X * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >X * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR >X * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR >X * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER >X * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >X * SUCH DAMAGE. >X * >X * $Id: sound.c,v 1.7 1999/11/19 01:05:13 vsilyaev Exp $ >X * >X */ >X >X#include <unistd.h> >X#include <stdlib.h> >X#include <stdio.h> >X#include <strings.h> >X#include <string.h> >X#include <fcntl.h> >X#include <math.h> >X#include <ctype.h> >X#include <assert.h> >X#include <errno.h> >X#include <signal.h> >X#include <err.h> >X#include <sysexits.h> >X#include <sys/time.h> >X#include <sys/soundcard.h> >X >X#define DEFAULT_RATE 44100 >X#define DEFAULT_FORMAT (AFMT_U16_LE|AFMT_STEREO) >X#define DEFAULT_FREQ 1000 >X#define DEFAULT_PLAY_TIME 5 >X#define DEFAULT_PAUSE_TIME 3 >X#define DEFAULT_NPERIODS 2 >X#define DEFAULT_BLOCK_SIZE 16384 >X >Xtypedef struct{ >X u_long *values; >X size_t length; >X} l_array; >X >Xtypedef struct { >X l_array formats; >X l_array rates; >X char *device; >X int play_freq; >X int play_time; >X int pause_time; >X int nperiods; >X int catch_sigint; >X int write_block_size; >X} sound_options; >X >Xstatic sound_options _app_options; >Xstatic sound_options *app_options=&_app_options; >X >Xtypedef struct { >X char *name; >X int fd; /* File descriptor */ >X snd_capabilities info; >X u_long format,rate; >X} sound_info ; >Xstatic int sound_change_param(sound_info *snd, u_long rate, u_long format); >X >Xtypedef struct { >X u_long format; >X u_long rate; >X int freq; >X float f_freq; >X int nsamples; >X int sample_len; >X int align; >X float t_sample; >X union { >X void *data; >X u_int8_t *data8; >X u_int8_t (*data8_s)[2]; >X u_int16_t *data16; >X u_int16_t (*data16_s)[2]; >X } data; >X} sound_sample; >X >Xtypedef struct { >X u_long offset; /* in samples, not in bytes */ >X} sample_play; >X >Xstatic int >Xl_array_init(l_array *array) >X{ >X bzero(array, sizeof(*array)); >X array->values=NULL; >X array->length=0; >X return 0; >X} >X >Xstatic int >Xl_array_shutdown(l_array *array) >X{ >X free(array->values); >X return 0; >X} >X >Xstatic int >Xl_array_push(l_array *array, u_long value) >X{ >X array->values=realloc(array->values,(array->length+1)*sizeof(*array->values)); >X array->values[array->length++]=value; >X return 0; >X} >X >Xstatic int >Xl_array_get(l_array *array, int index, u_long *pvalues) >X{ >X if (index>=array->length) return -1; >X if (pvalues) *pvalues=array->values[index]; >X return 0; >X} >X >Xstatic int >Xsound_options_init(sound_options *options) >X{ >X bzero(options, sizeof(*options)); >X l_array_init(&options->formats); >X l_array_init(&options->rates); >X options->device=NULL; >X return 0; >X} >X >Xstatic int >Xsound_options_shutdown(sound_options *options) >X{ >X l_array_shutdown(&options->formats); >X l_array_shutdown(&options->rates); >X return 0; >X} >X >X >Xstatic const char fields_sep[] = ","; >X >Xstatic int >Xfill_rates(l_array *rates, char *str) >X{ >Xchar *word; >Xint rate; >X >X while ( (word=strsep(&str, fields_sep)) != NULL ) { >X rate = atoi(word); >X if (rate==0) { >X fprintf(stderr, "Invalid bit rate '%s'\n", word); >X continue; >X } >X l_array_push(rates, rate); >X } >X return 0; >X} >X >Xstatic const struct { >Xu_long bit; >Xconst char *name; >X} known_formats[] = { >X#define FORMAT(name) {AFMT_##name, #name} >X FORMAT(U8), >X FORMAT(U16_LE), >X FORMAT(STEREO) >X#undef FORMAT >X}; >X >Xstatic int >Xstricmp(const char *str1,const char *str2) >X{ >Xint ch1,ch2; >X >X for(;;) { >X ch1=*str1++; >X ch2=*str2++; >X ch1=toupper(ch1); >X ch2=toupper(ch2); >X if (ch1!=ch2) return ch1-ch2; >X if (ch1==0) return 0; >X } >X /* NOT REACHED */ >X} >X >Xstatic u_long >Xparse_format(const char *sformat) >X{ >Xchar *str_alloc=strdup(sformat); >Xconst int n_known_formats=sizeof(known_formats)/sizeof(*known_formats); >Xu_long format=0; >Xint i; >Xu_long bit; >Xint nbits=0; >Xchar *str,*word; >X >X str=str_alloc; >X while ( (word=strsep(&str, "|")) != NULL) { >X for (bit=0,i=0;i<n_known_formats;i++) { >X if (stricmp(known_formats[i].name, word)==0) { >X bit=known_formats[i].bit; >X break; >X } >X } >X if (!bit) { >X fprintf(stderr, "Unknown format specifier '%s'\n", word); >X } else { >X format|=bit; >X if (bit!=AFMT_STEREO) nbits++; >X } >X } >X if (nbits!=1) { >X format=0; >X } >X free(str_alloc); >X return format; >X} >X >Xstatic int >Xfill_formats(l_array *formats, char *str) >X{ >Xchar *word; >Xu_long format; >X >X while ( (word=strsep(&str, fields_sep)) != NULL ) { >X format = parse_format(word); >X if (format==0) >X fprintf(stderr, "Invalid format '%s'\n", word); >X else >X l_array_push(formats, format); >X } >X return 0; >X} >X >Xstatic void >Xusage(const char *name) >X{ >X fprintf(stderr, >X "usage: %s [-h/?] [-i] [-d <device>] [-T <periods>] [-a <nsec>] [-s <nsec>] [-p <freq>] [-f <formats>] [-r <rates>] [-b <blocksize>]" >X "\n", name); >X exit(EX_USAGE); >X} >X >Xstatic int >Xsound_options_fill(sound_options *options, int argc, char *argv[]) >X{ >Xint option; >X >X options->play_freq=0; >X options->play_time=0; >X options->pause_time=0; >X options->nperiods=0; >X options->device=NULL; >X options->catch_sigint=0; >X options->write_block_size=0; >X while( (option=getopt(argc, argv, "ib:d:T:a:s:p:r:f:h?")) != -1 ) { >X switch(option) { >X case 'i': >X options->catch_sigint=1; >X break; >X case 'd': >X options->device=strdup(optarg); >X break; >X case 'T': >X options->nperiods=atoi(optarg); >X break; >X case 'a': >X options->play_time=atoi(optarg); >X break; >X case 's': >X options->pause_time=atoi(optarg); >X break; >X case 'p': >X options->play_freq=atoi(optarg); >X break; >X case 'b': >X options->write_block_size=atoi(optarg); >X break; >X case 'r': >X fill_rates(&options->rates,optarg); >X break; >X case 'f': >X fill_formats(&options->formats,optarg); >X break; >X case 'h': >X case '?': >X default: >X usage(argv[0]); >X /* NOT REACHED */ >X } >X } >X if (l_array_get(&options->rates, 0, NULL)<0) >X l_array_push(&options->rates, DEFAULT_RATE); >X if (l_array_get(&options->formats, 0, NULL)<0) >X l_array_push(&options->formats, DEFAULT_FORMAT); >X if (options->play_freq<=0) { >X options->play_freq=DEFAULT_FREQ; >X } >X if (options->play_time<=0) { >X options->play_time=DEFAULT_PLAY_TIME; >X } >X if (options->pause_time<=0) { >X options->pause_time=DEFAULT_PAUSE_TIME; >X } >X if (options->nperiods<=0) { >X options->nperiods=DEFAULT_NPERIODS; >X } >X if (options->write_block_size<=0) { >X options->write_block_size=DEFAULT_BLOCK_SIZE; >X } >X if (options->device==NULL) { >X options->device=strdup("/dev/dsp"); >X } >X return 0; >X} >X >Xstatic int >Xfind_nearest_for_freq(int rate,int freq) >X{ >Xint i; >Xint nsamples; >Xfloat diff; >Xfloat min_diff=freq; >Xint min_periods=1; >X >X for (i=1;i<1024;i++) { >X nsamples=(int)ceil((i*(float)rate)/freq); >X diff=fabs(freq-rate/nsamples); >X if (diff<min_diff) { >X min_periods=i; >X } >X } >X return min_periods; >X} >X >Xstatic int >Xsample_init(sound_sample *sample, int format, int rate, int freq) >X{ >Xint i; >Xint nperiods; >Xfloat f_sample; >Xconst float amp=0.5; >Xint data8,data16; >X >X bzero(sample, sizeof(*sample)); >X sample->format=format; >X sample->rate=rate; >X sample->freq=freq; >X switch(format&~AFMT_STEREO) { >X case AFMT_U8: >X sample->sample_len=1; >X break; >X case AFMT_U16_LE: >X sample->sample_len=2; >X break; >X default: >X return -1; >X } >X if (format&AFMT_STEREO) sample->sample_len*=2; >X >X sample->align=sample->sample_len; >X nperiods=find_nearest_for_freq(rate,freq); >X sample->nsamples=(int)ceil((nperiods*(float)rate)/freq); >X#if 0 >X fprintf(stderr, "Real freq %.1f HZ\n",((float)nperiods*rate)/sample->nsamples); >X#endif >X sample->t_sample=(2*M_PI*nperiods)/sample->nsamples; >X sample->data.data=malloc(sample->nsamples*sample->sample_len); >X assert(sample->data.data); >X for (i=0;i<sample->nsamples;i++) { >X f_sample=amp*sin(sample->t_sample*i); >X data8=(int)floor(f_sample*128+0.5); >X data16=(int)floor(f_sample*32768+0.5); >X switch(format) { >X case AFMT_U8: >X sample->data.data8[i]=(u_int8_t)(data8+128); >X break; >X case AFMT_U8|AFMT_STEREO: >X sample->data.data8_s[i][0]= >X sample->data.data8_s[i][1]=(u_int8_t)(data8+128); >X break; >X case AFMT_U16_LE: >X sample->data.data16[i]=(u_int16_t)(data16+32768); >X break; >X case AFMT_U16_LE|AFMT_STEREO: >X sample->data.data16_s[i][0]= >X sample->data.data16_s[i][1]=(u_int16_t)(data16+32768); >X break; >X } >X } >X return 0; >X} >X >X >Xstatic int >Xsample_shutdown(sound_sample *sample) >X{ >X free(sample->data.data); >X sample->data.data=0; >X return 0; >X} >X >Xstatic int >Xsample_play_init(sample_play *splay) >X{ >X bzero(splay, sizeof(*splay)); >X return 0; >X} >X >Xtypedef struct { >X u_long remain; >X u_int8_t *dest; >X unsigned offset; >X size_t bufsize; >X u_long ncopy; >X} sound_dest_helper; >X >Xstatic void >Xcopy_data_helper(sound_sample *sample, sample_play *splay, sound_dest_helper *helper) >X{ >Xsize_t ncopy; >X >X ncopy=helper->remain*sample->sample_len; >X memcpy(helper->dest, sample->data.data8+helper->offset, ncopy); >X helper->dest+=ncopy; >X helper->ncopy+=ncopy; >X helper->bufsize-=helper->remain; >X splay->offset+=helper->remain; >X} >X >Xstatic u_long >Xsample_play_fill_data(sound_sample *sample, sample_play *splay, void *buf, size_t bufsize) >X{ >Xsound_dest_helper helper; >X >X assert(bufsize%sample->sample_len==0); >X helper.bufsize = bufsize/sample->sample_len; >X helper.remain = splay->offset%sample->nsamples; >X helper.dest = (u_int8_t*)buf; >X helper.ncopy = 0; >X if (helper.remain) { >X helper.offset = helper.remain * sample->sample_len; >X helper.remain = sample->nsamples - helper.remain; >X if (helper.remain>helper.bufsize) helper.remain=helper.bufsize; >X copy_data_helper(sample, splay, &helper); >X } >X while (helper.bufsize>=sample->nsamples) { >X helper.offset=0; >X helper.remain=sample->nsamples; >X copy_data_helper(sample, splay, &helper); >X } >X if (helper.bufsize) { >X helper.offset=0; >X helper.remain=helper.bufsize; >X copy_data_helper(sample, splay, &helper); >X } >X return helper.ncopy; >X} >X >Xstatic int >Xsample_play_shutdown(sample_play *splay) >X{ >X return 0; >X} >X >Xstatic int >Xsound_open(sound_info *snd) >X{ >Xsnd_capabilities info; >Xint rc; >Xint sound; >X >X bzero(snd, sizeof(*snd)); >X snd->name=strdup(app_options->device); >X sound=open(snd->name ,O_RDWR); >X >X if (sound<0) { >X err(EX_UNAVAILABLE,snd->name); >X } >X >X rc=ioctl(sound,AIOGCAP,&info); >X if (rc<0) return rc; >X #if 0 >X printf("soundcard capability: rate_min %lu, rate_max %lu,\n" >X "formats %08lx, \n" >X "bufsize %lu,\n" >X "mixers %08lx, inputs %08lx, left %u, right %u\n", >X info.rate_min,info.rate_max, >X info.formats, >X info.bufsize, >X info.mixers, info.inputs, info.left, info.right); >X #endif >X snd->info=info; >X snd->fd=sound; >X return 0; >X} >X >Xstatic void wait_for_time(const struct timeval *stop) >X{ >Xstruct timeval current,remain_tv; >Xstruct timespec remain; >Xint rc; >X >X gettimeofday(¤t,NULL); >X timersub(stop, ¤t, &remain_tv); >X TIMEVAL_TO_TIMESPEC(&remain_tv, &remain); >X /* printf("%d,%ld\n", (int)remain.tv_sec,remain.tv_nsec); */ >X for (;;) { >X rc=nanosleep(&remain,&remain); >X if (rc!=-1 || errno!=EINTR) break; >X } >X return; >X} >X >X#define SOUND_WRITE 1 >X >Xstatic int >Xsound_play(sound_info *snd,sound_sample *sample) >X{ >Xu_int8_t *data,*pdata; >Xsample_play play; >Xstruct timeval begin,stop; >Xconst int play_time=app_options->play_time,pause_time=app_options->pause_time; >Xu_long nsamples,offset; >Xunsigned nwrite,nwrote; >Xint i; >Xint rc; >Xint block_size; >X >X block_size=app_options->write_block_size; >X data=malloc(block_size); >X assert(data); >X nsamples=sample->rate*play_time*sample->sample_len; >X for (i=0;i<app_options->nperiods;i++) { >X sample_play_init(&play); >X gettimeofday(&begin,NULL); >X fprintf(stderr,"\rsound playing%20c\r", ' '); >X for (offset=0;offset<nsamples;) { >X if (nsamples-offset>block_size) { >X nwrite=block_size; >X } else { >X nwrite=nsamples-offset; >X nwrite=((nwrite+sample->align-1)/sample->align)*sample->align; >X } >X sample_play_fill_data(sample,&play,data,nwrite); >X assert((nwrite%sample->align)==0); >X #if SOUND_WRITE >X for (nwrote=0,pdata=data;nwrite;) { >X rc=write(snd->fd,pdata,nwrite); >X if (rc<0) { >X warn("Error on writing %s",snd->name); >X if (errno == EINTR) continue; >X break; >X } >X nwrote+=rc; >X pdata+=rc; >X nwrite-=rc; >X } >X #else >X nwrote=nwrite; >X #endif >X offset+=nwrote; >X } >X #if SOUND_WRITE >X /* >X rc=ioctl(snd->fd, SNDCTL_DSP_SYNC, NULL); >X if (rc<0) warn("Error on sync at %s",snd->name); >X printf(" sync done\n"); >X */ >X #endif >X stop=begin; >X stop.tv_sec+=play_time; >X fprintf(stderr,"\rsound sync%20c\r", ' '); >X wait_for_time(&stop); >X fprintf(stderr,"\rsilent%20c\r", ' '); >X stop=begin; >X stop.tv_sec+=play_time+pause_time; >X wait_for_time(&stop); >X #if 0 >X sound_change_param(snd, snd->rate, snd->format); >X #endif >X sample_play_shutdown(&play); >X } >X free(data); >X return 0; >X} >X >X >Xstatic int >Xsound_sync(sound_info *snd) >X{ >X close(snd->fd); >X snd->fd=open(snd->name ,O_RDWR); >X >X if (snd->fd<0) { >X err(EX_UNAVAILABLE,snd->name); >X } >X return 0; >X} >X >Xchar * >Xformat2str(u_long format, u_long rate, char *dest, size_t maxlen) >X{ >Xchar str[64]; >Xconst char *name; >Xconst char *stereo; >X >X switch(format&~AFMT_STEREO) { >X case AFMT_U8: >X name="Unsigned 8-bit"; >X break; >X case AFMT_U16_LE: >X name="Unsigned 16-bit, Little endian"; >X break; >X default: >X snprintf(str,sizeof(str),"Unknown [0x%08lx]", format&~AFMT_STEREO); >X name=str; >X break; >X } >X if (format&AFMT_STEREO) stereo="Stereo, "; >X else stereo=""; >X snprintf(dest,maxlen,"%s%s rate %lu", stereo, name, rate); >X return dest; >X} >X >Xstatic int >Xsound_change_param(sound_info *snd, u_long rate, u_long format) >X{ >Xsnd_chan_param param; >Xint rc; >Xchar str[256]; >Xchar str2[256]; >X >X rc=sound_sync(snd); >X if (rc<0) return rc; >X bzero(¶m,sizeof(param)); >X param.play_rate=rate; >X param.play_format=format; >X rc=ioctl(snd->fd, AIOSFMT, ¶m); >X if (rc<0) { >X warn("Device %s: format %s rejected", >X snd->name, format2str(format, rate, str, sizeof(str))); >X return rc; >X } >X if (param.play_format!=format || param.play_rate!=rate) { >X fprintf(stderr, "Device %s: format %s unsupported, " >X "has been changed to %s\n", >X snd->name, >X format2str(format, rate, str, sizeof(str)), >X format2str(param.play_format, param.play_rate, >X str2, sizeof(str2)) >X ); >X return -1; >X } >X snd->format=format; >X snd->rate=rate; >X return 0; >X} >X >Xstatic int >Xsound_test(sound_info *snd) >X{ >Xint rate_index, format_index; >Xu_long rate, format; >Xint rc; >Xsound_sample sample; >Xchar sformat[256]; >X >X for(rate_index=0;l_array_get(&app_options->rates, rate_index, &rate)>=0;rate_index++) { >X for(format_index=0;l_array_get(&app_options->formats, format_index, &format)>=0; format_index++) { >X rc=sound_change_param(snd, rate, format); >X if (rc<0) continue; >X format2str(format, rate, sformat, sizeof(sformat)); >X fprintf(stderr, "%s%30c\n", sformat,' '); >X rc=sample_init(&sample, format, rate, app_options->play_freq); >X if (rc<0) { >X fprintf(stderr, "Unsupported format %s\n", sformat); >X continue; >X } >X sound_play(snd, &sample); >X sample_shutdown(&sample); >X } >X } >X return 0; >X} >X >X >Xstatic int >Xsound_close(sound_info *snd) >X{ >X if (snd->fd>0) close(snd->fd); >X snd->fd=-1; >X free(snd->name); >X snd->name=NULL; >X return 0; >X} >X >Xstatic void >Xsig_int_handler(int dummy) >X{ >X} >X >Xint main(int argc, char **argv) >X{ >Xsound_info snd; >X >X sound_options_init(app_options); >X sound_options_fill(app_options,argc,argv); >X if (app_options->catch_sigint) >X signal(SIGINT,sig_int_handler); >X sound_open(&snd); >X sound_test(&snd); >X sound_close(&snd); >X sound_options_shutdown(app_options); >X return 0; >X} >END-of-sound.c >exit
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 14990
:
6698
| 6699