/* * Copyright (c) 1983-2013 Martin Atkins, 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 * */ /* props.cpp: adapted from speclib3.c * NB this is now real C++ code, not C! * */ //LATEST VERSION OCT97: supercedes all previous! //can I make this fully portable to both graphic and console apps? //TODO: Feb 2014: replace sizeof(long) with sizeof(int) everywhere! #include "stdafx.h" //for MFC: def of BOOL, TRUE, FALSE, etc //#include //use multi-threaded version of sfsys.lib extern "C" { #include } #include "props.h" char *props_errstr = NULL; //RWD TODO: also need a copy constructor... /***************************** HEADREAD ******************************* * * Read input analysis file header data. */ //RWD TODO: see Holub: props MUST be a pointer, not ref BOOL sfheadread(int fd,SFPROPS &props) { long srate,chans,samptype,origsize = 0,origrate=0,origchans = 0,dummy; float arate = (float)0.0; int wlen=0,dfac=0,specenvcnt = 0,checksum=0; props_errstr = NULL; if(fd <0){ props_errstr = "Cannot read Soundfile: Bad Handle"; return FALSE; } if(sfgetprop(fd,"sample rate", (char *)&srate, sizeof(long)) < 0) { props_errstr = "Failure to read sample rate"; return FALSE; } if(sfgetprop(fd,"channels", (char *)&chans, sizeof(long)) < 0) { props_errstr ="Failure to read channel data"; return FALSE; } if(sfgetprop(fd,"sample type", (char *)&samptype, sizeof(long)) < 0){ props_errstr = "Failure to read sample size"; return FALSE; } if(!(samptype==SAMP_SHORT || samptype== SAMP_FLOAT)){ props_errstr = "unsupported sample type"; return FALSE; } props.srate = srate; props.chans = chans; if(samptype == SAMP_SHORT || samptype == SAMP_FLOAT){ props.type = wt_wave; props.samptype = (samptype == SAMP_SHORT ? SHORT16 : FLOAT32); } if(props.samptype==FLOAT32) { //we know we have floats: is it spectral file? if(sfgetprop(fd,"original sampsize",(char *)&origsize, sizeof(long))<0){ props_errstr = "Failure to read original sample size"; } if(sfgetprop(fd,"original sample rate",(char *)&origrate,sizeof(long))<0){ props_errstr = "Failure to read original sample rate"; } if(sfgetprop(fd,"arate",(char *)&arate,sizeof(float)) < 0){ props_errstr = "Failure to read analysis sample rate"; } if(sfgetprop(fd,"analwinlen",(char *)&wlen,sizeof(int)) < 0){ props_errstr = "Failure to read analysis window length"; } if(sfgetprop(fd,"decfactor",(char *)&dfac,sizeof(int)) < 0){ props_errstr = "Failure to read decimation factor"; } checksum = origsize + origrate + wlen + dfac + (int)arate; if(checksum==0) //its a wave file return TRUE; else { if(props_errstr==NULL){ //its a good spectral file props.origsize = origsize; props.origrate = origrate; props.arate = arate; props.winlen = wlen; //better be wlen+2 ? props.decfac = dfac; //props.chans = (wlen+2)/2; //?? if(sfgetprop(fd,"is a pitch file", (char *)&dummy, sizeof(long))>=0) props.type = wt_pitch; else if(sfgetprop(fd,"is a transpos file", (char *)&dummy, sizeof(long))>=0) props.type = wt_transposition; else if(sfgetprop(fd,"is a formant file", (char *)&dummy, sizeof(long))>=0) props.type = wt_formant; else props.type = wt_analysis; } else return FALSE; //somehow, got a bad analysis file... } // get any auxiliary stuff for control file //adapted from TW's function in speclibg.cpp switch(props.type){ case(wt_formant): if(sfgetprop(fd,"specenvcnt",(char *)&specenvcnt,sizeof(int)) < 0){ props_errstr = "Failure to read formant size in formant file"; return FALSE; } props.specenvcnt = specenvcnt; break; case(wt_pitch): case(wt_transposition): if(props.chans != 1){ //RWD: this makes old-style files illegal! props_errstr = "Channel count does not equal to 1 in transposition file"; return FALSE; } if(sfgetprop(fd,"orig channels", (char *)&origchans, sizeof(long)) < 0) { props_errstr = "Failure to read original channel data from transposition file"; return FALSE; } props.origchans = origchans; break; default: break; } } return TRUE; } BOOL sndheadread(int fd,SFPROPS &props) { long srate,chans,samptype,origsize = 0,origrate = 0, origchans = 0,dummy; float arate = (float)0.0; int wlen=0,dfac=0,specenvcnt = 0,checksum=0; props_errstr = NULL; if(fd <0){ props_errstr = "Bad Soundfile Handle"; return FALSE; } if(sndgetprop(fd,"sample rate", (char *)&srate, sizeof(long)) < 0) { props_errstr = "Failure to read sample rate"; return FALSE; } if(sndgetprop(fd,"channels", (char *)&chans, sizeof(long)) < 0) { props_errstr ="Failure to read channel data"; return FALSE; } if(sndgetprop(fd,"sample type", (char *)&samptype, sizeof(long)) < 0){ props_errstr = "Failure to read sample size"; return FALSE; } if(!(samptype==SAMP_SHORT || samptype== SAMP_FLOAT)){ props_errstr = "unsupported sample type"; return FALSE; } props.srate = srate; props.chans = chans; if(samptype == SAMP_SHORT || samptype== SAMP_FLOAT){ props.type = wt_wave; props.samptype = (samptype == SAMP_SHORT ? SHORT16 : FLOAT32); } if(props.samptype==FLOAT32) { //we know we have floats: is it spectral file? if(sndgetprop(fd,"original sampsize",(char *)&origsize, sizeof(long))<0){ props_errstr = "Failure to read original sample size"; } if(sndgetprop(fd,"original sample rate",(char *)&origrate,sizeof(long))<0){ props_errstr = "Failure to read original sample rate"; } if(sndgetprop(fd,"arate",(char *)&arate,sizeof(float)) < 0){ props_errstr = "Failure to read analysis sample rate"; } if(sndgetprop(fd,"analwinlen",(char *)&wlen,sizeof(int)) < 0){ props_errstr = "Failure to read analysis window length"; } if(sndgetprop(fd,"decfactor",(char *)&dfac,sizeof(int)) < 0){ props_errstr = "Failure to read decimation factor"; } //TODO: find a way to guarantee unique checksums... checksum = origsize + origrate + wlen + dfac + (int)arate; if(checksum==0) //its a wave file return TRUE; else { if(props_errstr==NULL){ //its a good spectral file props.origsize = origsize; props.origrate = origrate; props.arate = arate; props.winlen = wlen; props.decfac = dfac; //props.chans = (wlen+2)/2; //?? if(sndgetprop(fd,"is a pitch file", (char *)&dummy, sizeof(long))>=0) props.type = wt_pitch; else if(sndgetprop(fd,"is a transpos file", (char *)&dummy, sizeof(long))>=0) props.type = wt_transposition; else if(sndgetprop(fd,"is a formant file", (char *)&dummy, sizeof(long))>=0) props.type = wt_formant; else props.type = wt_analysis; } else return FALSE; //somehow, got a bad analysis file... } // get any auxiliary stuff for control file //adapted from TW's function in speclibg.cpp switch(props.type){ case(wt_formant): if(sndgetprop(fd,"specenvcnt",(char *)&specenvcnt,sizeof(int)) < 0){ props_errstr = "Failure to read formant size in formant file"; return FALSE; } props.specenvcnt = specenvcnt; break; case(wt_pitch): case(wt_transposition): if(props.chans != 1){ props_errstr = "Channel count not equal to 1 in transposition file"; return FALSE; } if(sndgetprop(fd,"orig channels", (char *)&origchans, sizeof(long)) < 0) { props_errstr = "Failure to read original channel data from transposition file"; return FALSE; } props.origchans = origchans; break; default: break; } } return TRUE; } // next is for SOUND files only... //TODO: full support for analysis and control files! BOOL sfwave_headwrite(int fd,const SFPROPS &props) { #ifdef _DEBUG ASSERT(fd >= 0); ASSERT(props.samptype==SHORT16 || props.samptype==FLOAT32); ASSERT(props.srate > 0); ASSERT(props.chans > 0); #endif int srate = props.srate; int chans = props.chans; int samptype; if(fd <0){ props_errstr = "Cannot write soundfile: bad Handle"; return FALSE; } if(props.type == wt_wave) samptype = (props.samptype == SHORT16 ? SAMP_SHORT : SAMP_FLOAT); //within sfsys,mostly safe assumption... else { props_errstr = "Not a wave file"; return FALSE; } if(sfputprop(fd,"sample rate", (char *)&srate, sizeof(long)) < 0) { props_errstr = "Failure to write sample rate"; return FALSE; } if(sfputprop(fd,"channels", (char *)&chans, sizeof(long)) < 0) { props_errstr ="Failure to write channel data"; return FALSE; } if(sfputprop(fd,"sample type", (char *)&samptype, sizeof(long)) < 0){ props_errstr = "Failure to write sample size"; return FALSE; } return TRUE; } fileprops::~fileprops() { } fileprops::fileprops() { srate = 0L; stype = -1L; filetype = UNKNOWN; channels = 0L; origstype = -1L; origrate = 0L; origchans = 0L; specenvcnt = 0; Mlen = 0; Dfac = 0; arate = 0.0f; } //TODO: when I have unique checksums, can just compare them const fileprops& fileprops::operator=(const fileprops &rhs) { if(!(rhs == *this)){ //use my operator==; TODO: define operator!= as well... srate = rhs.srate; channels = rhs.channels; stype = rhs.stype; origstype = rhs.origstype; origrate = rhs.origrate; Mlen = rhs.Mlen; Dfac = rhs.Dfac; arate = rhs.arate; origchans = rhs.origchans; specenvcnt = rhs.specenvcnt; //RWD: comes from? } return *this; } int fileprops::operator==(const fileprops &rhs) const { return (srate == rhs.srate && channels == rhs.channels && stype == rhs.stype && origstype == rhs.origstype && origrate == rhs.origrate && Mlen == rhs.Mlen && Dfac == rhs.Dfac && arate == rhs.arate && origchans == rhs.origchans && specenvcnt == rhs.specenvcnt); }