This is sndio.c in view mode; [Download] [Up]
#import "sndio.h" int main(int argc, char *argv[]) { char *filename, // input soundfile name *cbegi, // for begin frame input char *cendi, // for end frame input char *cfmati, // input format string (if headless) *cchani, // input # channels string (if headless) *csrate, // desired output sample rate as string *info, // for output header info string *new_info, // new info for output header *cbego, // for begin frame input char *cendo, // for end frame input char *cfmato; // output format char int pipe_in, // is input a pipe flag otty, // is output tty flag overwrite, // overwrite/pad output file headi, // no input header flag heado, // write header to output flag begi; // first sample to copy unsigned int endi; // last sample to copy int fmati, // input format value chani, // # of input channel (if headless) srate, // output sample rate dataSize, // size of sample data infoSize, // size of header info bego, // first sample to overwrite endo, // last sample to overwrite chano, // # of output channels fmato; // output format value char efmati, // end sample input format char efmato, // end sample output format char infotype, // header info field type ch; // tmp used with crack() FILE *infofp = NULL; // header info file pointer SNDSoundStruct *sndin,*sndout; // input and output soundfile pointers short *s_top; // pointers to input samples float *f_top; struct stat buf_size; // size of headless input file int clip, // ftos() clipped flag err; // snd errors short s_pad = 0; // output padding values float f_pad = 0.0; cbegi = NULL; // set up default values and flags cendi = NULL; cfmati = NULL; cchani = NULL; chanspec = NULL; csrate = NULL; info = NULL; new_info = NULL; cbego = NULL; cendo = NULL; cfmato = NULL; in_index = 'x'; // x is filler out_index = 'x'; // x is filler clip = NO; overwrite = NO; sndin = NULL; sndout = NULL; heado = YES; headi = YES; begi = 0; fmati = SND_FORMAT_LINEAR_16; chani = 1; srate = SND_RATE_HIGH; infoSize = 4; ascii_in = NO; ascii_out = NOTSET; // set up user defined variables itty = isatty(0); // 0 == stdin otty = isatty(1); // 1 == stdout // was != NULL while((ch = crack(argc,argv,"b|e|d|f|c|r|I|i|a|B|E|D|F|C|A|Hu",0)) != 0) { switch(ch) { case 'b': cbegi = arg_option; break; case 'e': efmati = ch; cendi = arg_option; break; case 'd': efmati = ch; cendi = arg_option; break; case 'f': cfmati = arg_option; break; // no input header input format case 'c': cchani = arg_option; break; // no input header input chan # case 'r': csrate = arg_option; break; // no input header input srate case 'a': ascii_in = YES; in_index = *arg_option; break; // arabic input case 'I': infotype = ch; new_info = arg_option; break; case 'i': infotype = ch; new_info = arg_option; break; case 'B': cbego = arg_option; overwrite = YES; break; case 'E': efmato = ch; cendo = arg_option; overwrite = YES; break; case 'D': efmato = ch; cendo = arg_option; overwrite = YES; break; case 'F': cfmato = arg_option; break; case 'C': chanspec = arg_option; break; case 'A': ascii_out = YES; // force arabic output out_index = *arg_option; break; case 'H': heado = NO; break; // no output header case 'u': usage(0); // help (usage) default: usage(1); } } if(itty) { // input is a file (i.e. not a pipe) pipe_in = NO; if(argc == arg_index) { // no file on commandline fprintf(stderr,"sndio error: No input file.\n"); exit(2); } filename = argv[arg_index]; if((err = SNDReadSoundfile(filename,&sndin)) == SND_ERR_NONE) ifp = NULL; else if(err == SND_ERR_NOT_SOUND) { // no sndheader input file if((ifp = fopen(filename,"r")) == NULL) { fprintf(stderr,"sndio error: Can't open `%s'.\n",filename); exit(3); } headi = NO; } else check_error(err); // snd exit mode ofp = stdout; // output cannot be a file } else { // input is a pipe pipe_in = YES; ifp = stdin; err = SNDReadHeaderFromStream(&sndin,ifp); if(err == SND_ERR_NOT_SOUND) headi = NO; // no sndheader else if(err != SND_ERR_NONE) check_error(err); // sndheader bad if(argc != arg_index) { // output file found on commandline if(ascii_out == NOTSET) ascii_out = NO; // not ascii unless user says it is filename = argv[arg_index]; if((ofp = fopen(filename,"r+")) == NULL) { // does file exist (overwrite) if((ofp = fopen(filename,"w")) == NULL) { // create new file fprintf(stderr,"sndio error: Can't open `%s'.\n",filename); exit(4); } } } else ofp = stdout; } if(ascii_out == NOTSET) { if(otty) ascii_out = YES; else ascii_out = NO; } if(ascii_out == YES) heado = NO; // if output is tty (ascii) if(new_info != NULL) { // new sndheader "info" from user if(infotype == 'I') { infoSize = (strlen(new_info)) + 1; if(infoSize < 4) infoSize = 4; info = (char *) malloc(sizeof(char) * infoSize); strncpy(info,new_info,infoSize - 1); } else if(infotype == 'i') { if((infofp = fopen(new_info,"r")) == NULL) { fprintf(stderr,"sndio error: Can't open `%s'.\n",new_info); exit(5); } stat(new_info,&buf_size); infoSize = buf_size.st_size + 1; if(infoSize < 4) infoSize = 4; info = (char *) malloc(sizeof(char) * infoSize); fread(info,sizeof(char),infoSize,infofp); fclose(infofp); } } if(headi == YES) { // get input header info fmati = sndin->dataFormat; // is format supported? if(fmati != SND_FORMAT_LINEAR_16 && fmati != SND_FORMAT_FLOAT ) check_error(SND_ERR_BAD_FORMAT); chani = sndin->channelCount; srate = sndin->samplingRate; dataSize = sndin->dataSize; if(info == NULL) { infoSize = sndin->dataLocation - (sizeof(int) * HEADNOINFO); if(infoSize < 4) infoSize = 4; info = (char *) malloc(sizeof(char) * infoSize); strncpy(info,sndin->info,infoSize - 1); } } else { // create input header info if(cfmati != NULL) { if(*cfmati == SND16BITSHORT) fmati = SND_FORMAT_LINEAR_16; else if(*cfmati == SND32BITFLOAT) fmati = SND_FORMAT_FLOAT; else check_error(SND_ERR_BAD_FORMAT); } if(cchani != NULL) chani = sfexpr(cchani,1.0); if(csrate != NULL) srate = sfexpr(csrate,1.0); if(pipe_in == NO && ascii_in == NO) { stat(filename,&buf_size); // get ->dataSize from binary file dataSize = buf_size.st_size; } else dataSize = 0; // dataSize should not be used but want to be safe } if(cfmato == NULL) fmato = fmati; // set data format for output else { if(*cfmato == SND16BITSHORT) fmato = SND_FORMAT_LINEAR_16; else if(*cfmato == SND32BITFLOAT) fmato = SND_FORMAT_FLOAT; else check_error(SND_ERR_BAD_FORMAT); } if(cbegi != NULL) { // do boundary calculations on sample frames begi = (sfexpr(cbegi,(float) srate)) * chani; if (begi < 0) begi = 0; } if(cendi != NULL) { if(efmati == 'e') endi = (sfexpr(cendi,(float) srate)) * chani; else /* == 'd' */ endi = (begi + sfexpr(cendi,(float) srate)) * chani; if(pipe_in == NO && ascii_in == NO) { // can't be larger than input data if(fmati == SND_FORMAT_LINEAR_16 && endi > (dataSize >> 1)) endi = dataSize >> 1; else if(fmati == SND_FORMAT_FLOAT && endi > (dataSize >> 2)) endi = dataSize >> 2; } else if(endi < 0) endi = 0; // just because its there } else if(pipe_in == NO && ascii_in == NO) { // set to end of file if(fmati == SND_FORMAT_LINEAR_16) endi = dataSize >> 1; else if(fmati == SND_FORMAT_FLOAT) endi = dataSize >> 2; } else endi = MAXFILESIZE; // set to monster size chano = setchan(chanspec,chani); // set output channels if(chano == NO) check_error(SND_ERR_BAD_CHANNEL); // no channels remain! if(cbego != NULL) bego = (sfexpr(cbego,(float) srate)) * chano; else bego = 0; if(cendo != NULL) { if(efmato == 'E') endo = (sfexpr(cendo,(float) srate)) * chani; else /* == 'D' */ endo = (bego + sfexpr(cendo,(float) srate)) * chani; } else endo = endi; if(heado == YES) { // alloc output header check_error(SNDAlloc(&sndout,0,fmato,srate,chano,infoSize)); if(info != NULL) strncpy(sndout->info,info,infoSize - 1); fwrite((void *) sndout,sizeof(char),sndout->dataLocation,ofp); } samrate = (float) srate; // set sample rate for ascii output if(overwrite == YES && ascii_out == NO) { // advance output pointer of pad switch(fmato) { case SND_FORMAT_LINEAR_16: // by shorts if(bego > 0) fseek(ofp,(unsigned long) (bego * sizeof(short)),SEEK_CUR); else if(bego < 0) { for( ; bego < 0; bego++) fwrite((void *) &s_pad,sizeof(short),1,ofp); } break; case SND_FORMAT_FLOAT: // by floats if(bego > 0) fseek(ofp,(unsigned long) (bego * sizeof(float)),SEEK_CUR); else if(bego < 0) { for( ; bego < 0; bego++) fwrite((void *) &f_pad,sizeof(float),1,ofp); } break; } } switch(fmati) { // convert and output input data case SND_FORMAT_LINEAR_16: // input is short if(ascii_in == YES) tobegi(begi,SND_FORMAT_LINEAR_16); else if(pipe_in == NO && headi == YES) { // set pointer to short samples s_top = (void *) (((char *) sndin) + sndin->dataLocation); s_top = (s_top + begi); } else if(begi != 0) fseek(ifp,(unsigned long) (begi * sizeof(short)),SEEK_CUR); switch(fmato) { case SND_FORMAT_LINEAR_16: // output is short if(ascii_in == YES) stosa(ifp,begi,endi,chani); // ascii input else if(pipe_in == YES) stosp(ifp,begi,endi,chani); // pipe in else if(headi == YES) stos(s_top,begi,endi,chani); // sndfile in else stoshf(ifp,begi,endi,chani); // headless file break; case SND_FORMAT_FLOAT: // output is float if(ascii_in == YES) stofa(ifp,begi,endi,chani); else if(pipe_in == YES) stofp(ifp,begi,endi,chani); else if(headi == YES) stof(s_top,begi,endi,chani); else stofhf(ifp,begi,endi,chani); break; } break; case SND_FORMAT_FLOAT: // input is float if(ascii_in == YES) tobegi(begi,SND_FORMAT_FLOAT); else if(pipe_in == NO && headi == YES) { // set pointer to float samples f_top = (void *) (((char *) sndin) + sndin->dataLocation); f_top = (f_top + begi); } else if(begi != 0) fseek(ifp,(unsigned long) (begi * sizeof(float)),SEEK_CUR); switch (fmato) { case SND_FORMAT_LINEAR_16: // output is short if(ascii_in == YES) clip = ftosa(ifp,begi,endi,chani); else if(pipe_in == YES) clip = ftosp(ifp,begi,endi,chani); else if(headi == YES) clip = ftos(f_top,begi,endi,chani); else clip = ftoshf(ifp,begi,endi,chani); if(clip != 0) { fprintf(stderr,"\nsndio error: %d clipped samples.\n\n",clip); } break; case SND_FORMAT_FLOAT: // output is float if(ascii_in == YES) ftofa(ifp,begi,endi,chani); else if(pipe_in == YES) ftofp(ifp,begi,endi,chani); else if(headi == YES) ftof(f_top,begi,endi,chani); else ftofhf(ifp,begi,endi,chani); break; } break; default: break; // can't happen! safty net } if(endo > endi) { // pad output file int inc,floor,y = -1; switch(fmato) { case SND_FORMAT_LINEAR_16: // pad is short if(ascii_out == YES) { // and ascii if(out_index == 's') { // sample indexed for(inc = endi; inc < endo; inc++) { if(chans[++y >= chani ? (y = 0) : y]) { fprintf(ofp,"%d\t0\n",(int) inc / chani); } } } else if(out_index == 't') { // time indexed for(inc = endi; inc < endo; inc++) { if(chans[++y >= chani ? (y = 0) : y]) { floor = (int) inc / chani; fprintf(ofp,"%f\t0\n",((float) floor) / samrate); } } } else { // no index for(inc = endi; inc < endo; inc++) { if(chans[++y >= chani ? (y = 0) : y]) fprintf(ofp,"0\n"); } } } else { for(inc = endi; inc < endo; inc++) { if(chans[++y >= chani ? (y = 0) : y]) { fwrite((void *) &s_pad,sizeof(short),1,ofp); } } } break; case SND_FORMAT_FLOAT: // pad is float if(ascii_out == YES) { // and ascii if(out_index == 's') { // sample indexed for(inc = endi; inc < endo; inc++) { if(chans[++y >= chani ? (y = 0) : y]) { fprintf(ofp,"%d\t0.0\n",(int) inc / chani); } } } else if(out_index == 't') { // time indexed for(inc = endi; inc < endo; inc++) { if(chans[++y >= chani ? (y = 0) : y]) { floor = (int) inc / chani; fprintf(ofp,"%f\t0.0\n",((float) floor) / samrate); } } } else { // no index for(inc = endi; inc < endo; inc++) { if(chans[++y >= chani ? (y = 0) : y]) fprintf(ofp,"0.0\n"); } } } else { for(inc = endi; inc < endo; inc++) { if(chans[++y >= chani ? (y = 0) : y]) { fwrite((void *) &f_pad,sizeof(float),1,ofp); } } } break; } } if(ifp != NULL) fclose(ifp); // clean house if(ofp != NULL) fclose(ofp); free(info); SNDFree(sndin); SNDFree(sndout); exit(0); } // advances ascii input stream to point begin void tobegi(long begin,int format) { unsigned long inc; // actual number of smaples in sobuf[] switch(format) { // advance pointer thru output data case SND_FORMAT_LINEAR_16: // advance shorts switch(in_index) { case 's': for(inc = 0; inc < begin; inc++) { if(fscanf(ifp,"%*d %*d") == EOF) break; } break; case 't': for(inc = 0; inc < begin; inc++) { if(fscanf(ifp,"%*f %*d") == EOF) break; } break; default: for(inc = 0; inc < begin; inc++) { if(fscanf(ifp,"%*d") == EOF) break; } break; } break; case SND_FORMAT_FLOAT: // advance floats switch(in_index) { case 's': for(inc = 0; inc < begin; inc++) { if(fscanf(ifp,"%*d %*f") == EOF) break; } break; case 't': for(inc = 0; inc < begin; inc++) { if(fscanf(ifp,"%*f %*f") == EOF) break; } break; default: for(inc = 0; inc < begin; inc++) { if(fscanf(ifp,"%*f") == EOF) break; } break; } break; } } int check_error(int err) { if(err) { fprintf(stderr,"sndio error: %s\n",SNDSoundError(err)); exit(err); } return err; } int usage(int x) { fprintf(stderr,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", "\nusage:\tsndio [flags] input_file > output\n", "\tsndio [flags] output_file < input\n", "\tsndio [flags] < input > output\n", "flags:\t-bN\tsets begin time of input to N [default: 0.0].\n", "\t-eN\tsets end time of input to N [end of input data].\n", "\t-dN\tsets duration of input to N [end of input data].\n", "\t-aX\tarabic (ascii) input. X denotes sample indexing format.\n", "\t\tX = t, time index; X = s, sample numbers; no X, no index.\n", "\t-fX\tsets format for headless input to X (see -F below) [s].\n", "\t-cN\tsets number of channels for headless input to N [1].\n", "\t-rN\tsets sample rate of headless input to N [44100].\n", "\t-IS\tS is an info string (without white chars) for output header.\n", "\t-iS\tS is an file name containing info for output header.\n", "\t-BN\tsets output begin time to N (for padding or overwrite) [0.0].\n", "\t-EN\tsets output end time to N (for padding) [-e value].\n", "\t-DN\tsets output duration to N (for padding) [-e value].\n", "\t-CS\tS is a comma-separated list of selected output channels.\n", "\t-FX\tX overrides (converts) default output format, X can be:\n", "\t\t\tf - pipe: 32 bit floats; tty: floating point.\n", "\t\t\ts - pipe: 16 bit ints; tty: integer.\n", "\t-AX\tforce arabic output, X sets indexing format (see -a above).\n", "\t-H\tsuppress generating sound file header for output.\n", "\t-u\tprints this usage information.\n" ); exit(x); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.