示例#1
0
void Processor::clearConvolvers()
{
  {
    juce::ScopedLock convolverLock(_convolverMutex);
    _reverse = false;
    _predelayMs = 0.0;
    _stretch = 1.0;
    _irBegin = 0.0;
    _irEnd = 1.0;
    _attackLength = 0.0;
    _attackShape = 0.0;
    _decayShape = 0.0;
  }

  setParameterNotifyingHost(Parameters::EqLowCutFreq, Parameters::EqLowCutFreq.getDefaultValue());
  setParameterNotifyingHost(Parameters::EqLowShelfFreq, Parameters::EqLowShelfFreq.getDefaultValue());
  setParameterNotifyingHost(Parameters::EqLowShelfDecibels, Parameters::EqLowShelfDecibels.getDefaultValue());
  setParameterNotifyingHost(Parameters::EqHighCutFreq, Parameters::EqHighCutFreq.getDefaultValue());
  setParameterNotifyingHost(Parameters::EqHighShelfFreq, Parameters::EqHighShelfFreq.getDefaultValue());
  setParameterNotifyingHost(Parameters::EqHighShelfDecibels, Parameters::EqHighShelfDecibels.getDefaultValue());
  setParameterNotifyingHost(Parameters::StereoWidth, Parameters::StereoWidth.getDefaultValue());

  for (size_t i=0; i<_agents.size(); ++i)
  {
    _agents[i]->clear();
  }

  notifyAboutChange();
  updateConvolvers();
}
示例#2
0
//==============================================================================
void Processor::prepareToPlay(double /*sampleRate*/, int samplesPerBlock)
{
  // Play safe to be clean
  releaseResources();

  // Prepare convolvers
  {
    juce::ScopedLock convolverLock(_convolverMutex);
    _convolverHeadBlockSize = 1;
    while (_convolverHeadBlockSize < static_cast<size_t>(samplesPerBlock))
    {
      _convolverHeadBlockSize *= 2;
    }
    _convolverTailBlockSize = std::max(size_t(8192), 2 * _convolverHeadBlockSize);
  }

  // Prepare convolution buffers
  _wetBuffer.setSize(2, samplesPerBlock);
  _convolutionBuffer.resize(samplesPerBlock);

  // Initialize parameters
  _stereoWidth.initializeWidth(getParameter(Parameters::StereoWidth));

  // Initialize IR agents
  for (size_t i=0; i<_agents.size(); ++i)
  {
    _agents[i]->initialize();
  }

  notifyAboutChange();
  updateConvolvers();
}
示例#3
0
void Processor::setIREnd(double irEnd)
{
  bool changed = false;
  bool irChanged = false;
  {
    juce::ScopedLock convolverLock(_convolverMutex);
    double irEndClamped = std::min(1.0, std::max(_irBegin, irEnd));
    if (::fabs(irEndClamped-irEnd) > 0.0001)
    {
      changed = true;
    }
    if (::fabs(_irEnd-irEndClamped) > 0.0001)
    {
      _irEnd = irEndClamped;
      changed = true;
      irChanged = true;
    }    
  }
  if (changed)
  {
    notifyAboutChange();    
  }
  if (irChanged)
  {
    updateConvolvers();
  }
}
示例#4
0
void IRAgent::setConvolver(Convolver* convolver)
{
  ScopedPointer<Convolver> conv(convolver);
  {
    // Make sure that the convolver mutex is locked as short as
    // possible and that all destruction and deallocation happens
    // outside of the lock because this might block the audio thread
    ScopedLock convolverLock(_convolverMutex);
    if (_convolver != conv)
    {
      _convolver.swapWith(conv);
    }
  }
  conv = nullptr;
}
示例#5
0
double Processor::getMaxFileDuration() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  double maxDuration = 0.0;
  for (auto it=_agents.begin(); it!=_agents.end(); ++it)
  {
    const size_t sampleCount = (*it)->getFileSampleCount();
    const double sampleRate = (*it)->getFileSampleRate();
    const double duration = static_cast<double>(sampleCount) / sampleRate;
    if (duration > maxDuration)
    {
      maxDuration = duration;
    }
  }
  return maxDuration;
}
示例#6
0
void Processor::setPredelayMs(double predelayMs)
{
  bool changed = false;
  {
    juce::ScopedLock convolverLock(_convolverMutex);
    if (_predelayMs != predelayMs)
    {
      _predelayMs = predelayMs;
      changed = true;
    }
  }
  if (changed)
  {
    notifyAboutChange();
    updateConvolvers();
  }
}
示例#7
0
void Processor::setReverse(bool reverse)
{
  bool changed = false;
  {
    juce::ScopedLock convolverLock(_convolverMutex);
    if (_reverse != reverse)
    {
      _reverse = reverse;
      changed = true;
    }
  }
  if (changed)
  {
    notifyAboutChange();
    updateConvolvers();
  }
}
示例#8
0
void Processor::setDecayShape(double shape)
{
  bool changed = false;
  {
    juce::ScopedLock convolverLock(_convolverMutex);
    if (_decayShape != shape)
    {
      _decayShape = shape;
      changed = true;
    }
  }
  if (changed)
  {
    notifyAboutChange();
    updateConvolvers();
  }
}
示例#9
0
void Processor::setStretch(double stretch)
{
  bool changed = false;
  {
    juce::ScopedLock convolverLock(_convolverMutex);
    if (::fabs(_stretch-stretch) > 0.000001)
    {
      _stretch = stretch;
      changed = true;
    }
  }
  if (changed)
  {
    notifyAboutChange();
    updateConvolvers();
  }
}
示例#10
0
void Processor::setAttackLength(double length)
{
  bool changed = false;
  length = std::max(0.0, std::min(1.0, length));
  {
    juce::ScopedLock convolverLock(_convolverMutex);
    if (_attackLength != length)
    {
      _attackLength = length;
      changed = true;
    }
  }
  if (changed)
  {
    notifyAboutChange();
    updateConvolvers();
  }
}
示例#11
0
void IRAgent::resetIR(const FloatBuffer::Ptr& irBuffer, Convolver* convolver)
{
  {
    ScopedLock lock(_mutex);
    _irBuffer = irBuffer;
  }

  {
    ScopedPointer<Convolver> conv(convolver);
    {
      // Make sure that the convolver mutex is locked as short as
      // possible and that all destruction and deallocation happens
      // outside of the lock because this might block the audio thread
      ScopedLock convolverLock(_convolverMutex);
      if (_convolver != conv)
      {
        _convolver.swapWith(conv);
      }
    }
  }

  propagateChange();
}
示例#12
0
size_t Processor::getConvolverTailBlockSize() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  return _convolverTailBlockSize;
}
示例#13
0
double Processor::getPredelayMs() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  return _predelayMs;
}
示例#14
0
void IRAgent::process(const float* input, float* output, size_t len)
{
  const float Epsilon = 0.0001f;
  
  // This is the hopefully one and only rare exception where we need to
  // lock a mutex in the realtime audio thread :-/ (however, the according
  // convolver mutex is locked somewhere else only once for a very short and
  // rare swapping operation, so this shouldn't be a problem, and most operating
  // systems internally try spinning before performing an expensive context switch,
  // so we will never give up the context here probably).
  juce::ScopedLock convolverLock(_convolverMutex);
  
  if (_convolver && (_fadeFactor > Epsilon || ::fabs(_fadeIncrement) > Epsilon))
  {
    _convolver->process(input, output, len);        
    if (::fabs(_fadeIncrement) > Epsilon || _fadeFactor < (1.0-Epsilon))
    {
      for (size_t i=0; i<len; ++i)
      {
        _fadeFactor = std::max(0.0f, std::min(1.0f, _fadeFactor+_fadeIncrement));
        output[i] *= _fadeFactor;
      }
      if (_fadeFactor < Epsilon || _fadeFactor > (1.0-Epsilon))
      {
        _fadeIncrement = 0.0;
      }
    }
  }
  else
  {
    ::memset(output, 0, len * sizeof(float));
    _fadeFactor = 0.0;
    _fadeIncrement = 0.0;
  }
  
  // EQ low
  const int eqLowType = _processor.getParameter(Parameters::EqLowType);
  if (eqLowType == Parameters::Cut)
  {    
    const float eqLowCutFreq = _processor.getParameter(Parameters::EqLowCutFreq);
    if (::fabs(eqLowCutFreq-Parameters::EqLowCutFreq.getMinValue()) > 0.0001f)
    {
      _eqLo.setType(CookbookEq::HiPass2);
      _eqLo.setFreq(eqLowCutFreq);
      _eqLo.filterOut(output, len);
    }
  }
  else if (eqLowType == Parameters::Shelf)
  {
    const float eqLowShelfDecibels = _processor.getParameter(Parameters::EqLowShelfDecibels);
    if (::fabs(eqLowShelfDecibels-0.0f) > 0.0001f)
    {
      _eqLo.setType(CookbookEq::LoShelf);
      _eqLo.setFreq(_processor.getParameter(Parameters::EqLowShelfFreq));
      _eqLo.setGain(eqLowShelfDecibels);
      _eqLo.filterOut(output, len);
    }
  }
  
  // EQ high
  const int eqHighType = _processor.getParameter(Parameters::EqHighType);
  if (eqHighType == Parameters::Cut)
  {
    const float eqHighCutFreq = _processor.getParameter(Parameters::EqHighCutFreq);
    if (::fabs(eqHighCutFreq-Parameters::EqHighCutFreq.getMaxValue()) > 0.0001f)
    {
      _eqHi.setType(CookbookEq::LoPass2);
      _eqHi.setFreq(eqHighCutFreq);
      _eqHi.filterOut(output, len);
    }
  }
  else if (eqHighType == Parameters::Shelf)
  {
    const float eqHighShelfDecibels = _processor.getParameter(Parameters::EqHighShelfDecibels);
    if (::fabs(eqHighShelfDecibels-0.0f) > 0.0001f)
    {
      _eqHi.setType(CookbookEq::HiShelf);
      _eqHi.setFreq(_processor.getParameter(Parameters::EqHighShelfFreq));
      _eqHi.setGain(eqHighShelfDecibels);
      _eqHi.filterOut(output, len);
    }
  }
}
示例#15
0
double Processor::getIREnd() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  return _irEnd;
}
示例#16
0
double Processor::getIRBegin() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  return _irBegin;
}
示例#17
0
double Processor::getDecayShape() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  return _decayShape;
}
示例#18
0
double Processor::getStretch() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  return _stretch;
}
示例#19
0
double Processor::getAttackShape() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  return _attackShape;
}
示例#20
0
bool Processor::getReverse() const
{
  juce::ScopedLock convolverLock(_convolverMutex);
  return _reverse;
}