@@ -97,9 +97,11 @@ void PaulstretchpluginAudioProcessorEditor::timerCallback(int id) | |||||
if (processor.isRecordingEnabled() != m_rec_enable.getToggleState()) | if (processor.isRecordingEnabled() != m_rec_enable.getToggleState()) | ||||
m_rec_enable.setToggleState(processor.isRecordingEnabled(), dontSendNotification); | m_rec_enable.setToggleState(processor.isRecordingEnabled(), dontSendNotification); | ||||
if (processor.isRecordingEnabled()) | if (processor.isRecordingEnabled()) | ||||
m_info_label.setText(String(processor.getRecordingPositionPercent()*100.0, 1),dontSendNotification); | |||||
else | |||||
m_info_label.setText(String(processor.m_control->getStretchAudioSource()->m_param_change_count), dontSendNotification); | |||||
{ | |||||
m_wavecomponent.setRecordingPosition(processor.getRecordingPositionPercent()); | |||||
} else | |||||
m_wavecomponent.setRecordingPosition(-1.0); | |||||
m_info_label.setText(String(processor.m_control->getStretchAudioSource()->m_param_change_count), dontSendNotification); | |||||
} | } | ||||
} | } | ||||
@@ -116,6 +118,16 @@ void PaulstretchpluginAudioProcessorEditor::setAudioBuffer(AudioBuffer<float>* b | |||||
}); | }); | ||||
} | } | ||||
void PaulstretchpluginAudioProcessorEditor::beginAddingAudioBlocks(int channels, int samplerate, int totalllen) | |||||
{ | |||||
m_wavecomponent.beginAddingAudioBlocks(channels, samplerate, totalllen); | |||||
} | |||||
void PaulstretchpluginAudioProcessorEditor::addAudioBlock(AudioBuffer<float>& buf, int samplerate, int pos) | |||||
{ | |||||
m_wavecomponent.addAudioBlock(buf, samplerate, pos); | |||||
} | |||||
WaveformComponent::WaveformComponent(AudioFormatManager* afm) : m_thumbcache(100) | WaveformComponent::WaveformComponent(AudioFormatManager* afm) : m_thumbcache(100) | ||||
{ | { | ||||
TimeSelectionChangedCallback = [](Range<double>, int) {}; | TimeSelectionChangedCallback = [](Range<double>, int) {}; | ||||
@@ -217,6 +229,12 @@ void WaveformComponent::paint(Graphics & g) | |||||
double pos = jmap<double>(CursorPosCallback(), m_view_range.getStart(), m_view_range.getEnd(), 0, getWidth()); | double pos = jmap<double>(CursorPosCallback(), m_view_range.getStart(), m_view_range.getEnd(), 0, getWidth()); | ||||
g.fillRect((int)pos, m_topmargin, 1, getHeight() - m_topmargin); | g.fillRect((int)pos, m_topmargin, 1, getHeight() - m_topmargin); | ||||
} | } | ||||
if (m_rec_pos >= 0.0) | |||||
{ | |||||
g.setColour(Colours::lightpink); | |||||
double pos = jmap<double>(m_rec_pos, m_view_range.getStart(), m_view_range.getEnd(), 0, getWidth()); | |||||
g.fillRect((int)pos, m_topmargin, 1, getHeight() - m_topmargin); | |||||
} | |||||
g.setColour(Colours::aqua.darker()); | g.setColour(Colours::aqua.darker()); | ||||
g.drawText(m_curfile.getFullPathName(), 2, m_topmargin + 2, getWidth(), 20, Justification::topLeft); | g.drawText(m_curfile.getFullPathName(), 2, m_topmargin + 2, getWidth(), 20, Justification::topLeft); | ||||
} | } | ||||
@@ -248,6 +266,18 @@ void WaveformComponent::setAudioBuffer(AudioBuffer<float>* buf, int samplerate, | |||||
m_thumb->addBlock(0, *buf, 0, len); | m_thumb->addBlock(0, *buf, 0, len); | ||||
} | } | ||||
void WaveformComponent::beginAddingAudioBlocks(int channels, int samplerate, int totalllen) | |||||
{ | |||||
m_waveimage = Image(); | |||||
m_curfile = File(); | |||||
m_thumb->reset(channels, samplerate, totalllen); | |||||
} | |||||
void WaveformComponent::addAudioBlock(AudioBuffer<float>& buf, int samplerate, int pos) | |||||
{ | |||||
m_thumb->addBlock(pos, buf, 0, buf.getNumSamples()); | |||||
} | |||||
void WaveformComponent::timerCallback() | void WaveformComponent::timerCallback() | ||||
{ | { | ||||
repaint(); | repaint(); | ||||
@@ -79,6 +79,8 @@ public: | |||||
void paint(Graphics& g) override; | void paint(Graphics& g) override; | ||||
void setAudioFile(File f); | void setAudioFile(File f); | ||||
void setAudioBuffer(AudioBuffer<float>* buf, int samplerate, int len); | void setAudioBuffer(AudioBuffer<float>* buf, int samplerate, int len); | ||||
void beginAddingAudioBlocks(int channels, int samplerate, int totalllen); | |||||
void addAudioBlock(AudioBuffer<float>& buf, int samplerate, int pos); | |||||
void timerCallback() override; | void timerCallback() override; | ||||
std::function<double()> CursorPosCallback; | std::function<double()> CursorPosCallback; | ||||
std::function<void(double)> SeekCallback; | std::function<void(double)> SeekCallback; | ||||
@@ -105,6 +107,7 @@ public: | |||||
void setTimerEnabled(bool b); | void setTimerEnabled(bool b); | ||||
void setViewRange(Range<double> rng); | void setViewRange(Range<double> rng); | ||||
Value ShowFileCacheRange; | Value ShowFileCacheRange; | ||||
void setRecordingPosition(double pos) { m_rec_pos = pos; } | |||||
private: | private: | ||||
AudioThumbnailCache m_thumbcache; | AudioThumbnailCache m_thumbcache; | ||||
@@ -124,6 +127,7 @@ private: | |||||
Image m_waveimage; | Image m_waveimage; | ||||
OpenGLContext m_ogl; | OpenGLContext m_ogl; | ||||
bool m_use_opengl = false; | bool m_use_opengl = false; | ||||
double m_rec_pos = 0.0; | |||||
}; | }; | ||||
@@ -140,6 +144,8 @@ public: | |||||
void timerCallback(int id) override; | void timerCallback(int id) override; | ||||
void setAudioFile(File f); | void setAudioFile(File f); | ||||
void setAudioBuffer(AudioBuffer<float>* buf, int samplerate, int len); | void setAudioBuffer(AudioBuffer<float>* buf, int samplerate, int len); | ||||
void beginAddingAudioBlocks(int channels, int samplerate, int totalllen); | |||||
void addAudioBlock(AudioBuffer<float>& buf, int samplerate, int pos); | |||||
private: | private: | ||||
PaulstretchpluginAudioProcessor& processor; | PaulstretchpluginAudioProcessor& processor; | ||||
std::vector<std::shared_ptr<ParameterComponent>> m_parcomps; | std::vector<std::shared_ptr<ParameterComponent>> m_parcomps; | ||||
@@ -10,7 +10,8 @@ | |||||
#include "PluginProcessor.h" | #include "PluginProcessor.h" | ||||
#include "PluginEditor.h" | #include "PluginEditor.h" | ||||
std::unique_ptr<PropertiesFile> g_propsfile; | |||||
#undef min | |||||
#undef max | |||||
//============================================================================== | //============================================================================== | ||||
PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor() | PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor() | ||||
@@ -30,7 +31,7 @@ PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor() | |||||
m_afm = std::make_unique<AudioFormatManager>(); | m_afm = std::make_unique<AudioFormatManager>(); | ||||
m_afm->registerBasicFormats(); | m_afm->registerBasicFormats(); | ||||
m_control = std::make_unique<Control>(m_afm.get()); | m_control = std::make_unique<Control>(m_afm.get()); | ||||
m_control->setPreBufferAmount(3); | |||||
m_control->setPreBufferAmount(2); | |||||
m_control->ppar.pitch_shift.enabled = true; | m_control->ppar.pitch_shift.enabled = true; | ||||
m_control->ppar.freq_shift.enabled = true; | m_control->ppar.freq_shift.enabled = true; | ||||
m_control->setOnsetDetection(0.0); | m_control->setOnsetDetection(0.0); | ||||
@@ -126,7 +127,7 @@ void PaulstretchpluginAudioProcessor::prepareToPlay(double sampleRate, int sampl | |||||
} | } | ||||
if (m_ready_to_play == false) | if (m_ready_to_play == false) | ||||
{ | { | ||||
m_control->setFFTSize(0.7); | |||||
m_control->setFFTSize(0.2); | |||||
m_control->update_player_stretch(); | m_control->update_player_stretch(); | ||||
m_control->update_process_parameters(); | m_control->update_process_parameters(); | ||||
@@ -169,6 +170,25 @@ bool PaulstretchpluginAudioProcessor::isBusesLayoutSupported (const BusesLayout& | |||||
} | } | ||||
#endif | #endif | ||||
void copyAudioBufferWrappingPosition(const AudioBuffer<float>& src, AudioBuffer<float>& dest, int destbufpos, int maxdestpos) | |||||
{ | |||||
for (int i = 0; i < dest.getNumChannels(); ++i) | |||||
{ | |||||
int channel_to_copy = i % src.getNumChannels(); | |||||
if (destbufpos + src.getNumSamples() > maxdestpos) | |||||
{ | |||||
int wrappos = (destbufpos + src.getNumSamples()) % maxdestpos; | |||||
int partial_len = src.getNumSamples() - wrappos; | |||||
dest.copyFrom(channel_to_copy, destbufpos, src, channel_to_copy, 0, partial_len); | |||||
dest.copyFrom(channel_to_copy, partial_len, src, channel_to_copy, 0, wrappos); | |||||
} | |||||
else | |||||
{ | |||||
dest.copyFrom(channel_to_copy, destbufpos, src, channel_to_copy, 0, src.getNumSamples()); | |||||
} | |||||
} | |||||
} | |||||
void PaulstretchpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) | void PaulstretchpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) | ||||
{ | { | ||||
std::lock_guard<std::mutex> locker(m_mutex); | std::lock_guard<std::mutex> locker(m_mutex); | ||||
@@ -182,16 +202,13 @@ void PaulstretchpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, M | |||||
return; | return; | ||||
if (m_is_recording == true) | if (m_is_recording == true) | ||||
{ | { | ||||
if (m_rec_pos + buffer.getNumSamples() < m_recbuffer.getNumSamples()) | |||||
{ | |||||
m_recbuffer.copyFrom(0, m_rec_pos, buffer, 0, 0, buffer.getNumSamples()); | |||||
m_recbuffer.copyFrom(1, m_rec_pos, buffer, 1, 0, buffer.getNumSamples()); | |||||
} | |||||
m_rec_pos += buffer.getNumSamples(); | |||||
if (m_rec_pos >= m_max_reclen * getSampleRate()) | |||||
int recbuflenframes = m_max_reclen * getSampleRate(); | |||||
copyAudioBufferWrappingPosition(buffer, m_recbuffer, m_rec_pos, recbuflenframes); | |||||
callGUI([this, &buffer](PaulstretchpluginAudioProcessorEditor*ed) | |||||
{ | { | ||||
finishRecording(m_max_reclen*getSampleRate()); | |||||
} | |||||
ed->addAudioBlock(buffer, getSampleRate(), m_rec_pos); | |||||
}, false); | |||||
m_rec_pos = (m_rec_pos + buffer.getNumSamples()) % recbuflenframes; | |||||
return; | return; | ||||
} | } | ||||
m_control->getStretchAudioSource()->val_MainVolume = (float)*getFloatParameter(0); | m_control->getStretchAudioSource()->val_MainVolume = (float)*getFloatParameter(0); | ||||
@@ -239,18 +256,23 @@ void PaulstretchpluginAudioProcessor::setStateInformation (const void* data, int | |||||
void PaulstretchpluginAudioProcessor::setRecordingEnabled(bool b) | void PaulstretchpluginAudioProcessor::setRecordingEnabled(bool b) | ||||
{ | { | ||||
std::lock_guard<std::mutex> locker(m_mutex); | std::lock_guard<std::mutex> locker(m_mutex); | ||||
int lenbufframes = getSampleRate()*m_max_reclen; | |||||
if (b == true) | if (b == true) | ||||
{ | { | ||||
m_recbuffer.setSize(2, m_max_reclen*getSampleRate()+4096); | m_recbuffer.setSize(2, m_max_reclen*getSampleRate()+4096); | ||||
m_recbuffer.clear(); | m_recbuffer.clear(); | ||||
m_rec_pos = 0; | m_rec_pos = 0; | ||||
callGUI([this,lenbufframes](PaulstretchpluginAudioProcessorEditor* ed) | |||||
{ | |||||
ed->beginAddingAudioBlocks(2, getSampleRate(), lenbufframes); | |||||
},false); | |||||
m_is_recording = true; | m_is_recording = true; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
if (m_is_recording == true) | if (m_is_recording == true) | ||||
{ | { | ||||
finishRecording(m_rec_pos); | |||||
finishRecording(lenbufframes); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -281,7 +303,7 @@ void PaulstretchpluginAudioProcessor::finishRecording(int lenrecording) | |||||
auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(getActiveEditor()); | auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(getActiveEditor()); | ||||
if (ed) | if (ed) | ||||
{ | { | ||||
ed->setAudioBuffer(&m_recbuffer, getSampleRate(), lenrecording); | |||||
//ed->setAudioBuffer(&m_recbuffer, getSampleRate(), lenrecording); | |||||
} | } | ||||
} | } | ||||
@@ -71,7 +71,7 @@ private: | |||||
bool m_ready_to_play = false; | bool m_ready_to_play = false; | ||||
AudioBuffer<float> m_recbuffer; | AudioBuffer<float> m_recbuffer; | ||||
double m_max_reclen = 10.0; | |||||
double m_max_reclen = 5; | |||||
bool m_is_recording = false; | bool m_is_recording = false; | ||||
int m_rec_pos = 0; | int m_rec_pos = 0; | ||||
void finishRecording(int lenrecorded); | void finishRecording(int lenrecorded); | ||||