| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /*
- * Copyright (c) 1983-2023 Richard Dobson and Composers Desktop Project Ltd
- * http://people.bath.ac.uk/masrwd
- * http://www.composersdesktop.com
- * This file is part of the CDP System.
- * The CDP System is free software; you can redistribute it
- * and/or modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * The CDP System is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with the CDP System; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
- /* chorder : reorder channels in m/c file */
- /* Jan 2010: corrected behaviour with out of range order chars */
- /* July 2010 removed spurious premature call to usage() */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <portsf.h>
- /* set size of multi-channel frame-buffer */
- #define NFRAMES (1024)
- /* TODO define program argument list, excluding flags */
- enum {ARG_PROGNAME,ARG_INFILE,ARG_OUTFILE,ARG_ORDERSTRING,ARG_NARGS};
- #define N_BFORMATS (10)
- static const int bformats[N_BFORMATS] = {2,3,4,5,6,7,8,9,11,16};
- #ifdef unix
- /* in portsf.lib */
- extern int stricmp(const char *a, const char *b);
- #endif
- void usage(void)
- {
- fprintf(stderr,"\nCDP MCTOOLS: CHORDER V1.2 (c) RWD,CDP 2009,2010\n");
- fprintf(stderr,
- "Reorder soundfile channels.\n"
- "Usage: chorder infile outfile orderstring\n"
- " orderstring = any combination of characters a-z inclusive.\n"
- " Infile channels are mapped in order as a=1,b=2...z=26\n"
- " (For example: channels in a 4-channel file are represented by the\n"
- " characters abcd; any other character is an error).\n"
- " Characters must be lower case, and may be used more than once.\n"
- " Duplicate characters duplicate the corresponding input channel.\n"
- " The zero character (0) may be used to set a silent channel.\n"
- " A maximum of 26 channels is supported for both input and output.\n"
- " NB: infile (WAVEX) speaker positions are discarded.\n"
- " The .amb extension is supported for the outfile.\n\n"
- );
- }
- int main(int argc, char* argv[])
- {
- PSF_PROPS inprops,outprops;
- long framesread;
- /* init all dynamic resources to default states */
- unsigned int i;
- int halfsec;
- unsigned int framepos;
- long outsize;
- int ifd = -1,ofd = -1;
- int error = 0;
- PSF_CHPEAK* peaks = NULL;
- psf_format outformat = PSF_FMT_UNKNOWN;
- unsigned long nframes = 1;
- float* inframe = NULL;
- float* outframe = NULL;
- float* orderptr[26];
- char* argstring = NULL;
- unsigned int rootchar = 'a';
- unsigned int maxchar = 'z';
- unsigned int nchars,nzeros = 0;
- unsigned int max_inchar;
- MYLONG peaktime;
-
- /* CDP version number */
- if(argc==2 && (stricmp(argv[1],"--version")==0)){
- printf("1.2.\n");
- return 0;
- }
- /* process any optional flags: remove this block if none used! */
- if(argc > 1){
- char flag;
- while(argv[1][0] == '-') {
- flag = argv[1][1];
- switch(flag){
- /*TODO: handle any flag arguments here */
- case('\0'):
- printf("Error: missing flag name\n");
- return 1;
- default:
- break;
- }
- argc--;
- argv++;
- }
- }
- if(argc < ARG_NARGS){
- printf("insufficient arguments.\n");
- usage();
- return 1;
- }
-
- /* initial check of charstring */
- argstring = argv[ARG_ORDERSTRING];
- nchars = strlen(argstring);
- if(nchars > 26) {
- printf("error: order string too long.\n");
- return 1;
- }
-
- /* always startup portsf */
- if(psf_init()){
- printf("unable to start portsf\n");
- return 1;
- }
-
- ifd = psf_sndOpen(argv[ARG_INFILE],&inprops,0);
- if(ifd < 0){
- printf("Error: unable to open infile %s\n",argv[ARG_INFILE]);
- error++;
- goto exit;
- }
- outsize = psf_sndSize(ifd);
- if(outsize <= 0){
- fprintf(stderr,"chorder: infile is empty!\n");
- psf_sndClose(ifd);
- return 1;
- }
- inframe = (float*) malloc(nframes * inprops.chans * sizeof(float));
- if(inframe==NULL){
- puts("No memory!\n");
- error++;
- goto exit;
- }
- /* final validate and parse of charstring */
- max_inchar = rootchar;
- for(i=0;i < nchars;i++){
- unsigned int thischar = argstring[i];
- // printf("reading char %c (%d)\n",thischar,thischar);
- unsigned int chindex;
- if(thischar != '0' && (thischar < rootchar || thischar > maxchar)){
- printf("illegal character in order string: %c\n",thischar);
- goto exit;
- }
- if(thischar =='0'){
- // printf("setting channel %d to zero.\n",i);
- orderptr[i] = NULL;
- nzeros++;
- }
- else{
- if(thischar > max_inchar)
- max_inchar = thischar;
- chindex = thischar - rootchar;
- orderptr[i] = &inframe[chindex];
- }
- }
- if(nzeros==nchars)
- printf("Warning: order string is all zeros - a silent file will be made!\n");
- else{
- /* count inclusively! */
- if(inprops.chans < (max_inchar - rootchar + 1)){
- printf("File has %d channels; order string defines non-existent channels.\n",inprops.chans);
- printf("For this file, maximum character is %c\n",rootchar+inprops.chans-1);
- goto exit;
- }
- }
- /* check file extension of outfile name, so we use correct output file format*/
- outformat = psf_getFormatExt(argv[ARG_OUTFILE]);
- if(outformat == PSF_FMT_UNKNOWN){
- printf("outfile name %s has unsupported extension.\n"
- "Use any of .wav, .aiff, .aif, .afc, .aifc, .amb\n",argv[ARG_OUTFILE]);
- error++;
- goto exit;
- }
- inprops.format = outformat;
- outprops = inprops;
- outprops.chans = nchars;
- if(!is_legalsize(outsize,&outprops)){
- fprintf(stderr,"error: outfile size exceeds capacity of format.\n");
- return 1;
- }
- /* any speaker assignment etc invalidated! */
- if(outformat == PSF_STDWAVE) {
- outprops.chformat = MC_STD;
- outprops.format = PSF_WAVE_EX;
- }
-
- if(outformat==PSF_WAVE_EX){
- int matched = 0;
- for(i=0;i < N_BFORMATS;i++) {
- if(inprops.chans == bformats[i]){
- matched = 1;
- break;
- }
- }
- if(!matched){
- printf("WARNING: No B-format definition for %d-channel file.\n",outprops.chans);
- }
- outprops.chformat = MC_BFMT;
- outprops.format = PSF_WAVE_EX;
- }
-
- outframe = malloc(sizeof(float) * nchars);
-
- peaks = (PSF_CHPEAK*) malloc(outprops.chans * sizeof(PSF_CHPEAK));
- if(peaks == NULL){
- puts("No memory!\n");
- error++;
- goto exit;
- }
- ofd = psf_sndCreate(argv[ARG_OUTFILE],&outprops,0,0,PSF_CREATE_RDWR);
- if(ofd < 0){
- printf("Error: unable to create outfile %s\n",argv[ARG_OUTFILE]);
- error++;
- goto exit;
- }
-
- halfsec = inprops.srate / 2;
- framepos = 0;
- printf("processing....\n");
-
- while ((framesread = psf_sndReadFloatFrames(ifd,inframe,1)) > 0){
- float val;
- for(i=0;i < nchars;i++){
- if(orderptr[i] == NULL)
- val = 0.0f;
- else
- val = *orderptr[i];
- outframe[i] = val;
- }
- if(psf_sndWriteFloatFrames(ofd,outframe,1) != 1){
- printf("Error writing to outfile\n");
- error++;
- break;
- }
- if((framepos % halfsec) == 0){
- printf("%.2lf secs\r",(double) framepos / (double) outprops.srate);
- fflush(stdout);
- }
- framepos++;
- }
- if(framesread < 0) {
- printf("Error reading infile. Outfile is incomplete.\n");
- error++;
- }
- printf("\n%.4lf secs\nWritten %d frames to %s\n",(double)framepos / (double) outprops.srate,framepos,argv[ARG_OUTFILE]);
-
- if(psf_sndReadPeaks( ofd,peaks,&peaktime)){
- printf("PEAK values:\n");
- for(i=0; i < outprops.chans; i++){
- double val, dbval;
- val = (double) peaks[i].val;
- if(val > 0.0){
- dbval = 20.0 * log10(val);
- printf("CH %d: %.6f (%.2lfdB) at frame %u:\t%.4f secs\n",i,
- val,dbval,(unsigned int) peaks[i].pos,(double)peaks[i].pos / (double) outprops.srate);
- }
- else{
- printf("CH %d: %.6f (-infdB) at frame %u:\t%.4f secs\n",i,
- val,(unsigned int) peaks[i].pos,(double)peaks[i].pos / (double) outprops.srate);
- }
- }
- }
- printf("\n");
- exit:
- if(ifd >= 0)
- psf_sndClose(ifd);
- if(ofd >= 0)
- psf_sndClose(ofd);
- if(inframe)
- free(inframe);
- if(outframe)
- free(outframe);
- if(peaks)
- free(peaks);
- psf_finish();
- return error;
- }
|