Some improvements. To keep things saner use the single stretch source for now.
This commit is contained in:
		| @@ -48,6 +48,7 @@ public: | ||||
|         PlayRangeEndCallback=[](AInputS*){}; | ||||
| 	} | ||||
|     ~AInputS() {} | ||||
|  | ||||
| 	void setAudioBuffer(AudioBuffer<float>* buf, int samplerate, int len) | ||||
| 	{ | ||||
| 		m_afreader = nullptr; | ||||
| @@ -60,6 +61,7 @@ public: | ||||
| 		m_loop_enabled = true; | ||||
| 		m_crossfadebuf.setSize(info.nchannels, m_crossfadebuf.getNumSamples()); | ||||
| 		m_cached_file_range = { 0,len }; | ||||
| 		seek(m_activerange.getStart()); | ||||
| 		updateXFadeCache(); | ||||
| 	} | ||||
| 	bool openAudioFile(File file) override | ||||
|   | ||||
| @@ -33,7 +33,7 @@ extern std::unique_ptr<PropertiesFile> g_propsfile; | ||||
|  | ||||
| Control::Control(AudioFormatManager* afm) : m_afm(afm), m_bufferingthread("stretchbufferingthread") | ||||
| { | ||||
| 	m_stretch_source = std::make_unique<MultiStretchAudioSource>(2,m_afm); | ||||
| 	m_stretch_source = std::make_unique<StretchAudioSource>(2,m_afm); | ||||
| 	 | ||||
| 	 | ||||
| 	wavinfo.samplerate=44100; | ||||
| @@ -619,91 +619,3 @@ void Control::update_process_parameters() | ||||
| 	//if (player)  | ||||
| 	//	player->set_process_parameters(&ppar,&bbpar); | ||||
| }; | ||||
|  | ||||
| AudioCallback::AudioCallback() : AudioIODeviceCallback(),  | ||||
| 	m_writethread("audio_out_record_thread") | ||||
| { | ||||
| 	 | ||||
| } | ||||
|  | ||||
| void AudioCallback::audioDeviceAboutToStart(AudioIODevice * device)  | ||||
| { | ||||
| 	m_debugcount = 0; | ||||
| 	m_outpos = 0.0; | ||||
| 	m_outsr = device->getCurrentSampleRate(); | ||||
| 	if (m_aviscomponent) | ||||
| 		m_aviscomponent->setNumChannels(m_numoutchans); | ||||
| 	if (m_bufferingsource) | ||||
| 	{ | ||||
| 		if (m_prebufferthread->isThreadRunning()==false) | ||||
| 			m_prebufferthread->startThread(g_propsfile->getIntValue("prebufthreadpriority",5)); | ||||
| 		int bufsize = std::max(512, device->getCurrentBufferSizeSamples()); | ||||
| 		//Logger::writeToLog("Using buffer size " + String(bufsize)); | ||||
| 		m_bufferingsource->prepareToPlay(bufsize, m_outsr); | ||||
| 	} | ||||
| 	m_playing = true; | ||||
| 	//Logger::writeToLog("hw samplerate " + String(m_outsr)); | ||||
| } | ||||
|  | ||||
| void AudioCallback::audioDeviceStopped()  | ||||
| { | ||||
| 	m_writer = nullptr; | ||||
| 	if (m_writethread.isThreadRunning() == true) | ||||
| 	{ | ||||
| 		if (m_writethread.stopThread(1000) == false) | ||||
| 		{ | ||||
| 			Logger::writeToLog("OUCH, live output recording thread didn't stop cleanly!"); | ||||
| 		} | ||||
| 	} | ||||
| 	if (m_bufferingsource) | ||||
| 	{ | ||||
| 		m_bufferingsource->releaseResources(); | ||||
| 		if (m_prebufferthread->isThreadRunning() == true) | ||||
| 		{ | ||||
| 			if (m_prebufferthread->stopThread(1000) == false) | ||||
| 				Logger::writeToLog("OUCH, prebuffering thread did not stop cleanly!"); | ||||
| 		} | ||||
| 	} | ||||
| 	m_playing = false; | ||||
| } | ||||
|  | ||||
| void AudioCallback::audioDeviceIOCallback(const float ** /*inputChannelData*/, int, float ** outputChannelData, int numOutputChannels, int numSamples) | ||||
| { | ||||
| 	if (m_bufferingsource == nullptr) | ||||
| 		return; | ||||
| 	AudioBuffer<float> buf(outputChannelData, numOutputChannels, numSamples); | ||||
| 	AudioSourceChannelInfo ainfo(buf); | ||||
| 	m_bufferingsource->getNextAudioBlock(ainfo); | ||||
| 	if (m_aviscomponent && m_aviscomponent->isVisible()) | ||||
| 	{ | ||||
| 		m_aviscomponent->pushBuffer((const float**)outputChannelData, m_numoutchans, numSamples); | ||||
| 	} | ||||
| 	if (m_writer && m_is_recording == true) | ||||
| 	{ | ||||
| 		m_writer->write((const float**)outputChannelData, numSamples); | ||||
|     } | ||||
|     m_outpos += (double)numSamples / m_outsr; | ||||
| } | ||||
|  | ||||
| String AudioCallback::startRecording(File outfile) | ||||
| { | ||||
| 	WavAudioFormat wavformat; | ||||
| 	auto outstream = outfile.createOutputStream(); | ||||
| 	if (outstream == nullptr) | ||||
| 		return "Could not create output stream"; | ||||
| 	auto writer = wavformat.createWriterFor(outstream, m_outsr, m_numoutchans, 32, StringPairArray(), 0); | ||||
| 	if (writer != nullptr) | ||||
| 	{ | ||||
| 		if (m_writethread.isThreadRunning()==false) | ||||
| 			m_writethread.startThread(); | ||||
| 		m_writer = std::make_unique<AudioFormatWriter::ThreadedWriter>(writer, m_writethread, 65536); | ||||
| 		m_is_recording = true; | ||||
| 		return String(); | ||||
| 	} | ||||
| 	return "Could not create audio writer"; | ||||
| } | ||||
|  | ||||
| void AudioCallback::setNumOutchans(int numchans) | ||||
| { | ||||
| 	m_numoutchans = jlimit(2, g_maxnumoutchans, numchans); | ||||
| } | ||||
|   | ||||
| @@ -26,36 +26,6 @@ Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA | ||||
| #include "../JuceLibraryCode/JuceHeader.h" | ||||
| #include "../ps3_BufferingAudioSource.h" | ||||
|  | ||||
| class AudioCallback : public AudioIODeviceCallback | ||||
| { | ||||
| public: | ||||
| 	AudioCallback(); | ||||
| 	void audioDeviceAboutToStart(AudioIODevice* device) override; | ||||
| 	void audioDeviceStopped() override; | ||||
|     void audioDeviceIOCallback (const float** inputChannelData, | ||||
|                                 int numInputChannels, | ||||
|                                 float** outputChannelData, | ||||
|                                 int numOutputChannels, | ||||
| 		int numSamples) override; | ||||
| 	String startRecording(File outfile); | ||||
| 	 | ||||
| 	std::atomic<bool> m_is_recording{ false }; | ||||
| 	AudioVisualiserComponent* m_aviscomponent = nullptr; | ||||
| 	std::unique_ptr<AudioFormatWriter::ThreadedWriter> m_writer; | ||||
| 	TimeSliceThread m_writethread; | ||||
| 	TimeSliceThread* m_prebufferthread = nullptr; | ||||
| 	MyBufferingAudioSource* m_bufferingsource = nullptr; | ||||
| 	MultiStretchAudioSource* m_sas = nullptr; | ||||
| 	std::atomic<bool> m_playing{false}; | ||||
| 	double m_outpos = 0.0; | ||||
| 	void setNumOutchans(int numchans); | ||||
| private: | ||||
| 	std::mutex m_mutex; | ||||
| 	int m_debugcount = 0; | ||||
| 	int m_outsr = 44100; | ||||
| 	int m_numoutchans = 2; | ||||
| }; | ||||
|  | ||||
| class RenderInfo | ||||
| { | ||||
| public: | ||||
| @@ -102,7 +72,7 @@ public: | ||||
| 	void setFFTSize(double size); | ||||
| 	int getFFTSize() { return m_fft_size_to_use; } | ||||
| 	void setOnsetDetection(double x); | ||||
| 	MultiStretchAudioSource* getStretchAudioSource() { return m_stretch_source.get(); } | ||||
| 	StretchAudioSource* getStretchAudioSource() { return m_stretch_source.get(); } | ||||
|     void set_input_file(File filename, std::function<void(String)> cb);//return non empty String if the file cannot be opened | ||||
| 	String get_input_filename(); | ||||
| 	String get_stretch_info(Range<double> playrange); | ||||
| @@ -169,7 +139,7 @@ private: | ||||
|     REALTYPE seek_pos; | ||||
| 	AudioFormatManager* m_afm = nullptr; | ||||
|     TimeSliceThread m_bufferingthread; | ||||
| 	std::unique_ptr<MultiStretchAudioSource> m_stretch_source; | ||||
| 	std::unique_ptr<StretchAudioSource> m_stretch_source; | ||||
| 	std::unique_ptr<MyBufferingAudioSource> m_buffering_source; | ||||
| 	int m_prebuffer_amount = 1; | ||||
| 	bool m_recreate_buffering_source = true; | ||||
|   | ||||
| @@ -123,6 +123,8 @@ void StretchAudioSource::setAudioBufferAsInputSource(AudioBuffer<float>* buf, in | ||||
| 	m_seekpos = 0.0; | ||||
| 	m_lastinpos = 0.0; | ||||
| 	m_curfile = File(); | ||||
| 	if (m_playrange.isEmpty()) | ||||
| 		setPlayRange({ 0.0,1.0 }, true); | ||||
| } | ||||
|  | ||||
| void StretchAudioSource::getNextAudioBlock(const AudioSourceChannelInfo & bufferToFill) | ||||
|   | ||||
| @@ -40,6 +40,7 @@ PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor (Pa | ||||
| 	}; | ||||
| 	m_wavecomponent.ShowFileCacheRange = true; | ||||
| 	startTimer(1, 100); | ||||
| 	m_wavecomponent.startTimer(100); | ||||
| } | ||||
|  | ||||
| PaulstretchpluginAudioProcessorEditor::~PaulstretchpluginAudioProcessorEditor() | ||||
|   | ||||
| @@ -114,7 +114,17 @@ void PaulstretchpluginAudioProcessor::changeProgramName (int index, const String | ||||
| void PaulstretchpluginAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) | ||||
| { | ||||
| 	if (m_using_memory_buffer == true) | ||||
| 		m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer, getSampleRate(), m_recbuffer.getNumSamples()); | ||||
| 	{ | ||||
| 		int len = jlimit(100,m_recbuffer.getNumSamples(), m_rec_pos); | ||||
| 		m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer,  | ||||
| 			getSampleRate(),  | ||||
| 			len); | ||||
| 		auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(getActiveEditor()); | ||||
| 		if (ed) | ||||
| 		{ | ||||
| 			ed->setAudioBuffer(&m_recbuffer, getSampleRate(), len); | ||||
| 		} | ||||
| 	} | ||||
| 	if (m_ready_to_play == false) | ||||
| 	{ | ||||
| 		m_control->update_player_stretch(); | ||||
| @@ -180,7 +190,8 @@ bool PaulstretchpluginAudioProcessor::isBusesLayoutSupported (const BusesLayout& | ||||
|  | ||||
| void PaulstretchpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) | ||||
| { | ||||
|     ScopedNoDenormals noDenormals; | ||||
| 	std::lock_guard<std::mutex> locker(m_mutex); | ||||
| 	ScopedNoDenormals noDenormals; | ||||
|     const int totalNumInputChannels  = getTotalNumInputChannels(); | ||||
|     const int totalNumOutputChannels = getTotalNumOutputChannels(); | ||||
|  | ||||
| @@ -245,6 +256,7 @@ void PaulstretchpluginAudioProcessor::setStateInformation (const void* data, int | ||||
|  | ||||
| void PaulstretchpluginAudioProcessor::setRecordingEnabled(bool b) | ||||
| { | ||||
| 	std::lock_guard<std::mutex> locker(m_mutex); | ||||
| 	if (b == true) | ||||
| 	{ | ||||
| 		m_is_recording = true; | ||||
| @@ -272,10 +284,11 @@ void PaulstretchpluginAudioProcessor::finishRecording(int lenrecording) | ||||
| { | ||||
| 	m_is_recording = false; | ||||
| 	m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer, getSampleRate(), lenrecording); | ||||
| 	m_control->getStretchAudioSource()->setPlayRange({ *getFloatParameter(5),*getFloatParameter(6) }, true); | ||||
| 	auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(getActiveEditor()); | ||||
| 	if (ed) | ||||
| 	{ | ||||
| 		ed->setAudioBuffer(&m_recbuffer, getSampleRate(), m_rec_pos); | ||||
| 		ed->setAudioBuffer(&m_recbuffer, getSampleRate(), lenrecording); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -74,7 +74,7 @@ private: | ||||
| 	int m_rec_pos = 0; | ||||
| 	void finishRecording(int lenrecorded); | ||||
| 	bool m_using_memory_buffer = true; | ||||
| 	 | ||||
| 	std::mutex m_mutex; | ||||
| 	//============================================================================== | ||||
|     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PaulstretchpluginAudioProcessor) | ||||
| }; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
|  | ||||
| <JUCERPROJECT id="fn1Rg8" name="paulstretchplugin" displaySplashScreen="0" | ||||
|               reportAppUsage="1" splashScreenColour="Dark" projectType="audioplug" | ||||
|               reportAppUsage="0" splashScreenColour="Dark" projectType="audioplug" | ||||
|               version="1.0.0" bundleIdentifier="com.yourcompany.paulstretchplugin" | ||||
|               includeBinaryInAppConfig="1" cppLanguageStandard="latest" companyCopyright="" | ||||
|               buildVST="1" buildVST3="0" buildAU="1" buildAUv3="0" buildRTAS="0" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 xenakios
					xenakios