You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

375 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file was auto-generated!
  4. It contains the basic framework code for a JUCE plugin processor.
  5. ==============================================================================
  6. */
  7. #include "PluginProcessor.h"
  8. #include "PluginEditor.h"
  9. #undef min
  10. #undef max
  11. template<typename F>
  12. void callGUI(AudioProcessor* ap, F&& f, bool async)
  13. {
  14. auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(ap->getActiveEditor());
  15. if (ed)
  16. {
  17. if (async == false)
  18. f(ed);
  19. else
  20. MessageManager::callAsync([ed,f]() { f(ed); });
  21. }
  22. }
  23. //==============================================================================
  24. PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor()
  25. #ifndef JucePlugin_PreferredChannelConfigurations
  26. : AudioProcessor (BusesProperties()
  27. #if ! JucePlugin_IsMidiEffect
  28. #if ! JucePlugin_IsSynth
  29. .withInput ("Input", AudioChannelSet::stereo(), true)
  30. #endif
  31. .withOutput ("Output", AudioChannelSet::stereo(), true)
  32. #endif
  33. )
  34. #endif
  35. {
  36. m_recbuffer.setSize(2, 44100);
  37. m_recbuffer.clear();
  38. m_afm = std::make_unique<AudioFormatManager>();
  39. m_afm->registerBasicFormats();
  40. m_control = std::make_unique<Control>(m_afm.get());
  41. m_control->setPreBufferAmount(2);
  42. m_control->ppar.pitch_shift.enabled = true;
  43. m_control->ppar.freq_shift.enabled = true;
  44. m_control->setOnsetDetection(0.0);
  45. m_control->getStretchAudioSource()->setLoopingEnabled(true);
  46. addParameter(new AudioParameterFloat("mainvolume0", "Main volume", -24.0f, 12.0f, -3.0f));
  47. addParameter(new AudioParameterFloat("stretchamount0", "Stretch amount", 0.1f, 128.0f, 1.0f));
  48. addParameter(new AudioParameterFloat("fftsize0", "FFT size", 0.0f, 1.0f, 0.7f));
  49. addParameter(new AudioParameterFloat("pitchshift0", "Pitch shift", -24.0f, 24.0f, 0.0f));
  50. addParameter(new AudioParameterFloat("freqshift0", "Frequency shift", -1000.0f, 1000.0f, 0.0f));
  51. addParameter(new AudioParameterFloat("playrange_start0", "Sound start", 0.0f, 1.0f, 0.0f));
  52. addParameter(new AudioParameterFloat("playrange_end0", "Sound end", 0.0f, 1.0f, 1.0f));
  53. }
  54. PaulstretchpluginAudioProcessor::~PaulstretchpluginAudioProcessor()
  55. {
  56. m_control->stopplay();
  57. }
  58. //==============================================================================
  59. const String PaulstretchpluginAudioProcessor::getName() const
  60. {
  61. return JucePlugin_Name;
  62. }
  63. bool PaulstretchpluginAudioProcessor::acceptsMidi() const
  64. {
  65. #if JucePlugin_WantsMidiInput
  66. return true;
  67. #else
  68. return false;
  69. #endif
  70. }
  71. bool PaulstretchpluginAudioProcessor::producesMidi() const
  72. {
  73. #if JucePlugin_ProducesMidiOutput
  74. return true;
  75. #else
  76. return false;
  77. #endif
  78. }
  79. bool PaulstretchpluginAudioProcessor::isMidiEffect() const
  80. {
  81. #if JucePlugin_IsMidiEffect
  82. return true;
  83. #else
  84. return false;
  85. #endif
  86. }
  87. double PaulstretchpluginAudioProcessor::getTailLengthSeconds() const
  88. {
  89. return 0.0;
  90. }
  91. int PaulstretchpluginAudioProcessor::getNumPrograms()
  92. {
  93. return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs,
  94. // so this should be at least 1, even if you're not really implementing programs.
  95. }
  96. int PaulstretchpluginAudioProcessor::getCurrentProgram()
  97. {
  98. return 0;
  99. }
  100. void PaulstretchpluginAudioProcessor::setCurrentProgram (int index)
  101. {
  102. }
  103. const String PaulstretchpluginAudioProcessor::getProgramName (int index)
  104. {
  105. return {};
  106. }
  107. void PaulstretchpluginAudioProcessor::changeProgramName (int index, const String& newName)
  108. {
  109. }
  110. //==============================================================================
  111. void PaulstretchpluginAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
  112. {
  113. if (getNumOutputChannels() != m_cur_num_out_chans)
  114. m_ready_to_play = false;
  115. if (m_using_memory_buffer == true)
  116. {
  117. int len = jlimit(100,m_recbuffer.getNumSamples(), m_rec_pos);
  118. m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer,
  119. getSampleRate(),
  120. len);
  121. callGUI(this,[this,len](auto ed) { ed->setAudioBuffer(&m_recbuffer, getSampleRate(), len); },false);
  122. }
  123. if (m_ready_to_play == false)
  124. {
  125. m_control->setFFTSize(0.7);
  126. m_control->update_player_stretch();
  127. m_control->update_process_parameters();
  128. String err;
  129. m_control->startplay(false, true,
  130. { *getFloatParameter(5),*getFloatParameter(6) },
  131. 2, err);
  132. m_cur_num_out_chans = getNumOutputChannels();
  133. m_ready_to_play = true;
  134. }
  135. }
  136. void PaulstretchpluginAudioProcessor::releaseResources()
  137. {
  138. //m_control->stopplay();
  139. //m_ready_to_play = false;
  140. }
  141. #ifndef JucePlugin_PreferredChannelConfigurations
  142. bool PaulstretchpluginAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
  143. {
  144. #if JucePlugin_IsMidiEffect
  145. ignoreUnused (layouts);
  146. return true;
  147. #else
  148. // This is the place where you check if the layout is supported.
  149. // In this template code we only support mono or stereo.
  150. if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
  151. && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
  152. return false;
  153. // This checks if the input layout matches the output layout
  154. #if ! JucePlugin_IsSynth
  155. if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
  156. return false;
  157. #endif
  158. return true;
  159. #endif
  160. }
  161. #endif
  162. void copyAudioBufferWrappingPosition(const AudioBuffer<float>& src, AudioBuffer<float>& dest, int destbufpos, int maxdestpos)
  163. {
  164. for (int i = 0; i < dest.getNumChannels(); ++i)
  165. {
  166. int channel_to_copy = i % src.getNumChannels();
  167. if (destbufpos + src.getNumSamples() > maxdestpos)
  168. {
  169. int wrappos = (destbufpos + src.getNumSamples()) % maxdestpos;
  170. int partial_len = src.getNumSamples() - wrappos;
  171. dest.copyFrom(channel_to_copy, destbufpos, src, channel_to_copy, 0, partial_len);
  172. dest.copyFrom(channel_to_copy, partial_len, src, channel_to_copy, 0, wrappos);
  173. }
  174. else
  175. {
  176. dest.copyFrom(channel_to_copy, destbufpos, src, channel_to_copy, 0, src.getNumSamples());
  177. }
  178. }
  179. }
  180. void PaulstretchpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
  181. {
  182. std::lock_guard<std::mutex> locker(m_mutex);
  183. ScopedNoDenormals noDenormals;
  184. const int totalNumInputChannels = getTotalNumInputChannels();
  185. const int totalNumOutputChannels = getTotalNumOutputChannels();
  186. for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
  187. buffer.clear (i, 0, buffer.getNumSamples());
  188. if (m_ready_to_play == false)
  189. return;
  190. if (m_is_recording == true)
  191. {
  192. int recbuflenframes = m_max_reclen * getSampleRate();
  193. copyAudioBufferWrappingPosition(buffer, m_recbuffer, m_rec_pos, recbuflenframes);
  194. callGUI(this,[this, &buffer](PaulstretchpluginAudioProcessorEditor*ed)
  195. {
  196. ed->addAudioBlock(buffer, getSampleRate(), m_rec_pos);
  197. }, false);
  198. m_rec_pos = (m_rec_pos + buffer.getNumSamples()) % recbuflenframes;
  199. return;
  200. }
  201. /*
  202. for (int i=0;i<buffer.getNumSamples();++i)
  203. {
  204. buffer.setSample(0, i, 0.1*sin(2*3.141592/44100*m_phase*440));
  205. buffer.setSample(1, i, 0.1*sin(2*3.141592/44100*m_phase*440));
  206. m_phase+=1.0;
  207. }
  208. return;
  209. */
  210. m_control->getStretchAudioSource()->val_MainVolume = (float)*getFloatParameter(0);
  211. m_control->getStretchAudioSource()->setRate(*getFloatParameter(1));
  212. m_control->getStretchAudioSource()->val_XFadeLen = 0.1;
  213. //m_control->setFFTSize(*getFloatParameter(2));
  214. m_control->ppar.pitch_shift.cents = *getFloatParameter(3) * 100.0;
  215. m_control->ppar.freq_shift.Hz = *getFloatParameter(4);
  216. double t0 = *getFloatParameter(5);
  217. double t1 = *getFloatParameter(6);
  218. if (t0 > t1)
  219. std::swap(t0, t1);
  220. if (t1 - t0 < 0.001)
  221. t1 = t0 + 0.001;
  222. m_control->getStretchAudioSource()->setPlayRange({ t0,t1 }, true);
  223. m_control->update_process_parameters();
  224. m_control->processAudio(buffer);
  225. }
  226. //==============================================================================
  227. bool PaulstretchpluginAudioProcessor::hasEditor() const
  228. {
  229. return true; // (change this to false if you choose to not supply an editor)
  230. }
  231. AudioProcessorEditor* PaulstretchpluginAudioProcessor::createEditor()
  232. {
  233. return new PaulstretchpluginAudioProcessorEditor (*this);
  234. }
  235. //==============================================================================
  236. void PaulstretchpluginAudioProcessor::getStateInformation (MemoryBlock& destData)
  237. {
  238. ValueTree paramtree("paulstretch3pluginstate");
  239. for (int i=0;i<getNumParameters();++i)
  240. {
  241. auto par = getFloatParameter(i);
  242. paramtree.setProperty(par->paramID, (double)*par, nullptr);
  243. }
  244. if (m_current_file != File())
  245. {
  246. paramtree.setProperty("importedfile", m_current_file.getFullPathName(), nullptr);
  247. }
  248. MemoryOutputStream stream(destData,true);
  249. paramtree.writeToStream(stream);
  250. }
  251. void PaulstretchpluginAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
  252. {
  253. return;
  254. ValueTree tree = ValueTree::readFromData(data, sizeInBytes);
  255. if (tree.isValid())
  256. {
  257. for (int i = 0; i<getNumParameters(); ++i)
  258. {
  259. auto par = getFloatParameter(i);
  260. double parval = tree.getProperty(par->paramID, (double)*par);
  261. *par = parval;
  262. }
  263. String fn = tree.getProperty("importedfile");
  264. if (fn.isEmpty() == false)
  265. {
  266. m_using_memory_buffer = false;
  267. File f(fn);
  268. setAudioFile(f);
  269. Timer::callAfterDelay(500, [this,f]()
  270. {
  271. callGUI(this,[f,this](PaulstretchpluginAudioProcessorEditor* ed)
  272. {
  273. ed->setAudioFile(f);
  274. ed->m_wavecomponent.setTimeSelection({ *getFloatParameter(5),*getFloatParameter(6) });
  275. }, false);
  276. });
  277. }
  278. }
  279. }
  280. void PaulstretchpluginAudioProcessor::setRecordingEnabled(bool b)
  281. {
  282. std::lock_guard<std::mutex> locker(m_mutex);
  283. int lenbufframes = getSampleRate()*m_max_reclen;
  284. if (b == true)
  285. {
  286. m_using_memory_buffer = true;
  287. m_current_file = File();
  288. m_recbuffer.setSize(2, m_max_reclen*getSampleRate()+4096);
  289. m_recbuffer.clear();
  290. m_rec_pos = 0;
  291. callGUI(this,[this,lenbufframes](PaulstretchpluginAudioProcessorEditor* ed)
  292. {
  293. ed->beginAddingAudioBlocks(2, getSampleRate(), lenbufframes);
  294. },false);
  295. m_is_recording = true;
  296. }
  297. else
  298. {
  299. if (m_is_recording == true)
  300. {
  301. finishRecording(lenbufframes);
  302. }
  303. }
  304. }
  305. double PaulstretchpluginAudioProcessor::getRecordingPositionPercent()
  306. {
  307. if (m_is_recording==false)
  308. return 0.0;
  309. return 1.0 / m_recbuffer.getNumSamples()*m_rec_pos;
  310. }
  311. String PaulstretchpluginAudioProcessor::setAudioFile(File f)
  312. {
  313. std::lock_guard<std::mutex> locker(m_mutex);
  314. m_control->set_input_file(f, [this,f](String)
  315. {
  316. });
  317. m_current_file = f;
  318. m_using_memory_buffer = false;
  319. return String();
  320. }
  321. void PaulstretchpluginAudioProcessor::finishRecording(int lenrecording)
  322. {
  323. m_is_recording = false;
  324. m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer, getSampleRate(), lenrecording);
  325. m_control->getStretchAudioSource()->setPlayRange({ *getFloatParameter(5),*getFloatParameter(6) }, true);
  326. auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(getActiveEditor());
  327. if (ed)
  328. {
  329. //ed->setAudioBuffer(&m_recbuffer, getSampleRate(), lenrecording);
  330. }
  331. }
  332. //==============================================================================
  333. // This creates new instances of the plugin..
  334. AudioProcessor* JUCE_CALLTYPE createPluginFilter()
  335. {
  336. return new PaulstretchpluginAudioProcessor();
  337. }