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.

364 lines
10KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCETICE project - Copyright 2009 by Lucio Asnaghi.
  4. JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions"
  5. Copyright 2007 by Julian Storer.
  6. ------------------------------------------------------------------------------
  7. JUCE and JUCETICE can be redistributed and/or modified under the terms of
  8. the GNU General Public License, as published by the Free Software Foundation;
  9. either version 2 of the License, or (at your option) any later version.
  10. JUCE and JUCETICE are distributed in the hope that they will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to
  16. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  17. Boston, MA 02111-1307 USA
  18. ==============================================================================
  19. */
  20. BEGIN_JUCE_NAMESPACE
  21. #include "jucetice_AudioPlugin.h"
  22. #include "jucetice_AudioParameter.h"
  23. #include "jucetice_MathConstants.h"
  24. //==============================================================================
  25. AudioParameter::AudioParameter ()
  26. : index (0),
  27. partNumber (0),
  28. minValue (0.0f),
  29. maxValue (1.0f),
  30. baseValue (0.0f),
  31. currentValue (0.0f),
  32. #if AudioParameterUseMapping
  33. transferFunction (AudioParameter::RangeLinear),
  34. transferData (0.0f),
  35. #endif
  36. plugin (0)
  37. {
  38. zeromem (paramName, AudioParameterMaxNameLength * sizeof (char));
  39. zeromem (paramLabel, AudioParameterMaxLabelLength * sizeof (char));
  40. getValueFunction = MakeDelegate (this, &AudioParameter::defaultGetFunction);
  41. setValueFunction = MakeDelegate (this, &AudioParameter::defaultSetFunction);
  42. getTextFunction = MakeDelegate (this, &AudioParameter::defaultGetTextFunction);
  43. }
  44. AudioParameter::~AudioParameter ()
  45. {
  46. removeAllListeners ();
  47. }
  48. //==============================================================================
  49. AudioParameter& AudioParameter::id (const int newIndex)
  50. {
  51. index = newIndex;
  52. return *this;
  53. }
  54. AudioParameter& AudioParameter::part (const int newPartNumber)
  55. {
  56. partNumber = newPartNumber;
  57. return *this;
  58. }
  59. AudioParameter& AudioParameter::name (const String& newName)
  60. {
  61. #if JUCE_WIN32
  62. _snprintf (paramName, AudioParameterMaxNameLength, "%s", newName.toRawUTF8());
  63. #else
  64. snprintf (paramName, AudioParameterMaxNameLength, "%s", newName.toRawUTF8());
  65. #endif
  66. return *this;
  67. }
  68. AudioParameter& AudioParameter::unit (const String& newLabel)
  69. {
  70. #if JUCE_WIN32
  71. _snprintf (paramLabel, AudioParameterMaxLabelLength, "%s", newLabel.toRawUTF8());
  72. #else
  73. snprintf (paramLabel, AudioParameterMaxLabelLength, "%s", newLabel.toRawUTF8());
  74. #endif
  75. return *this;
  76. }
  77. #if AudioParameterUseMapping
  78. AudioParameter& AudioParameter::mapping (TransferFunction newFunction,
  79. const float additionalData)
  80. {
  81. transferFunction = newFunction;
  82. transferData = additionalData;
  83. return *this;
  84. }
  85. #endif
  86. AudioParameter& AudioParameter::range (const float min, const float max)
  87. {
  88. minValue = min;
  89. maxValue = max;
  90. return *this;
  91. }
  92. AudioParameter& AudioParameter::base (const float newBaseValue)
  93. {
  94. baseValue = newBaseValue;
  95. return *this;
  96. }
  97. AudioParameter& AudioParameter::set (SetValueDelegate newSetFunction)
  98. {
  99. setValueFunction = newSetFunction;
  100. return *this;
  101. }
  102. AudioParameter& AudioParameter::get (GetValueDelegate newGetFunction)
  103. {
  104. getValueFunction = newGetFunction;
  105. return *this;
  106. }
  107. AudioParameter& AudioParameter::text (GetTextDelegate newGetTextFunction)
  108. {
  109. getTextFunction = newGetTextFunction;
  110. return *this;
  111. }
  112. //==============================================================================
  113. float AudioParameter::getValue () const
  114. {
  115. #if AudioParameterUseMapping
  116. switch (transferFunction) {
  117. case RangeLinear:
  118. default:
  119. return (getValueFunction (partNumber) - minValue) / (maxValue - minValue);
  120. case RangeSquared:
  121. return sqrtf ((getValueFunction (partNumber) - minValue) / (maxValue - minValue));
  122. case RangeCubed:
  123. return powf ((getValueFunction (partNumber) - minValue) / (maxValue - minValue), 1.0f / 3.0f);
  124. case RangePow:
  125. return powf ((getValueFunction (partNumber) - minValue) / (maxValue - minValue), 1.0f / transferData);
  126. case RangeExp:
  127. return logf (1.0f - minValue + getValueFunction (partNumber)) / logf (1.0f - minValue + maxValue);
  128. case Stepped:
  129. return getValueFunction (partNumber) / (float) (transferData - 1);
  130. case Frequency:
  131. return (logf (getValueFunction (partNumber) / 20.0f) / logf (2.0f))
  132. / 9.965784284662088765571752446703612804412841796875f;
  133. }
  134. #else
  135. return (getValueFunction (partNumber) - minValue) / (maxValue - minValue);
  136. #endif
  137. }
  138. void AudioParameter::setValue (const float newValue)
  139. {
  140. #if AudioParameterUseMapping
  141. switch (transferFunction) {
  142. case RangeLinear:
  143. default:
  144. setValueFunction (partNumber, minValue + newValue * (maxValue - minValue));
  145. case RangeSquared:
  146. setValueFunction (partNumber, minValue + (newValue * newValue) * (maxValue - minValue));
  147. case RangeCubed:
  148. setValueFunction (partNumber, minValue + (newValue * newValue * newValue) * (maxValue - minValue));
  149. case RangePow:
  150. setValueFunction (partNumber, minValue + powf (newValue, transferData) * (maxValue - minValue));
  151. case RangeExp:
  152. setValueFunction (partNumber, minValue + expf (logf (maxValue - minValue + 1.0f) * newValue) - 1.0f);
  153. case Stepped:
  154. setValueFunction (partNumber, (float) roundFloatToInt (newValue * (transferData - 0.01f)));
  155. case Frequency:
  156. setValueFunction (partNumber, 20.0f * powf (2.0f, newValue * 9.965784284662088765571752446703612804412841796875f));
  157. }
  158. #else
  159. setValueFunction (partNumber, minValue + newValue * (maxValue - minValue));
  160. #endif
  161. }
  162. //==============================================================================
  163. void AudioParameter::addListener (AudioParameterListener* const listener)
  164. {
  165. listeners.addIfNotAlreadyThere (listener);
  166. if (plugin)
  167. {
  168. const ScopedLock sl (plugin->getParameterLock());
  169. listener->attachedToParameter (this, index);
  170. }
  171. else
  172. {
  173. listener->attachedToParameter (this, index);
  174. }
  175. }
  176. void AudioParameter::removeListener (AudioParameterListener* const listener)
  177. {
  178. if (plugin)
  179. {
  180. const ScopedLock sl (plugin->getParameterLock());
  181. listener->detachedFromParameter (this, index);
  182. }
  183. else
  184. {
  185. listener->detachedFromParameter (this, index);
  186. }
  187. int index = listeners.indexOf (listener);
  188. if (index >= 0)
  189. listeners.remove (index);
  190. }
  191. void AudioParameter::removeAllListeners ()
  192. {
  193. if (plugin)
  194. {
  195. const ScopedLock sl (plugin->getParameterLock());
  196. for (int i = listeners.size (); --i >= 0;)
  197. listeners.getUnchecked (i)->detachedFromParameter (this, index);
  198. }
  199. else
  200. {
  201. for (int i = listeners.size (); --i >= 0;)
  202. listeners.getUnchecked (i)->detachedFromParameter (this, index);
  203. }
  204. listeners.clear ();
  205. }
  206. //==============================================================================
  207. void AudioParameter::setAudioPlugin (AudioPlugin* newPlugin, const int newIndex)
  208. {
  209. plugin = newPlugin;
  210. index = newIndex;
  211. }
  212. //==============================================================================
  213. void AudioParameter::handleAsyncUpdate ()
  214. {
  215. const ScopedLock sl (plugin->getParameterLock());
  216. for (int i = listeners.size (); --i >= 0;)
  217. listeners.getUnchecked (i)->parameterChanged (this, index);
  218. }
  219. //==============================================================================
  220. bool AudioParameter::handleMidiMessage (const MidiMessage& message)
  221. {
  222. // TODO - handle parameters changes by midi notes and not only cc.
  223. plugin->setParameter (index, message.getControllerValue () * float_MidiScaler);
  224. return true;
  225. }
  226. //==============================================================================
  227. float AudioParameter::defaultGetFunction (int partNumber)
  228. {
  229. return currentValue;
  230. }
  231. void AudioParameter::defaultSetFunction (int partNumber, float value)
  232. {
  233. currentValue = value;
  234. }
  235. const String AudioParameter::defaultGetTextFunction (int partNumber, float value)
  236. {
  237. int decimalNumber = 0;
  238. float absValue = fabsf (value);
  239. if (absValue < 10) decimalNumber = 4;
  240. else if (absValue < 100) decimalNumber = 3;
  241. else if (absValue < 1000) decimalNumber = 2;
  242. else if (absValue < 10000) decimalNumber = 1;
  243. else if (absValue < 100000) decimalNumber = 0;
  244. return String (value, jmin (jmax (decimalNumber, 0), 4))
  245. + " "
  246. + (String)paramLabel;
  247. }
  248. //==============================================================================
  249. juce_ImplementSingleton (AudioParameterThread);
  250. AudioParameterThread::AudioParameterThread ()
  251. : Thread ("AudioParameterThread"),
  252. parameterChanges (8192),
  253. changeChecksPerSecond (50)
  254. {
  255. startThread (6);
  256. }
  257. AudioParameterThread::~AudioParameterThread ()
  258. {
  259. stopThread (5000);
  260. }
  261. void AudioParameterThread::sendParameterChange (AudioParameter* parameter)
  262. {
  263. parameterChanges.put (parameter);
  264. notify ();
  265. }
  266. int AudioParameterThread::getParametersChangeChecksPerSecond () const
  267. {
  268. return changeChecksPerSecond;
  269. }
  270. void AudioParameterThread::setParametersChangeChecksPerSecond (const int howManyCheckPerSecond)
  271. {
  272. changeChecksPerSecond = jmax (1, jmin (100, howManyCheckPerSecond));
  273. }
  274. void AudioParameterThread::run()
  275. {
  276. AudioParameter* parameter;
  277. while (! threadShouldExit ())
  278. {
  279. int32 currentWaitTime = Time::getMillisecondCounter ();
  280. while (! parameterChanges.isEmpty ())
  281. {
  282. parameter = (AudioParameter*) parameterChanges.get ();
  283. if (parameter)
  284. parameter->triggerAsyncUpdate ();
  285. }
  286. currentWaitTime = 1000 / changeChecksPerSecond
  287. - (Time::getMillisecondCounter () - currentWaitTime);
  288. // wait (jmax (1, jmin (1000, currentWaitTime)));
  289. Thread::sleep (jmax (1, jmin (1000, currentWaitTime)));
  290. }
  291. }
  292. END_JUCE_NAMESPACE