41 for (
const auto &subViewPtr : waveChannelViewPtr->GetAllSubViews()){
42 if (subViewPtr->IsSpectral()) {
44 std::static_pointer_cast<SpectrumView>(subViewPtr).get();
45 const auto pData = sView->GetSpectralData();
46 if (!pData->dataHistory.empty()) {
61 using Type =
long long;
62 Type startSample{ std::numeric_limits<Type>::max() };
64 for (
auto pChannel : wt->Channels()) {
66 const auto &hopSize = pData->GetHopSize();
67 auto start = pData->GetStartSample();
68 endSample = std::max(endSample, pData->GetEndSample());
72 start = std::max(
static_cast<long long>(0), start - 2 * hopSize);
73 startSample =
std::min(startSample, start);
76 if (startSample >= endSample)
78 const auto t0 = wt->LongSamplesToTime(startSample);
79 const auto len = endSample - startSample;
80 const auto tLen = wt->LongSamplesToTime(len);
81 auto tempTrack = wt->EmptyCopy();
82 auto iter = tempTrack->Channels().begin();
83 long long processed{};
84 for (
auto pChannel : wt->Channels()) {
85 Worker worker{ (*iter++).get(), setting };
89 for (
const auto &subViewPtr : waveChannelViewPtr->GetAllSubViews()){
90 if (!subViewPtr->IsSpectral())
92 auto sView = std::static_pointer_cast<SpectrumView>(subViewPtr).get();
93 auto pSpectralData = sView->GetSpectralData();
95 if (!pSpectralData->dataHistory.empty()) {
98 processed = std::max(processed, pSpectralData->GetLength());
99 worker.Process(*pChannel, pSpectralData);
100 applyCount +=
static_cast<int>(pSpectralData->dataHistory.size());
101 pSpectralData->clearAllData();
112 wt->ClearAndPaste(t0, t0 + tLen, *tempTrack,
true,
false);
118 XO(
"Applied effect to selection"),
119 XO(
"Applied effect to selection"));
123 return applyCount > 0;
127 long long int startSC,
int hopSize,
double threshold,
int targetFreqBin)
131 Worker worker{
nullptr, setting };
133 return worker.ProcessSnapping(
134 channel, startSC, hopSize, setting.
mWindowSize, threshold, targetFreqBin);
138 long long int startSC,
145 Worker worker{
nullptr, setting };
147 return worker.ProcessOvertones(wc, startSC, hopSize, setting.
mWindowSize, threshold, targetFreqBin);
153 setting.mNeedOutput, setting.mInWindowType, setting.mOutWindowType,
154 setting.mWindowSize, setting.mStepsPerWindow,
155 setting.mLeadingPadding, setting.mTrailingPadding
171 const std::shared_ptr<SpectralData> &pSpectralData)
173 mpSpectralData = pSpectralData;
174 const auto hopSize = mpSpectralData->GetHopSize();
175 const auto startSample = mpSpectralData->GetStartSample();
178 mStartHopNum = startSample / hopSize - (mStepsPerWindow - 1);
181 mpSpectralData->GetCorrectedStartSample(), mpSpectralData->GetLength());
185 long long startSC,
int hopSize,
size_t winSize,
double threshold,
188 mSnapThreshold = threshold;
189 mSnapTargetFreqBin = targetFreqBin;
192 startSC = std::max(
static_cast<long long>(0), startSC - 2 * hopSize);
195 1, startSC, winSize))
198 return mSnapReturnFreqBin;
202 const WaveChannel &channel,
long long startSC,
int hopSize,
size_t winSize,
203 double threshold,
int targetFreqBin)
205 mOvertonesThreshold = threshold;
206 mSnapTargetFreqBin = targetFreqBin;
209 startSC = std::max(
static_cast<long long>(0), startSC - 2 * hopSize);
212 OvertonesProcessor, channel, 1, startSC, winSize);
213 return move( mOvertonesTargetFreqBin );
217 auto &worker =
static_cast<Worker &
>(transformer);
220 MyWindow &record = worker.NthWindow(0);
222 const double dc = record.mRealFFTs[0];
223 *pSpectrum++ = dc * dc;
224 float *pReal = &record.mRealFFTs[1], *pImag = &record.mImagFFTs[1];
225 for (
size_t nn = worker.mSpectrumSize - 2; nn--;) {
226 const double re = *pReal++, im = *pImag++;
227 *pSpectrum++ = re * re + im * im;
229 const double nyquist = record.mImagFFTs[0];
230 *pSpectrum = nyquist * nyquist;
232 const double &sr = worker.mSnapSamplingRate;
233 const double nyquistRate = sr / 2;
234 const double &threshold = worker.mSnapThreshold;
235 const double &spectrumSize = worker.mSpectrumSize;
236 const int &targetBin = worker.mSnapTargetFreqBin;
238 int binBound = spectrumSize * threshold;
242 for(
int i = -binBound; i < binBound; i++){
243 int idx = std::clamp(targetBin + i, 0,
static_cast<int>(spectrumSize - 1));
247 worker.mSnapReturnFreqBin = idx;
256 auto &worker =
static_cast<Worker &
>(transformer);
259 MyWindow &record = worker.NthWindow(0);
261 const double dc = record.mRealFFTs[0];
262 *pSpectrum++ = dc * dc;
263 float *pReal = &record.mRealFFTs[1], *pImag = &record.mImagFFTs[1];
264 for (
size_t nn = worker.mSpectrumSize - 2; nn--;) {
265 const double re = *pReal++, im = *pImag++;
266 *pSpectrum++ = re * re + im * im;
268 const double nyquist = record.mImagFFTs[0];
269 *pSpectrum = nyquist * nyquist;
271 const double &spectrumSize = worker.mSpectrumSize;
272 const int &targetBin = worker.mSnapTargetFreqBin;
274 float targetValue = record.
mSpectrums[targetBin];
276 double fundamental = targetBin;
277 int overtone = 2, binNum = 0;
279 while ( fundamental >= 1 &&
280 ( binNum =
lrint( fundamental * overtone ) ) < spectrumSize) {
282 constexpr int tolerance = 3;
283 auto begin = pSpectrum + std::max( 0, binNum - (tolerance + 1) );
284 auto end = pSpectrum +
285 std::min<size_t>( spectrumSize, binNum + (tolerance + 1) + 1 );
286 auto peak = std::max_element(
begin,
end );
289 if ( peak ==
begin || peak ==
end - 1 )
292 int newBin = peak - pSpectrum;
293 worker.mOvertonesTargetFreqBin.push_back(newBin);
295 fundamental = double(newBin) / overtone++;
303 auto &worker =
static_cast<Worker &
>(transformer);
306 MyWindow &record = worker.NthWindow(0);
308 const double dc = record.mRealFFTs[0];
309 *pSpectrum++ = dc * dc;
310 float *pReal = &record.mRealFFTs[1], *pImag = &record.mImagFFTs[1];
311 for (
size_t nn = worker.mSpectrumSize - 2; nn--;) {
312 const double re = *pReal++, im = *pImag++;
313 *pSpectrum++ = re * re + im * im;
315 const double nyquist = record.mImagFFTs[0];
316 *pSpectrum = nyquist * nyquist;
319 worker.ApplyEffectToSelection();
324 auto &record = NthWindow(0);
326 for(
auto &spectralDataMap: mpSpectralData->dataHistory){
328 for(
const int &freqBin: spectralDataMap[mStartHopNum]){
329 record.mRealFFTs[freqBin] = 0;
330 record.mImagFFTs[freqBin] = 0;
340-> std::unique_ptr<Window>
342 return std::make_unique<MyWindow>(windowSize);
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
static ChannelView & Get(Channel &channel)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
Worker(WaveChannel *pChannel, const Setting &setting)
std::vector< int > ProcessOvertones(const WaveChannel &channel, long long int startSC, int hopSize, size_t winSize, double threshold, int targetFreqBin)
bool ApplyEffectToSelection()
bool DoFinish() override
Called after the last call to ProcessWindow().
bool DoStart() override
Called before any calls to ProcessWindow.
std::unique_ptr< Window > NewWindow(size_t windowSize) override
Allocates a window to place in the queue.
int ProcessSnapping(const WaveChannel &channel, long long int startSC, int hopSize, size_t winSize, double threshold, int targetFreqBin)
bool Process(const WaveChannel &channel, const std::shared_ptr< SpectralData > &sDataPtr)
static bool OvertonesProcessor(SpectrumTransformer &transformer)
static bool Processor(SpectrumTransformer &transformer)
static bool SnappingProcessor(SpectrumTransformer &transformer)
static std::vector< int > FindHighestFrequencyBins(WaveChannel &wc, long long int startSC, int hopSize, double threshold, int targetFreqBin)
static bool ProcessTracks(AudacityProject &project)
static int FindFrequencySnappingBin(const WaveChannel &channel, long long startSC, int hopSize, double threshold, int targetFreqBin)
static TrackList & Get(AudacityProject &project)
A Track that contains audio waveform data.
double GetRate() const override
const std::shared_ptr< SpectralData > FindSpectralData(Channel *pChannel)
const char * end(const char *str) noexcept
const char * begin(const char *str) noexcept
eWindowFunctions mOutWindowType
eWindowFunctions mInWindowType