29#include "../widgets/valnum.h"
49 PaulStretch(
float rap_,
size_t in_bufsize_,
float samplerate_);
53 void process(
float *smps,
size_t nsmps);
98 Parameters().Reset(*
this);
100 SetLinearEffectFlag(
true);
116 return XO(
"Paulstretch is only for an extreme time-stretch or \"stasis\" effect");
121 return L
"Paulstretch";
154 for (
const auto track : outputs.Get().Selected<
WaveTrack>()) {
155 double trackStart = track->GetStartTime();
156 double trackEnd = track->GetEndTime();
157 double t0 =
mT0 < trackStart ? trackStart :
mT0;
158 double t1 =
mT1 > trackEnd ? trackEnd :
mT1;
160 auto tempList = track->WideEmptyCopy();
161 const auto channels = track->Channels();
162 auto iter = (*tempList->Any<
WaveTrack>().
begin())->Channels().begin();
163 for (
const auto pChannel : channels) {
164 if (!
ProcessOne(*pChannel, **iter++, t0, t1, count++))
169 newT1 = std::max(newT1,
mT0 + pNewTrack->GetEndTime());
170 track->Clear(t0, t1);
171 track->Paste(t0, *tempList);
174 count += track->NChannels();
178 outputs.Get().Any().Visit(
179 [&](
auto &&fallthrough){
return [&](
WaveTrack &track) {
180 if (!track.IsSelected())
185 track.SyncLockAdjust(
mT1, newT1);
201 S.StartMultiColumn(2, wxALIGN_CENTER);
204 .Validator<FloatingPointValidator<float>>(
210 .AddTextBox(
XXO(
"&Stretch Factor:"),
wxT(
""), 10);
213 .Validator<FloatingPointValidator<float>>(
215 .AddTextBox(
XXO(
"&Time Resolution (seconds):"), L
"", 10);
253 tmp = log(tmp) / log(2.0);
254 tmp = pow(2.0, floor(tmp + 0.5));
256 auto stmp = size_t(tmp);
260 if (stmp >= 2 * stmp)
264 return std::max<size_t>(stmp, 128);
268 WaveChannel &outputTrack,
double t0,
double t1,
int count)
270 const auto badAllocMessage =
271 XO(
"Requested value exceeds memory capacity.");
275 if (stretch_buf_size == 0) {
284 auto len =
end - start;
286 const auto minDuration = stretch_buf_size * 2 + 1;
287 if (minDuration < stretch_buf_size) {
293 if (len < minDuration) {
295 float maxTimeRes = log( len.as_double() ) / log(2.0);
296 maxTimeRes = pow(2.0, floor(maxTimeRes) + 0.5);
297 maxTimeRes = maxTimeRes / rate;
300 double defaultPreviewLen;
301 gPrefs->
Read(
wxT(
"/AudioIO/EffectsPreviewLen"), &defaultPreviewLen, 6.0);
306 XO(
"Audio selection too short to preview.\n\n"
307 "Try increasing the audio selection to at least %.1f seconds,\n"
308 "or reducing the 'Time Resolution' to less than %.1f seconds.")
310 (minDuration / rate) + 0.05,
311 floor(maxTimeRes * 10.0) / 10.0),
312 wxOK | wxICON_EXCLAMATION );
317 XO(
"Unable to Preview.\n\n"
318 "For the current audio selection, the maximum\n"
319 "'Time Resolution' is %.1f seconds.")
320 .
Format( floor(maxTimeRes * 10.0) / 10.0 ),
321 wxOK | wxICON_EXCLAMATION );
327 XO(
"The 'Time Resolution' is too long for the selection.\n\n"
328 "Try increasing the audio selection to at least %.1f seconds,\n"
329 "or reducing the 'Time Resolution' to less than %.1f seconds.")
331 (minDuration / rate) + 0.05,
332 floor(maxTimeRes * 10.0) / 10.0),
333 wxOK | wxICON_EXCLAMATION );
339 auto dlen = len.as_double();
340 double adjust_amount = dlen /
341 (dlen - ((double)stretch_buf_size * 2.0));
342 amount = 1.0 + (amount - 1.0) * adjust_amount;
348 PaulStretch stretch(amount, stretch_buf_size, rate);
353 Floats buffer0{ bufsize };
354 float *bufferptr0 = buffer0.get();
355 bool first_time =
true;
357 const auto fade_len = std::min<size_t>(100, bufsize / 2 - 1);
358 bool cancelled =
false;
361 Floats fade_track_smps{ fade_len };
365 track.
GetFloats(bufferptr0, start + s, nget);
366 stretch.
process(buffer0.get(), nget);
369 stretch.
process(buffer0.get(), 0);
375 track.
GetFloats(fade_track_smps.get(), start, fade_len);
377 for (
size_t i = 0; i < fade_len; i++){
378 float fi = (float)i / (
float)fade_len;
380 stretch.
out_buf[i] * fi + (1.0 - fi) * fade_track_smps[i];
384 track.
GetFloats(fade_track_smps.get(),
end - fade_len, fade_len);
385 for (
size_t i = 0; i < fade_len; i++){
386 float fi = (float)i / (
float)fade_len;
387 auto i2 = bufsize / 2 - 1 - i;
389 stretch.
out_buf[i2] * fi + (1.0 - fi) *
390 fade_track_smps[fade_len - 1 - i];
398 s.as_double() / len.as_double()
409 catch (
const std::bad_alloc& ) {
419 : samplerate { samplerate_ }
420 , rap {
std::max(1.0f, rap_) }
421 , in_bufsize { in_bufsize_ }
422 , out_bufsize {
std::max(size_t{ 8 }, in_bufsize) }
423 , out_buf { out_bufsize }
424 , old_out_smp_buf { out_bufsize * 2, true }
425 , poolsize { in_bufsize_ * 2 }
426 , in_pool { poolsize, true }
427 , remained_samples { 0.0 }
428 , fft_smps { poolsize, true }
429 , fft_c { poolsize, true }
430 , fft_s { poolsize, true }
431 , fft_freq { poolsize, true }
432 , fft_tmp { poolsize }
443 if ((smps != NULL) && (nsmps != 0)) {
450 for (
int i = 0; i < nleft; i++)
454 for (
size_t i = 0; i < nsmps; i++)
459 for (
size_t i = 0; i <
poolsize; i++)
465 for (
size_t i = 0; i <
poolsize / 2; i++)
471 float inv_2p15_2pi = 1.0 / 16384.0 * (float)
M_PI;
472 for (
size_t i = 1; i <
poolsize / 2; i++) {
473 unsigned int random = (rand()) & 0x7fff;
474 float phase = random * inv_2p15_2pi;
487 float max = 0.0, max2 = 0.0;
488 for (
size_t i = 0; i <
poolsize; i++) {
489 max = std::max(max, fabsf(
fft_tmp[i]));
490 max2 = std::max(max2, fabsf(
fft_smps[i]));
496 float hinv_sqrt2 = 0.853553390593f;
498 float ampfactor = 1.0;
500 ampfactor =
rap * 0.707;
505 float a = (0.5 + 0.5 * cos(i * tmp));
508 out * (hinv_sqrt2 - (1.0 - hinv_sqrt2) * cos(i * 2.0 * tmp)) *
520 auto ri = (size_t)floor(r);
521 double rf = r - floor(r);
void WindowFunc(int whichFunction, size_t NumSamples, float *in)
void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *ImagOut)
void FFT(size_t NumSamples, bool InverseTransform, const float *RealIn, const float *ImagIn, float *RealOut, float *ImagOut)
XXO("&Cut/Copy/Paste Toolbar")
audacity::BasicSettings * gPrefs
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
bool IsPreviewing() const
std::shared_ptr< TrackList > mTracks
static bool EnableApply(wxWindow *parent, bool enable=true)
Enable or disable the Apply button of the dialog that contains parent.
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Performs effect computation.
Use this object to copy the input tracks to tentative outputTracks.
Hold values to send to effect output meters.
Interface for manipulations of an Effect's settings.
An Extreme Time Stretch and Time Smear effect.
bool TransferDataToWindow(const EffectSettings &settings) override
static constexpr EffectParameter Time
const EffectParameterMethods & Parameters() const override
virtual ~EffectPaulstretch()
bool ProcessOne(const WaveChannel &track, WaveChannel &outputTrack, double t0, double t1, int count)
bool TransferDataFromWindow(EffectSettings &settings) override
static const ComponentInterfaceSymbol Symbol
TranslatableString GetDescription() const override
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const override
EffectType GetType() const override
Type determines how it behaves.
wxWeakRef< wxWindow > mUIParent
std::unique_ptr< EffectEditor > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
void OnText(wxCommandEvent &evt)
bool Process(EffectInstance &instance, EffectSettings &settings) override
size_t GetBufferSize(double rate) const
ComponentInterfaceSymbol GetSymbol() const override
static constexpr EffectParameter Amount
static int DoMessageBox(const EffectPlugin &plugin, const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={})
Class that helps EffectPaulStretch. It does the FFTs and inner loop of the effect.
void process(float *smps, size_t nsmps)
const Floats old_out_smp_buf
size_t get_nsamples_for_fill()
PaulStretch(float rap_, size_t in_bufsize_, float samplerate_)
void process_spectrum(float *WXUNUSED(freq))
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
static bool IsSyncLockSelected(const Track *pTrack)
Abstract base class for an object holding data associated with points on a time axis.
Holds a msgid for the translation catalog; may also bind format arguments.
bool Append(constSamplePtr buffer, sampleFormat format, size_t len)
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
"narrow" overload fetches from the unique channel
A Track that contains audio waveform data.
double GetRate() const override
sampleCount TimeToLongSamples(double t0) const
virtual bool Read(const wxString &key, bool *value) const =0
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
BuiltinEffectsModule::Registration< EffectPaulstretch > reg
__finl float_x4 __vecc sqrt(const float_x4 &a)
const Type min
Minimum value.
Externalized state of a plug-in.