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.

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