1 /* 2 * Copyright (C) 2002 - David W. Durham 3 * 4 * This file is part of ReZound, an audio editing application. 5 * 6 * ReZound is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published 8 * by the Free Software Foundation; either version 2 of the License, 9 * or (at your option) any later version. 10 * 11 * ReZound is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 19 */ 20 21 #include "CFlangeEffect.h" 22 23 #include <memory> 24 25 #include "../DSP/FlangeEffect.h" 26 #include "../unit_conv.h" 27 28 #include "../CActionParameters.h" 29 #include "../CActionSound.h" 30 31 // LFO Speed is in Hertz, LFO Depth is in ?,LFO Phase is in degrees, Delay is in milliseconds 32 CFlangeEffect::CFlangeEffect(const AActionFactory *factory,const CActionSound *actionSound,float _delayTime,float _wetGain,float _dryGain,const CLFODescription &_flangeLFO,float _feedback) : 33 AAction(factory,actionSound), 34 35 // ??? perhaps I should do these conversions down in the code because I might someday be able to stream the action to disk for later use and the sampleRate would not necessarily be the same 36 37 delayTime(_delayTime), 38 39 wetGain(_wetGain), 40 dryGain(_dryGain), 41 42 flangeLFO(_flangeLFO), 43 44 feedback(_feedback) 45 { 46 if(_delayTime<0.0) 47 throw(runtime_error(string(__func__)+_(" -- _delayTime is negative"))); 48 if(flangeLFO.amp<0.0) 49 throw(runtime_error(string(__func__)+_(" -- flangeLFO.amp is negative"))); 50 } 51 52 CFlangeEffect::~CFlangeEffect() 53 { 54 } 55 56 bool CFlangeEffect::doActionSizeSafe(CActionSound *actionSound,bool prepareForUndo) 57 { 58 const sample_pos_t start=actionSound->start; 59 const sample_pos_t stop=actionSound->stop; 60 61 if(prepareForUndo) 62 moveSelectionToTempPools(actionSound,mmSelection,actionSound->selectionLength()); 63 64 unsigned channelsDoneCount=0; 65 for(unsigned i=0;i<actionSound->sound->getChannelCount();i++) 66 { 67 if(actionSound->doChannel[i]) 68 { 69 CStatusBar statusBar(_("Flange -- Channel ")+istring(++channelsDoneCount)+"/"+istring(actionSound->countChannels()),start,stop,true); 70 71 CRezPoolAccesser dest=actionSound->sound->getAudio(i); 72 const CRezPoolAccesser src=prepareForUndo ? actionSound->sound->getTempAudio(tempAudioPoolKey,i) : actionSound->sound->getAudio(i); 73 74 auto_ptr<ALFO> LFO(gLFORegistry.createLFO(flangeLFO,actionSound->sound->getSampleRate())); 75 76 CDSPFlangeEffect flangeEffect( 77 ms_to_samples(delayTime,actionSound->sound->getSampleRate()), 78 wetGain, 79 dryGain, 80 LFO.get(), 81 ms_to_samples(flangeLFO.amp,actionSound->sound->getSampleRate()), 82 feedback 83 ); 84 85 sample_pos_t srcP=prepareForUndo ? 0 : start; 86 for(sample_pos_t t=start;t<=stop;t++) 87 { 88 dest[t]=ClipSample(flangeEffect.processSample(src[srcP++])); 89 90 if(statusBar.update(t)) 91 { // cancelled 92 if(prepareForUndo) 93 undoActionSizeSafe(actionSound); 94 else 95 actionSound->sound->invalidatePeakData(i,actionSound->start,t); 96 return false; 97 } 98 } 99 100 /* This code can be used to test what the LFOs actually look like 101 for(sample_pos_t t=start;t<=stop;t++) 102 { 103 dest[t]=ClipSample(LFO->nextValue()*10000); 104 UPDATE_PROGRESS_BAR(t); 105 } 106 */ 107 if(!prepareForUndo) 108 actionSound->sound->invalidatePeakData(i,actionSound->start,actionSound->stop); 109 } 110 } 111 112 return(true); 113 } 114 115 AAction::CanUndoResults CFlangeEffect::canUndo(const CActionSound *actionSound) const 116 { 117 return(curYes); 118 } 119 120 void CFlangeEffect::undoActionSizeSafe(const CActionSound *actionSound) 121 { 122 restoreSelectionFromTempPools(actionSound,actionSound->start,actionSound->selectionLength()); 123 } 124 125 126 // --------------------------------------------- 127 128 CFlangeEffectFactory::CFlangeEffectFactory(AActionDialog *channelSelectDialog,AActionDialog *dialog) : 129 AActionFactory(N_("Flange"),"",channelSelectDialog,dialog) 130 { 131 } 132 133 CFlangeEffectFactory::~CFlangeEffectFactory() 134 { 135 } 136 137 CFlangeEffect *CFlangeEffectFactory::manufactureAction(const CActionSound *actionSound,const CActionParameters *actionParameters) const 138 { 139 return(new CFlangeEffect(this,actionSound, 140 actionParameters->getValue<float>("Delay"), 141 actionParameters->getValue<float>("Wet Gain"), 142 actionParameters->getValue<float>("Dry Gain"), 143 actionParameters->getValue<CLFODescription>("Flange LFO"), 144 actionParameters->getValue<float>("Feedback") 145 )); 146 } 147 148