Audio input capture more or less running
This commit is contained in:
parent
c32e64a570
commit
76de3b12a5
@ -48,14 +48,27 @@ public:
|
|||||||
PlayRangeEndCallback=[](AInputS*){};
|
PlayRangeEndCallback=[](AInputS*){};
|
||||||
}
|
}
|
||||||
~AInputS() {}
|
~AInputS() {}
|
||||||
|
void setAudioBuffer(AudioBuffer<float>* buf, int samplerate, int len)
|
||||||
|
{
|
||||||
|
m_afreader = nullptr;
|
||||||
|
m_using_memory_buffer = true;
|
||||||
|
m_readbuf = *buf;
|
||||||
|
info.nchannels = buf->getNumChannels();
|
||||||
|
info.nsamples = len;
|
||||||
|
info.samplerate = samplerate;
|
||||||
|
m_currentsample = 0;
|
||||||
|
m_crossfadebuf.setSize(info.nchannels, m_crossfadebuf.getNumSamples());
|
||||||
|
m_cached_file_range = { 0,len };
|
||||||
|
updateXFadeCache();
|
||||||
|
}
|
||||||
bool openAudioFile(File file) override
|
bool openAudioFile(File file) override
|
||||||
{
|
{
|
||||||
m_silenceoutputted = 0;
|
m_silenceoutputted = 0;
|
||||||
AudioFormatReader* reader = m_manager->createReaderFor(file);
|
AudioFormatReader* reader = m_manager->createReaderFor(file);
|
||||||
if (reader)
|
if (reader)
|
||||||
{
|
{
|
||||||
m_afreader = std::unique_ptr<AudioFormatReader>(reader);
|
m_using_memory_buffer = false;
|
||||||
|
m_afreader = std::unique_ptr<AudioFormatReader>(reader);
|
||||||
m_currentsample = 0;
|
m_currentsample = 0;
|
||||||
info.samplerate = (int)m_afreader->sampleRate;
|
info.samplerate = (int)m_afreader->sampleRate;
|
||||||
info.nchannels = m_afreader->numChannels;
|
info.nchannels = m_afreader->numChannels;
|
||||||
@ -80,9 +93,12 @@ public:
|
|||||||
}
|
}
|
||||||
int readNextBlock(AudioBuffer<float>& abuf, int nsmps, int numchans) override
|
int readNextBlock(AudioBuffer<float>& abuf, int nsmps, int numchans) override
|
||||||
{
|
{
|
||||||
if (m_afreader == nullptr)
|
if (m_afreader == nullptr && m_using_memory_buffer == false)
|
||||||
return 0;
|
return 0;
|
||||||
int inchans = m_afreader->numChannels;
|
int inchans = 0;
|
||||||
|
if (m_afreader)
|
||||||
|
inchans = m_afreader->numChannels;
|
||||||
|
else inchans = m_readbuf.getNumChannels();
|
||||||
int64_t subsect_t0 = (int64_t)(m_activerange.getStart()*info.nsamples);
|
int64_t subsect_t0 = (int64_t)(m_activerange.getStart()*info.nsamples);
|
||||||
int64_t subsect_t1 = (int64_t)(m_activerange.getEnd()*info.nsamples);
|
int64_t subsect_t1 = (int64_t)(m_activerange.getEnd()*info.nsamples);
|
||||||
int64_t subsectlen = subsect_t1 - subsect_t0;
|
int64_t subsectlen = subsect_t1 - subsect_t0;
|
||||||
@ -130,7 +146,7 @@ public:
|
|||||||
for (int i = 0; i < nsmps; ++i)
|
for (int i = 0; i < nsmps; ++i)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_afreader->numChannels == 1 && numchans > 0)
|
if (inchans == 1 && numchans > 0)
|
||||||
{
|
{
|
||||||
float sig = getCrossFadedSampleLambda(m_currentsample, 0, subsect_t0, subsect_t1, xfadelen);
|
float sig = getCrossFadedSampleLambda(m_currentsample, 0, subsect_t0, subsect_t1, xfadelen);
|
||||||
for (int j = 0; j < numchans; ++j)
|
for (int j = 0; j < numchans; ++j)
|
||||||
@ -138,7 +154,7 @@ public:
|
|||||||
smps[j][i] = sig;
|
smps[j][i] = sig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_afreader->numChannels > 1 && numchans > 1)
|
else if (inchans > 1 && numchans > 1)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < numchans; ++j)
|
for (int j = 0; j < numchans; ++j)
|
||||||
{
|
{
|
||||||
@ -172,6 +188,17 @@ public:
|
|||||||
}
|
}
|
||||||
void seek(double pos) override //0=start,1.0=end
|
void seek(double pos) override //0=start,1.0=end
|
||||||
{
|
{
|
||||||
|
if (m_using_memory_buffer == true)
|
||||||
|
{
|
||||||
|
jassert(m_readbuf.getNumSamples() > 0 && m_afreader==nullptr);
|
||||||
|
m_loopcount = 0;
|
||||||
|
m_silenceoutputted = 0;
|
||||||
|
m_cache_misses = 0;
|
||||||
|
m_currentsample = (int64_t)(pos*m_readbuf.getNumSamples());
|
||||||
|
m_currentsample = jlimit<int64_t>(0, m_readbuf.getNumSamples(), m_currentsample);
|
||||||
|
m_cached_file_range = { 0,m_readbuf.getNumSamples() };
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (m_afreader==nullptr)
|
if (m_afreader==nullptr)
|
||||||
return;
|
return;
|
||||||
m_loopcount = 0;
|
m_loopcount = 0;
|
||||||
@ -199,8 +226,11 @@ public:
|
|||||||
{
|
{
|
||||||
if (m_xfadelen>m_crossfadebuf.getNumSamples())
|
if (m_xfadelen>m_crossfadebuf.getNumSamples())
|
||||||
m_crossfadebuf.setSize(info.nchannels,m_xfadelen);
|
m_crossfadebuf.setSize(info.nchannels,m_xfadelen);
|
||||||
m_afreader->read(&m_crossfadebuf, 0, m_xfadelen, (int64_t)(m_activerange.getStart()*info.nsamples), true, true);
|
if (m_afreader != nullptr && m_using_memory_buffer == false)
|
||||||
m_cached_crossfade_range =
|
m_afreader->read(&m_crossfadebuf, 0, m_xfadelen, (int64_t)(m_activerange.getStart()*info.nsamples), true, true);
|
||||||
|
if (m_afreader == nullptr && m_using_memory_buffer == true)
|
||||||
|
m_crossfadebuf.copyFrom(0, 0, m_readbuf, 0, (int64_t)(m_activerange.getStart()*info.nsamples), m_xfadelen);
|
||||||
|
m_cached_crossfade_range =
|
||||||
Range<int64_t>((int64_t)(m_activerange.getStart()*info.nsamples),(int64_t)(m_activerange.getStart()*info.nsamples+m_xfadelen));
|
Range<int64_t>((int64_t)(m_activerange.getStart()*info.nsamples),(int64_t)(m_activerange.getStart()*info.nsamples+m_xfadelen));
|
||||||
}
|
}
|
||||||
void setActiveRange(Range<double> rng) override
|
void setActiveRange(Range<double> rng) override
|
||||||
@ -243,6 +273,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool isReversed() { return m_reverseplay; }
|
bool isReversed() { return m_reverseplay; }
|
||||||
int64_t getLoopCount() { return m_loopcount; }
|
int64_t getLoopCount() { return m_loopcount; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<void(AInputS*)> PlayRangeEndCallback;
|
std::function<void(AInputS*)> PlayRangeEndCallback;
|
||||||
std::unique_ptr<AudioFormatReader> m_afreader;
|
std::unique_ptr<AudioFormatReader> m_afreader;
|
||||||
@ -256,5 +287,6 @@ private:
|
|||||||
int m_xfadelen = 0;
|
int m_xfadelen = 0;
|
||||||
bool m_reverseplay = false;
|
bool m_reverseplay = false;
|
||||||
int64_t m_loopcount = 0;
|
int64_t m_loopcount = 0;
|
||||||
|
bool m_using_memory_buffer = false;
|
||||||
AudioFormatManager* m_manager = nullptr;
|
AudioFormatManager* m_manager = nullptr;
|
||||||
};
|
};
|
||||||
|
@ -116,6 +116,14 @@ void StretchAudioSource::setLoopingEnabled(bool b)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StretchAudioSource::setAudioBufferAsInputSource(AudioBuffer<float>* buf, int sr, int len)
|
||||||
|
{
|
||||||
|
std::lock_guard <std::mutex> locker(m_mutex);
|
||||||
|
m_inputfile->setAudioBuffer(buf, sr, len);
|
||||||
|
m_seekpos = 0.0;
|
||||||
|
m_lastinpos = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
void StretchAudioSource::getNextAudioBlock(const AudioSourceChannelInfo & bufferToFill)
|
void StretchAudioSource::getNextAudioBlock(const AudioSourceChannelInfo & bufferToFill)
|
||||||
{
|
{
|
||||||
// for realtime play, this is assumed to be used with BufferingAudioSource, so mutex locking should not be too bad...
|
// for realtime play, this is assumed to be used with BufferingAudioSource, so mutex locking should not be too bad...
|
||||||
@ -489,6 +497,12 @@ std::pair<Range<double>, Range<double>> MultiStretchAudioSource::getFileCachedRa
|
|||||||
return getActiveStretchSource()->getFileCachedRangesNormalized();
|
return getActiveStretchSource()->getFileCachedRangesNormalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MultiStretchAudioSource::setAudioBufferAsInputSource(AudioBuffer<float>* buf, int sr, int len)
|
||||||
|
{
|
||||||
|
m_stretchsources[0]->setAudioBufferAsInputSource(buf, sr, len);
|
||||||
|
m_stretchsources[1]->setAudioBufferAsInputSource(buf, sr, len);
|
||||||
|
}
|
||||||
|
|
||||||
StretchAudioSource * MultiStretchAudioSource::getActiveStretchSource() const
|
StretchAudioSource * MultiStretchAudioSource::getActiveStretchSource() const
|
||||||
{
|
{
|
||||||
return m_stretchsources[0].get();
|
return m_stretchsources[0].get();
|
||||||
|
@ -90,6 +90,7 @@ public:
|
|||||||
bool isLoopingEnabled();
|
bool isLoopingEnabled();
|
||||||
void setLoopingEnabled(bool b);
|
void setLoopingEnabled(bool b);
|
||||||
void setMaxLoops(int64_t numloops) { m_maxloops = numloops; }
|
void setMaxLoops(int64_t numloops) { m_maxloops = numloops; }
|
||||||
|
void setAudioBufferAsInputSource(AudioBuffer<float>* buf, int sr, int len);
|
||||||
private:
|
private:
|
||||||
CircularBuffer<float> m_stretchoutringbuf{ 1024 * 1024 };
|
CircularBuffer<float> m_stretchoutringbuf{ 1024 * 1024 };
|
||||||
AudioBuffer<float> m_file_inbuf;
|
AudioBuffer<float> m_file_inbuf;
|
||||||
@ -187,6 +188,7 @@ public:
|
|||||||
Value val_XFadeLen;
|
Value val_XFadeLen;
|
||||||
//ValueTree getStateTree();
|
//ValueTree getStateTree();
|
||||||
//void setStateTree(ValueTree state);
|
//void setStateTree(ValueTree state);
|
||||||
|
void setAudioBufferAsInputSource(AudioBuffer<float>* buf, int sr, int len);
|
||||||
private:
|
private:
|
||||||
std::vector<std::shared_ptr<StretchAudioSource>> m_stretchsources;
|
std::vector<std::shared_ptr<StretchAudioSource>> m_stretchsources;
|
||||||
bool m_is_in_switch{ false };
|
bool m_is_in_switch{ false };
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor (PaulstretchpluginAudioProcessor& p)
|
PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor (PaulstretchpluginAudioProcessor& p)
|
||||||
: AudioProcessorEditor (&p), processor (p)
|
: AudioProcessorEditor (&p), processor (p)
|
||||||
{
|
{
|
||||||
|
addAndMakeVisible(&m_info_label);
|
||||||
const auto& pars = processor.getParameters();
|
const auto& pars = processor.getParameters();
|
||||||
for (int i=0;i<pars.size();++i)
|
for (int i=0;i<pars.size();++i)
|
||||||
{
|
{
|
||||||
@ -52,6 +53,7 @@ void PaulstretchpluginAudioProcessorEditor::resized()
|
|||||||
{
|
{
|
||||||
m_rec_enable.setBounds(1, getHeight() - 25, 10, 24);
|
m_rec_enable.setBounds(1, getHeight() - 25, 10, 24);
|
||||||
m_rec_enable.changeWidthToFitText();
|
m_rec_enable.changeWidthToFitText();
|
||||||
|
m_info_label.setBounds(m_rec_enable.getRight() + 1, getHeight() - 25, 60, 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaulstretchpluginAudioProcessorEditor::timerCallback(int id)
|
void PaulstretchpluginAudioProcessorEditor::timerCallback(int id)
|
||||||
@ -60,5 +62,8 @@ void PaulstretchpluginAudioProcessorEditor::timerCallback(int id)
|
|||||||
{
|
{
|
||||||
for (auto& e : m_parcomps)
|
for (auto& e : m_parcomps)
|
||||||
e->updateComponent();
|
e->updateComponent();
|
||||||
|
if (processor.isRecordingEnabled() != m_rec_enable.getToggleState())
|
||||||
|
m_rec_enable.setToggleState(processor.isRecordingEnabled(), dontSendNotification);
|
||||||
|
m_info_label.setText(String(processor.getRecordingPositionPercent()*100.0, 1),dontSendNotification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,5 +85,6 @@ private:
|
|||||||
PaulstretchpluginAudioProcessor& processor;
|
PaulstretchpluginAudioProcessor& processor;
|
||||||
std::vector<std::shared_ptr<ParameterComponent>> m_parcomps;
|
std::vector<std::shared_ptr<ParameterComponent>> m_parcomps;
|
||||||
ToggleButton m_rec_enable;
|
ToggleButton m_rec_enable;
|
||||||
|
Label m_info_label;
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PaulstretchpluginAudioProcessorEditor)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PaulstretchpluginAudioProcessorEditor)
|
||||||
};
|
};
|
||||||
|
@ -167,11 +167,17 @@ 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();
|
m_rec_pos += buffer.getNumSamples();
|
||||||
if (m_rec_pos >= m_max_reclen * getSampleRate())
|
if (m_rec_pos >= m_max_reclen * getSampleRate())
|
||||||
{
|
{
|
||||||
m_is_recording = false;
|
m_is_recording = false;
|
||||||
// Set record buffer as strech source...
|
m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer, getSampleRate(),
|
||||||
|
m_max_reclen*getSampleRate());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -220,15 +226,24 @@ void PaulstretchpluginAudioProcessor::setRecordingEnabled(bool b)
|
|||||||
if (b == true)
|
if (b == true)
|
||||||
{
|
{
|
||||||
m_is_recording = true;
|
m_is_recording = true;
|
||||||
m_recbuffer.setSize(2, m_max_reclen*getSampleRate());
|
m_recbuffer.setSize(2, m_max_reclen*getSampleRate()+4096);
|
||||||
|
m_recbuffer.clear();
|
||||||
m_rec_pos = 0;
|
m_rec_pos = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_is_recording = false;
|
m_is_recording = false;
|
||||||
|
m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer, getSampleRate(), m_rec_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double PaulstretchpluginAudioProcessor::getRecordingPositionPercent()
|
||||||
|
{
|
||||||
|
if (m_is_recording==false)
|
||||||
|
return 0.0;
|
||||||
|
return 1.0 / m_recbuffer.getNumSamples()*m_rec_pos;
|
||||||
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// This creates new instances of the plugin..
|
// This creates new instances of the plugin..
|
||||||
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
|
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
|
||||||
|
@ -60,13 +60,15 @@ public:
|
|||||||
return dynamic_cast<AudioParameterFloat*>(getParameters()[index]);
|
return dynamic_cast<AudioParameterFloat*>(getParameters()[index]);
|
||||||
}
|
}
|
||||||
void setRecordingEnabled(bool b);
|
void setRecordingEnabled(bool b);
|
||||||
|
bool isRecordingEnabled() { return m_is_recording; }
|
||||||
|
double getRecordingPositionPercent();
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Control> m_control;
|
std::unique_ptr<Control> m_control;
|
||||||
std::unique_ptr<AudioFormatManager> m_afm;
|
std::unique_ptr<AudioFormatManager> m_afm;
|
||||||
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 = 10.0;
|
||||||
bool m_is_recording = true;
|
bool m_is_recording = false;
|
||||||
int m_rec_pos = 0;
|
int m_rec_pos = 0;
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PaulstretchpluginAudioProcessor)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PaulstretchpluginAudioProcessor)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user