2017-11-13 15:06:08 +00:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (C) 2017 Xenakios
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
2018-06-04 19:04:53 +00:00
|
|
|
it under the terms of version 3 of the GNU General Public License
|
2017-11-13 15:06:08 +00:00
|
|
|
as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This program 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
|
2018-06-04 19:04:53 +00:00
|
|
|
GNU General Public License (version 3) for more details.
|
|
|
|
|
|
|
|
www.gnu.org/licenses
|
2017-11-13 15:06:08 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
2018-06-04 19:04:53 +00:00
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../JuceLibraryCode/JuceHeader.h"
|
|
|
|
#include "Input/AInputS.h"
|
|
|
|
#include "ProcessedStretch.h"
|
|
|
|
#include <mutex>
|
2018-03-06 11:44:36 +00:00
|
|
|
#include <array>
|
2017-11-13 15:06:08 +00:00
|
|
|
#include "../WDL/resample.h"
|
|
|
|
|
|
|
|
class StretchAudioSource final : public PositionableAudioSource
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
StretchAudioSource() {}
|
2018-03-09 16:05:33 +00:00
|
|
|
StretchAudioSource(int initialnumoutchans, AudioFormatManager* afm, std::array<AudioParameterBool*, 9>& enab_pars);
|
2017-11-13 15:06:08 +00:00
|
|
|
~StretchAudioSource();
|
|
|
|
// Inherited via PositionableAudioSource
|
|
|
|
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override;
|
|
|
|
|
|
|
|
void releaseResources() override;
|
|
|
|
|
|
|
|
void getNextAudioBlock(const AudioSourceChannelInfo & bufferToFill) override;
|
|
|
|
|
|
|
|
void setNextReadPosition(int64 newPosition) override;
|
|
|
|
|
|
|
|
int64 getNextReadPosition() const override;
|
|
|
|
|
|
|
|
int64 getTotalLength() const override;
|
|
|
|
|
|
|
|
bool isLooping() const override;
|
|
|
|
|
2022-04-13 17:48:09 +00:00
|
|
|
String setAudioFile(const URL & file);
|
|
|
|
URL getAudioFile();
|
2017-11-13 15:06:08 +00:00
|
|
|
|
2017-12-13 03:18:39 +00:00
|
|
|
AudioBuffer<float>* getSourceAudioBuffer();
|
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
void setNumOutChannels(int chans);
|
|
|
|
int getNumOutChannels() { return m_num_outchans; }
|
|
|
|
double getInfilePositionPercent();
|
|
|
|
double getInfilePositionSeconds();
|
|
|
|
double getInfileLengthSeconds();
|
2019-01-20 13:24:30 +00:00
|
|
|
double getInfileSamplerate();
|
2017-11-13 15:06:08 +00:00
|
|
|
void setRate(double rate);
|
2018-09-13 10:47:19 +00:00
|
|
|
double getRate()
|
|
|
|
{
|
|
|
|
return m_playrate;
|
|
|
|
}
|
|
|
|
double getOutputSamplerate() const { return m_outsr; }
|
2017-11-13 15:06:08 +00:00
|
|
|
void setProcessParameters(ProcessParameters* pars);
|
2017-12-03 21:28:54 +00:00
|
|
|
const ProcessParameters& getProcessParameters();
|
2022-04-15 18:29:23 +00:00
|
|
|
void setFFTSize(int size, bool force=false);
|
2017-11-13 15:06:08 +00:00
|
|
|
int getFFTSize() { return m_process_fftsize; }
|
|
|
|
|
|
|
|
double getFreezePos() const { return m_freeze_pos; }
|
|
|
|
void setFreezing(bool b) { m_freezing = b; }
|
|
|
|
bool isFreezing() { return m_freezing; }
|
|
|
|
|
2017-12-14 20:17:45 +00:00
|
|
|
void setPaused(bool b);
|
|
|
|
bool isPaused() const;
|
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
void seekPercent(double pos);
|
|
|
|
|
|
|
|
double getOutputDurationSecondsForRange(Range<double> range, int fftsize);
|
|
|
|
|
|
|
|
void setOnsetDetection(double x);
|
2022-04-15 18:29:23 +00:00
|
|
|
void setPlayRange(Range<double> playrange, bool force=false);
|
2017-11-13 15:06:08 +00:00
|
|
|
Range<double> getPlayRange() { return m_playrange; }
|
|
|
|
bool isLoopEnabled();
|
|
|
|
bool hasReachedEnd();
|
|
|
|
bool isResampling();
|
2018-05-19 12:03:30 +00:00
|
|
|
int64_t getDiskReadSampleCount() const;
|
2018-01-30 15:32:23 +00:00
|
|
|
std::vector<SpectrumProcess> getSpectrumProcessOrder();
|
|
|
|
void setSpectrumProcessOrder(std::vector<SpectrumProcess> order);
|
2017-11-13 15:06:08 +00:00
|
|
|
void setFFTWindowingType(int windowtype);
|
|
|
|
int getFFTWindowingType() { return m_fft_window_type; }
|
|
|
|
std::pair<Range<double>,Range<double>> getFileCachedRangesNormalized();
|
2017-11-25 19:25:46 +00:00
|
|
|
|
2018-02-27 13:02:34 +00:00
|
|
|
void setFreeFilterEnvelope(shared_envelope env);
|
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
void setClippingEnabled(bool b) { m_clip_output = b; }
|
|
|
|
bool isLoopingEnabled();
|
|
|
|
void setLoopingEnabled(bool b);
|
|
|
|
void setMaxLoops(int64_t numloops) { m_maxloops = numloops; }
|
2017-11-13 20:35:36 +00:00
|
|
|
void setAudioBufferAsInputSource(AudioBuffer<float>* buf, int sr, int len);
|
2022-04-02 16:45:02 +00:00
|
|
|
bool isAudioBufferInputSource() const { return m_audiobuffer_is_source; }
|
2017-11-25 19:25:46 +00:00
|
|
|
void setMainVolume(double decibels);
|
|
|
|
double getMainVolume() const { return m_main_volume; }
|
2018-04-26 20:07:08 +00:00
|
|
|
//void setSpectralModulesEnabled(const std::array<AudioParameterBool*, 9>& params);
|
|
|
|
void setSpectralModuleEnabled(int index, bool b);
|
2017-11-25 19:25:46 +00:00
|
|
|
void setLoopXFadeLength(double lenseconds);
|
|
|
|
double getLoopXFadeLengtj() const { return m_loopxfadelen; }
|
2018-02-21 17:34:39 +00:00
|
|
|
void setPreviewDry(bool b);
|
|
|
|
bool isPreviewingDry() const;
|
2018-08-20 12:49:51 +00:00
|
|
|
void setDryPlayrate(double rate);
|
|
|
|
double getDryPlayrate() const;
|
2017-11-14 17:44:13 +00:00
|
|
|
int m_param_change_count = 0;
|
2018-05-11 13:45:34 +00:00
|
|
|
double getLastSeekPos() const { return m_seekpos; }
|
2018-02-27 13:21:36 +00:00
|
|
|
CriticalSection* getMutex() { return &m_cs; }
|
2018-09-13 10:47:19 +00:00
|
|
|
int64_t getLastSourcePosition() const { return m_last_filepos; }
|
2018-09-13 11:04:56 +00:00
|
|
|
int m_prebuffersize = 0;
|
2018-11-11 12:46:25 +00:00
|
|
|
void setSpectralOrderPreset(int id);
|
2019-01-17 13:23:01 +00:00
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
private:
|
|
|
|
CircularBuffer<float> m_stretchoutringbuf{ 1024 * 1024 };
|
|
|
|
AudioBuffer<float> m_file_inbuf;
|
|
|
|
LinearSmoothedValue<double> m_vol_smoother;
|
|
|
|
std::unique_ptr<AInputS> m_inputfile;
|
|
|
|
std::vector<std::shared_ptr<ProcessedStretch>> m_stretchers;
|
2018-02-28 17:32:17 +00:00
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
std::function<void(StretchAudioSource*)> SourceEndedCallback;
|
|
|
|
bool m_firstbuffer = false;
|
|
|
|
bool m_output_has_begun = false;
|
|
|
|
int m_num_outchans = 0;
|
|
|
|
double m_outsr = 44100.0;
|
|
|
|
int m_process_fftsize = 0;
|
|
|
|
int m_fft_window_type = -1;
|
2017-11-25 19:25:46 +00:00
|
|
|
double m_main_volume = 0.0;
|
|
|
|
double m_loopxfadelen = 0.0;
|
2017-11-13 15:06:08 +00:00
|
|
|
ProcessParameters m_ppar;
|
2018-02-28 17:32:17 +00:00
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
double m_playrate = 1.0;
|
|
|
|
double m_lastplayrate = 0.0;
|
|
|
|
double m_onsetdetection = 0.0;
|
|
|
|
double m_seekpos = 0.0;
|
2017-11-22 16:50:39 +00:00
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
bool m_freezing = false;
|
2018-04-23 17:55:25 +00:00
|
|
|
|
2022-04-15 23:13:55 +00:00
|
|
|
int m_pause_state = 2; // start paused
|
2017-11-13 15:06:08 +00:00
|
|
|
Range<double> m_playrange{ 0.0,1.0 };
|
2018-03-03 15:22:23 +00:00
|
|
|
int64_t m_rand_count = 0;
|
2019-01-17 13:23:01 +00:00
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
bool m_stream_end_reached = false;
|
|
|
|
int64_t m_output_silence_counter = 0;
|
2022-04-13 17:48:09 +00:00
|
|
|
URL m_curfile;
|
2022-04-02 16:45:02 +00:00
|
|
|
bool m_audiobuffer_is_source = false;
|
2017-11-13 15:06:08 +00:00
|
|
|
int64_t m_maxloops = 0;
|
|
|
|
std::unique_ptr<WDL_Resampler> m_resampler;
|
|
|
|
std::vector<double> m_resampler_outbuf;
|
2017-12-12 18:27:29 +00:00
|
|
|
CriticalSection m_cs;
|
2018-01-30 15:32:23 +00:00
|
|
|
std::vector<SpectrumProcess> m_specproc_order;
|
2018-04-26 20:15:39 +00:00
|
|
|
|
2017-11-13 15:06:08 +00:00
|
|
|
bool m_stop_play_requested = false;
|
|
|
|
double m_freeze_pos = 0.0;
|
|
|
|
int64_t m_output_counter = 0;
|
|
|
|
int64_t m_output_length = 0;
|
|
|
|
bool m_clip_output = true;
|
|
|
|
void initObjects();
|
2018-02-27 13:02:34 +00:00
|
|
|
shared_envelope m_free_filter_envelope;
|
2017-11-13 15:06:08 +00:00
|
|
|
AudioFormatManager* m_afm = nullptr;
|
2017-11-22 16:50:39 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
AudioBuffer<float> buffer;
|
|
|
|
int state = 0; // 0 not active, 1 fill xfade buffer, 2 play xfade buffer
|
|
|
|
int xfade_len = 0;
|
|
|
|
int counter = 0;
|
|
|
|
int requested_fft_size = 0;
|
|
|
|
File requested_file;
|
|
|
|
} m_xfadetask;
|
2017-12-14 20:17:45 +00:00
|
|
|
int m_pause_fade_counter = 0;
|
2018-02-21 17:34:39 +00:00
|
|
|
bool m_preview_dry = false;
|
2018-08-20 12:49:51 +00:00
|
|
|
double m_dryplayrate = 1.0;
|
2018-02-21 17:34:39 +00:00
|
|
|
AudioBuffer<float> m_drypreviewbuf;
|
2018-09-13 10:47:19 +00:00
|
|
|
int64_t m_last_filepos = 0;
|
2018-02-23 15:43:29 +00:00
|
|
|
void playDrySound(const AudioSourceChannelInfo & bufferToFill);
|
2018-11-11 12:46:25 +00:00
|
|
|
int m_current_spec_order_preset = -1;
|
2017-11-13 15:06:08 +00:00
|
|
|
};
|