From c2409ca4bee5fbd0968977c33aee0837f0600417 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 24 Feb 2021 13:21:35 -0500 Subject: [PATCH] cwFileOps.h/cpp: Added fade in/out fucnctionality to selectToFile(). --- cwAudioFileOps.cpp | 476 +++++++++++++++++++++++++-------------------- cwAudioFileOps.h | 2 +- 2 files changed, 270 insertions(+), 208 deletions(-) diff --git a/cwAudioFileOps.cpp b/cwAudioFileOps.cpp index 4411119..fea21de 100644 --- a/cwAudioFileOps.cpp +++ b/cwAudioFileOps.cpp @@ -12,6 +12,155 @@ #include "cwVectOps.h" #include "cwDsp.h" +namespace cw +{ + namespace afop + { + typedef struct _cutMixArg_str + { + const cutMixArg_t* arg; + char* srcFn; + unsigned srcFrmIdx; + unsigned srcFrmN; + unsigned srcFadeInFrmN; + unsigned srcFadeOutFrmN; + unsigned dstFrmIdx; + audiofile::handle_t afH; + audiofile::info_t afInfo; + } _cutMixArg_t; + + rc_t _cutAndMixOpen( const char* srcDir, const cutMixArg_t* argL, _cutMixArg_t* xArgL, unsigned argN, unsigned& chN_Ref, double& srate_Ref, unsigned& dstFrmN_Ref, unsigned& maxSrcFrmN_Ref ) + { + rc_t rc = kOkRC; + + maxSrcFrmN_Ref = 0; + chN_Ref = 0; + + for(unsigned i = 0; i argL[i].srcEndSec ) + { + rc = cwLogError(kInvalidArgRC,"The end time is prior to the begin time on source file '%s'.", xArgL[i].srcFn); + goto errLabel; + } + + xArgL[i].arg = argL + i; + xArgL[i].srcFrmIdx = floor(argL[i].srcBegSec * srate_Ref); + xArgL[i].srcFrmN = floor(argL[i].srcEndSec * srate_Ref) - xArgL[i].srcFrmIdx; + xArgL[i].srcFadeInFrmN = floor(argL[i].srcBegFadeSec * srate_Ref); + xArgL[i].srcFadeOutFrmN = floor(argL[i].srcEndFadeSec * srate_Ref); + xArgL[i].dstFrmIdx = floor(argL[i].dstBegSec * srate_Ref); + + //printf("cm beg:%f end:%f dst:%f gain:%f %s\n", argL[i].srcBegSec, argL[i].srcEndSec, argL[i].dstBegSec, argL[i].gain, argL[i].srcFn ); + + + chN_Ref = std::max( chN_Ref, xArgL[i].afInfo.chCnt ); + maxSrcFrmN_Ref = std::max( maxSrcFrmN_Ref, xArgL[i].srcFrmN ); + + dstFrmN_Ref = std::max( dstFrmN_Ref, xArgL[i].dstFrmIdx + xArgL[i].srcFrmN ); + + } + + errLabel: + return rc; + } + + rc_t _cutAndMixClose( _cutMixArg_t* xArgL, unsigned argN ) + { + rc_t rc = kOkRC; + + for(unsigned i = 0; i end0Sec ) + { + rc = cwLogError(kInvalidArgRC,"Invalid time selection. Begin time (%f) is greater than end time (%f). ", beg1Sec, end0Sec ); + goto errLabel; + } + // open the source file if((rc = audiofile::open( iH, iFn, &info )) != kOkRC ) goto errLabel; - // - if( begSec >= endSec ) - { - rc = cwLogError(kInvalidArgRC,"Invalid time selection. Begin time (%f) is greater than end time (%f). ", begSec, endSec ); - goto errLabel; - } - // create the output file if((rc = audiofile::create( oH, oFn, info.srate, outBits, info.chCnt)) != kOkRC ) goto errLabel; else { - unsigned begFrmIdx = (unsigned)floor(begSec * info.srate); - unsigned endFrmIdx = endSec==-1 ? info.frameCnt : (unsigned)floor(endSec * info.srate); - unsigned ttlFrmN = endFrmIdx - begFrmIdx; + unsigned beg0FrmIdx = (unsigned)floor(beg0Sec * info.srate); + unsigned beg1FrmIdx = (unsigned)floor(beg1Sec * info.srate); + unsigned end0FrmIdx = (unsigned)floor(end0Sec * info.srate); + unsigned end1FrmIdx = end1Sec==-1 ? info.frameCnt : (unsigned)floor(end1Sec * info.srate); + unsigned ttlFrmN = end1FrmIdx - beg0FrmIdx; unsigned actualBufFrmN = 0; - const unsigned bufFrmN = 8196; // read/write buffer size - float buf[ bufFrmN*info.chCnt ]; float* chBuf[ info.chCnt ]; + beg0FrmIdx = std::max(0u,std::min(beg0FrmIdx,info.frameCnt)); + beg1FrmIdx = std::max(0u,std::min(beg1FrmIdx,info.frameCnt)); + end0FrmIdx = std::max(0u,std::min(end0FrmIdx,info.frameCnt)); + end1FrmIdx = std::max(0u,std::min(end1FrmIdx,info.frameCnt)); + + + cwLogInfo("beg:%f %f end: %f %f : src:%s dst:%s", beg0Sec,beg1Sec,end0Sec,end1Sec,iFn,oFn); + + // Seek to the start of the read location + if((rc = audiofile::seek( iH, beg0FrmIdx )) != kOkRC ) + goto errLabel; + + // set up the read/write channel buffer for(unsigned i = 0; i(ttlFrmN); - // seek to first frame - if((rc = audiofile::seek(iH,begFrmIdx)) != kOkRC ) - goto errLabel; - - // for each read/write buffer in the selected region - for(unsigned curFrmN=0; curFrmN ttlFrmN ) - actualBufFrmN -= ttlFrmN - curFrmN; - - // write the buffer to the output file - if((rc = audiofile::writeFloat(oH, actualBufFrmN, info.chCnt, chBuf )) != kOkRC ) - { - rc = cwLogError(kOpFailRC,"Write failed on output file '%s'.", oFn ); - goto errLabel; - } - } + + // if there is a fade-in then generate it + if( beg1FrmIdx > beg0FrmIdx ) + _fadeAllChannels( chBuf, info.chCnt, ttlFrmN, beg1FrmIdx-beg0FrmIdx, kLinearFadeFl | kFadeInFl ); + + // if there is a fade-out then generate it + if( end1FrmIdx > end0FrmIdx ) + { + float* fadeChBuf[ info.chCnt ]; + for(unsigned i = 0; igetv("outDir",oDir,"outBits",outBits,"selectL",selectL)) != kOkRC ) - goto errLabel; + goto errLabel; else - { - unsigned selN = selectL->child_count(); - - for(unsigned i=0; igetv_opt("srcFn",src0Fn,"fadeInSec",fadeInSec,"fadeOutSec",fadeOutSec,"fadeInPreFl",fadeInPreFl,"fadeOutPreFl",fadeOutPostFl)) != kOkRC ) + goto errLabel; + else { - double begSec = 0; - double endSec = -1; - const char* dstFn = nullptr; - const char* srcFn = nullptr; + unsigned selN = selectL->child_count(); - if((rc = selectL->child_ele(i)->getv("begSec",begSec,"endSec",endSec,"dst",dstFn, "src",srcFn)) != kOkRC ) + for(unsigned i=0; ichild_ele(i)->getv("begSec",begSec,"endSec",endSec,"dst",dstFn)) != kOkRC ) + { + rc = cwLogError(kSyntaxErrorRC,"Argument error in 'select to file' index %i syntax error."); + goto errLabel; + } + + + if((rc = selectL->child_ele(i)->getv_opt("src",src1Fn)) != kOkRC ) + { + rc = cwLogError(kSyntaxErrorRC,"Optional argument parse error in 'select to file' index %i syntax error."); + goto errLabel; + } + + if( src0Fn == nullptr && src1Fn == nullptr ) + { + rc = cwLogError(kInvalidArgRC,"selection at index %i does not have a source file.",i); + goto errLabel; + } + + double beg0Sec = fadeInPreFl ? std::max(0.0,begSec-fadeInSec) : begSec; + double beg1Sec = fadeInPreFl ? begSec : begSec + fadeInSec; + double end0Sec = fadeOutPostFl ? endSec : std::max(0.0,endSec - fadeOutSec); + double end1Sec = fadeOutPostFl ? endSec+fadeOutSec : endSec; + + beg1Sec = std::max(beg0Sec,beg1Sec); + end1Sec = std::max(end0Sec,end1Sec); + + if((rc = selectToFile( src1Fn==nullptr ? src0Fn : src1Fn, beg0Sec, beg1Sec, end0Sec, end1Sec, outBits, oDir, dstFn )) != kOkRC ) + goto errLabel; + } - - if((rc = selectToFile( srcFn, begSec, endSec, outBits, oDir, dstFn )) != kOkRC ) - goto errLabel; - } - } errLabel: return rc; } -namespace cw -{ - namespace afop - { - typedef struct _cutMixArg_str - { - const cutMixArg_t* arg; - char* srcFn; - unsigned srcFrmIdx; - unsigned srcFrmN; - unsigned srcFadeInFrmN; - unsigned srcFadeOutFrmN; - unsigned dstFrmIdx; - audiofile::handle_t afH; - audiofile::info_t afInfo; - } _cutMixArg_t; - - rc_t _cutAndMixOpen( const char* srcDir, const cutMixArg_t* argL, _cutMixArg_t* xArgL, unsigned argN, unsigned& chN_Ref, double& srate_Ref, unsigned& dstFrmN_Ref, unsigned& maxSrcFrmN_Ref ) - { - rc_t rc = kOkRC; - - maxSrcFrmN_Ref = 0; - chN_Ref = 0; - - for(unsigned i = 0; i argL[i].srcEndSec ) - { - rc = cwLogError(kInvalidArgRC,"The end time is prior to the begin time on source file '%s'.", xArgL[i].srcFn); - goto errLabel; - } - - xArgL[i].arg = argL + i; - xArgL[i].srcFrmIdx = floor(argL[i].srcBegSec * srate_Ref); - xArgL[i].srcFrmN = floor(argL[i].srcEndSec * srate_Ref) - xArgL[i].srcFrmIdx; - xArgL[i].srcFadeInFrmN = floor(argL[i].srcBegFadeSec * srate_Ref); - xArgL[i].srcFadeOutFrmN = floor(argL[i].srcEndFadeSec * srate_Ref); - xArgL[i].dstFrmIdx = floor(argL[i].dstBegSec * srate_Ref); - - //printf("cm beg:%f end:%f dst:%f gain:%f %s\n", argL[i].srcBegSec, argL[i].srcEndSec, argL[i].dstBegSec, argL[i].gain, argL[i].srcFn ); - - - chN_Ref = std::max( chN_Ref, xArgL[i].afInfo.chCnt ); - maxSrcFrmN_Ref = std::max( maxSrcFrmN_Ref, xArgL[i].srcFrmN ); - - dstFrmN_Ref = std::max( dstFrmN_Ref, xArgL[i].dstFrmIdx + xArgL[i].srcFrmN ); - - } - - errLabel: - return rc; - } - - rc_t _cutAndMixClose( _cutMixArg_t* xArgL, unsigned argN ) - { - rc_t rc = kOkRC; - - for(unsigned i = 0; i