Add Chromium-only Blender WebEngine parity work
This commit is contained in:
73
blender-5.2.0/extern/audaspace/src/fx/ADSR.cpp
vendored
Normal file
73
blender-5.2.0/extern/audaspace/src/fx/ADSR.cpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/ADSR.h"
|
||||
#include "fx/ADSRReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
ADSR::ADSR(std::shared_ptr<ISound> sound, float attack, float decay, float sustain, float release) :
|
||||
Effect(sound),
|
||||
m_attack(attack), m_decay(decay), m_sustain(sustain), m_release(release)
|
||||
{
|
||||
}
|
||||
|
||||
float ADSR::getAttack() const
|
||||
{
|
||||
return m_attack;
|
||||
}
|
||||
|
||||
void ADSR::setAttack(float attack)
|
||||
{
|
||||
m_attack = attack;
|
||||
}
|
||||
|
||||
float ADSR::getDecay() const
|
||||
{
|
||||
return m_decay;
|
||||
}
|
||||
|
||||
void ADSR::setDecay(float decay)
|
||||
{
|
||||
m_decay = decay;
|
||||
}
|
||||
|
||||
float ADSR::getSustain() const
|
||||
{
|
||||
return m_sustain;
|
||||
}
|
||||
|
||||
void ADSR::setSustain(float sustain)
|
||||
{
|
||||
m_sustain = sustain;
|
||||
}
|
||||
|
||||
float ADSR::getRelease() const
|
||||
{
|
||||
return m_release;
|
||||
}
|
||||
|
||||
void ADSR::setRelease(float release)
|
||||
{
|
||||
m_release = release;
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> ADSR::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new ADSRReader(getReader(), m_attack, m_decay, m_sustain, m_release));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
115
blender-5.2.0/extern/audaspace/src/fx/ADSRReader.cpp
vendored
Normal file
115
blender-5.2.0/extern/audaspace/src/fx/ADSRReader.cpp
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/ADSRReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
ADSRReader::ADSRReader(std::shared_ptr<IReader> reader, float attack, float decay, float sustain, float release) :
|
||||
EffectReader(reader),
|
||||
m_attack(attack), m_decay(decay), m_sustain(sustain), m_release(release)
|
||||
{
|
||||
nextState(ADSR_STATE_ATTACK);
|
||||
}
|
||||
|
||||
ADSRReader::~ADSRReader()
|
||||
{
|
||||
}
|
||||
|
||||
void ADSRReader::nextState(ADSRState state)
|
||||
{
|
||||
m_state = state;
|
||||
|
||||
switch(m_state)
|
||||
{
|
||||
case ADSR_STATE_ATTACK:
|
||||
m_level = 0;
|
||||
if(m_attack <= 0)
|
||||
{
|
||||
nextState(ADSR_STATE_DECAY);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case ADSR_STATE_DECAY:
|
||||
if(m_decay <= 0)
|
||||
{
|
||||
nextState(ADSR_STATE_SUSTAIN);
|
||||
return;
|
||||
}
|
||||
if(m_level > 1.0)
|
||||
m_level = 1 - (m_level - 1) * m_attack / m_decay * (1 - m_sustain);
|
||||
if(m_level <= m_sustain)
|
||||
nextState(ADSR_STATE_SUSTAIN);
|
||||
break;
|
||||
case ADSR_STATE_SUSTAIN:
|
||||
m_level = m_sustain;
|
||||
break;
|
||||
case ADSR_STATE_RELEASE:
|
||||
if(m_release <= 0)
|
||||
{
|
||||
nextState(ADSR_STATE_INVALID);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case ADSR_STATE_INVALID:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ADSRReader::read(int & length, bool &eos, sample_t* buffer)
|
||||
{
|
||||
Specs specs = m_reader->getSpecs();
|
||||
m_reader->read(length, eos, buffer);
|
||||
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
for(int channel = 0; channel < specs.channels; channel++)
|
||||
{
|
||||
buffer[i * specs.channels + channel] *= m_level;
|
||||
}
|
||||
|
||||
switch(m_state)
|
||||
{
|
||||
case ADSR_STATE_ATTACK:
|
||||
m_level += 1 / m_attack / specs.rate;
|
||||
if(m_level >= 1)
|
||||
nextState(ADSR_STATE_DECAY);
|
||||
break;
|
||||
case ADSR_STATE_DECAY:
|
||||
m_level -= (1 - m_sustain) / m_decay / specs.rate;
|
||||
if(m_level <= m_sustain)
|
||||
nextState(ADSR_STATE_SUSTAIN);
|
||||
break;
|
||||
case ADSR_STATE_SUSTAIN:
|
||||
break;
|
||||
case ADSR_STATE_RELEASE:
|
||||
m_level -= m_sustain / m_release / specs.rate ;
|
||||
if(m_level <= 0)
|
||||
nextState(ADSR_STATE_INVALID);
|
||||
break;
|
||||
case ADSR_STATE_INVALID:
|
||||
length = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ADSRReader::release()
|
||||
{
|
||||
nextState(ADSR_STATE_RELEASE);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
54
blender-5.2.0/extern/audaspace/src/fx/Accumulator.cpp
vendored
Normal file
54
blender-5.2.0/extern/audaspace/src/fx/Accumulator.cpp
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Accumulator.h"
|
||||
#include "fx/CallbackIIRFilterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
sample_t Accumulator::accumulatorFilterAdditive(CallbackIIRFilterReader* reader, void* useless)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
float lastin = reader->x(-1);
|
||||
float out = reader->y(-1) + in - lastin;
|
||||
if(in > lastin)
|
||||
out += in - lastin;
|
||||
return out;
|
||||
}
|
||||
|
||||
sample_t Accumulator::accumulatorFilter(CallbackIIRFilterReader* reader, void* useless)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
float lastin = reader->x(-1);
|
||||
float out = reader->y(-1);
|
||||
if(in > lastin)
|
||||
out += in - lastin;
|
||||
return out;
|
||||
}
|
||||
|
||||
Accumulator::Accumulator(std::shared_ptr<ISound> sound,
|
||||
bool additive) :
|
||||
Effect(sound),
|
||||
m_additive(additive)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Accumulator::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new CallbackIIRFilterReader(getReader(), 2, 2, m_additive ? accumulatorFilterAdditive : accumulatorFilter));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
78
blender-5.2.0/extern/audaspace/src/fx/AnimateableTimeStretchPitchScale.cpp
vendored
Normal file
78
blender-5.2.0/extern/audaspace/src/fx/AnimateableTimeStretchPitchScale.cpp
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2025 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/AnimateableTimeStretchPitchScale.h"
|
||||
|
||||
#include "fx/AnimateableTimeStretchPitchScaleReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
AnimateableTimeStretchPitchScale::AnimateableTimeStretchPitchScale(std::shared_ptr<ISound> sound, float fps, float timeStretch, float pitchScale, StretcherQuality quality,
|
||||
bool preserveFormant) :
|
||||
Effect(sound),
|
||||
m_fps(fps),
|
||||
m_timeStretch(std::make_shared<AnimateableProperty>(1, timeStretch)),
|
||||
m_pitchScale(std::make_shared<AnimateableProperty>(1, pitchScale)),
|
||||
m_quality(quality),
|
||||
m_preserveFormant(preserveFormant)
|
||||
{
|
||||
}
|
||||
|
||||
AnimateableTimeStretchPitchScale::AnimateableTimeStretchPitchScale(std::shared_ptr<ISound> sound, float fps, std::shared_ptr<AnimateableProperty> timeStretch,
|
||||
std::shared_ptr<AnimateableProperty> pitchScale, StretcherQuality quality, bool preserveFormant) :
|
||||
Effect(sound), m_fps(fps), m_timeStretch(timeStretch), m_pitchScale(pitchScale), m_quality(quality), m_preserveFormant(preserveFormant)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> AnimateableTimeStretchPitchScale::createReader()
|
||||
{
|
||||
return std::make_shared<AnimateableTimeStretchPitchScaleReader>(getReader(), m_fps, m_timeStretch, m_pitchScale, m_quality, m_preserveFormant);
|
||||
}
|
||||
|
||||
bool AnimateableTimeStretchPitchScale::getPreserveFormant() const
|
||||
{
|
||||
return m_preserveFormant;
|
||||
}
|
||||
|
||||
StretcherQuality AnimateableTimeStretchPitchScale::getStretcherQuality() const
|
||||
{
|
||||
return m_quality;
|
||||
}
|
||||
|
||||
std::shared_ptr<AnimateableProperty> AnimateableTimeStretchPitchScale::getAnimProperty(AnimateablePropertyType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case AP_TIME_STRETCH:
|
||||
return m_timeStretch;
|
||||
case AP_PITCH_SCALE:
|
||||
return m_pitchScale;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
float AnimateableTimeStretchPitchScale::getFPS() const
|
||||
{
|
||||
return m_fps;
|
||||
}
|
||||
|
||||
void AnimateableTimeStretchPitchScale::setFPS(float fps)
|
||||
{
|
||||
m_fps = fps;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
96
blender-5.2.0/extern/audaspace/src/fx/AnimateableTimeStretchPitchScaleReader.cpp
vendored
Normal file
96
blender-5.2.0/extern/audaspace/src/fx/AnimateableTimeStretchPitchScaleReader.cpp
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2025 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/AnimateableTimeStretchPitchScaleReader.h"
|
||||
|
||||
#include "IReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
AnimateableTimeStretchPitchScaleReader::AnimateableTimeStretchPitchScaleReader(std::shared_ptr<IReader> reader, float fps, std::shared_ptr<AnimateableProperty> timeStretch,
|
||||
std::shared_ptr<AnimateableProperty> pitchScale, StretcherQuality quality, bool preserveFormant) :
|
||||
TimeStretchPitchScaleReader(reader, timeStretch->readSingle(0), pitchScale->readSingle(0), quality, preserveFormant),
|
||||
m_fps(fps),
|
||||
m_timeStretch(timeStretch),
|
||||
m_pitchScale(pitchScale)
|
||||
{
|
||||
}
|
||||
|
||||
void AnimateableTimeStretchPitchScaleReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
int position = getPosition();
|
||||
|
||||
double time = double(position) / double(m_reader->getSpecs().rate);
|
||||
float frame = time * m_fps;
|
||||
|
||||
float timeRatio = m_timeStretch->readSingle(frame);
|
||||
setTimeRatio(timeRatio);
|
||||
float pitchScale = m_pitchScale->readSingle(frame);
|
||||
setPitchScale(pitchScale);
|
||||
TimeStretchPitchScaleReader::read(length, eos, buffer);
|
||||
}
|
||||
|
||||
void AnimateableTimeStretchPitchScaleReader::seek(int position)
|
||||
{
|
||||
const double sampleRate = double(m_reader->getSpecs().rate);
|
||||
const double samplesPerFrame = sampleRate / m_fps;
|
||||
const double frame = double(position) / samplesPerFrame;
|
||||
|
||||
float timeRatio = m_timeStretch->readSingle(frame);
|
||||
setTimeRatio(timeRatio);
|
||||
float pitchScale = m_pitchScale->readSingle(frame);
|
||||
setPitchScale(pitchScale);
|
||||
|
||||
const int totalFrames = static_cast<int>(frame);
|
||||
|
||||
float ratio = 1.0f;
|
||||
|
||||
double inputSamplePos = 0.0;
|
||||
|
||||
const sample_t* animationSamples = m_timeStretch->getBuffer().getBuffer();
|
||||
|
||||
const int bufferFrames = m_timeStretch->getBuffer().getSize() / (sizeof(sample_t) * m_timeStretch->getCount());
|
||||
|
||||
for(int frameIndex = 0; frameIndex < std::min(bufferFrames, totalFrames); frameIndex++)
|
||||
{
|
||||
ratio = std::max(animationSamples[frameIndex], 1.0f / 256.0f);
|
||||
inputSamplePos += samplesPerFrame / ratio;
|
||||
}
|
||||
|
||||
if(totalFrames > bufferFrames)
|
||||
{
|
||||
// The position is past the end of animation buffer and so use the last read ratio
|
||||
// This already includes the fractional frame
|
||||
inputSamplePos += (samplesPerFrame * (frame - bufferFrames)) / ratio;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The position is before the end of the animation buffer and so read one last time for the remaining fractional frame
|
||||
double remainderFrame = frame - totalFrames;
|
||||
|
||||
float remainderRatio = std::max(m_timeStretch->readSingle(frame), 1.0f / 256.0f);
|
||||
|
||||
inputSamplePos += (samplesPerFrame * remainderFrame) / remainderRatio;
|
||||
}
|
||||
|
||||
m_reader->seek(static_cast<int>(inputSamplePos));
|
||||
m_finishedReader = false;
|
||||
m_stretcher->reset();
|
||||
reset();
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
125
blender-5.2.0/extern/audaspace/src/fx/BaseIIRFilterReader.cpp
vendored
Normal file
125
blender-5.2.0/extern/audaspace/src/fx/BaseIIRFilterReader.cpp
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/BaseIIRFilterReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
BaseIIRFilterReader::BaseIIRFilterReader(std::shared_ptr<IReader> reader, int in, int out) :
|
||||
EffectReader(reader),
|
||||
m_specs(reader->getSpecs()),
|
||||
m_xlen(in), m_ylen(out),
|
||||
m_xpos(0), m_ypos(0), m_channel(0)
|
||||
{
|
||||
m_x = new sample_t[m_xlen * m_specs.channels];
|
||||
m_y = new sample_t[m_ylen * m_specs.channels];
|
||||
|
||||
std::memset(m_x, 0, sizeof(sample_t) * m_xlen * m_specs.channels);
|
||||
std::memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels);
|
||||
}
|
||||
|
||||
BaseIIRFilterReader::~BaseIIRFilterReader()
|
||||
{
|
||||
delete[] m_x;
|
||||
delete[] m_y;
|
||||
}
|
||||
|
||||
void BaseIIRFilterReader::setLengths(int in, int out)
|
||||
{
|
||||
if(in != m_xlen)
|
||||
{
|
||||
sample_t* xn = new sample_t[in * m_specs.channels];
|
||||
std::memset(xn, 0, sizeof(sample_t) * in * m_specs.channels);
|
||||
|
||||
for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
|
||||
{
|
||||
for(int i = 1; i <= in && i <= m_xlen; i++)
|
||||
{
|
||||
xn[(in - i) * m_specs.channels + m_channel] = x(-i);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] m_x;
|
||||
m_x = xn;
|
||||
m_xpos = 0;
|
||||
m_xlen = in;
|
||||
}
|
||||
|
||||
if(out != m_ylen)
|
||||
{
|
||||
sample_t* yn = new sample_t[out * m_specs.channels];
|
||||
std::memset(yn, 0, sizeof(sample_t) * out * m_specs.channels);
|
||||
|
||||
for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
|
||||
{
|
||||
for(int i = 1; i <= out && i <= m_ylen; i++)
|
||||
{
|
||||
yn[(out - i) * m_specs.channels + m_channel] = y(-i);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] m_y;
|
||||
m_y = yn;
|
||||
m_ypos = 0;
|
||||
m_ylen = out;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseIIRFilterReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
Specs specs = m_reader->getSpecs();
|
||||
if(specs.channels != m_specs.channels)
|
||||
{
|
||||
m_specs.channels = specs.channels;
|
||||
|
||||
delete[] m_x;
|
||||
delete[] m_y;
|
||||
|
||||
m_x = new sample_t[m_xlen * m_specs.channels];
|
||||
m_y = new sample_t[m_ylen * m_specs.channels];
|
||||
|
||||
std::memset(m_x, 0, sizeof(sample_t) * m_xlen * m_specs.channels);
|
||||
std::memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels);
|
||||
}
|
||||
|
||||
if(specs.rate != m_specs.rate)
|
||||
{
|
||||
m_specs = specs;
|
||||
sampleRateChanged(m_specs.rate);
|
||||
}
|
||||
|
||||
m_reader->read(length, eos, buffer);
|
||||
|
||||
for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
|
||||
{
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
m_x[m_xpos * m_specs.channels + m_channel] = buffer[i * m_specs.channels + m_channel];
|
||||
m_y[m_ypos * m_specs.channels + m_channel] = buffer[i * m_specs.channels + m_channel] = filter();
|
||||
|
||||
m_xpos = m_xlen ? (m_xpos + 1) % m_xlen : 0;
|
||||
m_ypos = m_ylen ? (m_ypos + 1) % m_ylen : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BaseIIRFilterReader::sampleRateChanged(SampleRate rate)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
255
blender-5.2.0/extern/audaspace/src/fx/BinauralReader.cpp
vendored
Normal file
255
blender-5.2.0/extern/audaspace/src/fx/BinauralReader.cpp
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/BinauralReader.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
#define NUM_OUTCHANNELS 2
|
||||
#define NUM_CONVOLVERS 4
|
||||
#define CROSSFADE_SAMPLES 1024
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
BinauralReader::BinauralReader(std::shared_ptr<IReader> reader, std::shared_ptr<HRTF> hrtfs, std::shared_ptr<Source> source, std::shared_ptr<ThreadPool> threadPool, std::shared_ptr<FFTPlan> plan) :
|
||||
m_position(0), m_reader(reader), m_hrtfs(hrtfs), m_source(source), m_N(plan->getSize()), m_transition(false), m_transPos(CROSSFADE_SAMPLES*NUM_OUTCHANNELS), m_eosReader(false), m_eosTail(false), m_threadPool(threadPool)
|
||||
{
|
||||
if(m_hrtfs->isEmpty())
|
||||
AUD_THROW(StateException, "The provided HRTF object is empty");
|
||||
if(m_reader->getSpecs().channels != 1)
|
||||
AUD_THROW(StateException, "The sound must have only one channel");
|
||||
if(m_reader->getSpecs().rate != m_hrtfs->getSpecs().rate)
|
||||
AUD_THROW(StateException, "The sound and the HRTFs must have the same rate");
|
||||
m_M = m_L = m_N / 2;
|
||||
|
||||
m_RealAzimuth = m_Azimuth = m_source->getAzimuth();
|
||||
m_RealElevation = m_Elevation = m_source->getElevation();
|
||||
auto irs = m_hrtfs->getImpulseResponse(m_RealAzimuth, m_RealElevation);
|
||||
for(unsigned int i = 0; i < NUM_CONVOLVERS; i++)
|
||||
if(i%NUM_OUTCHANNELS==0)
|
||||
m_convolvers.push_back(std::unique_ptr<Convolver>(new Convolver(irs.first->getChannel(0), irs.first->getLength(), m_threadPool, plan)));
|
||||
else
|
||||
m_convolvers.push_back(std::unique_ptr<Convolver>(new Convolver(irs.second->getChannel(0), irs.second->getLength(), m_threadPool, plan)));
|
||||
m_futures.resize(NUM_CONVOLVERS);
|
||||
|
||||
m_outBuffer = (sample_t*)std::malloc(m_L*NUM_OUTCHANNELS*sizeof(sample_t));
|
||||
m_eOutBufLen = m_outBufLen = m_outBufferPos = m_L * NUM_OUTCHANNELS;
|
||||
m_inBuffer = (sample_t*)std::malloc(m_L * sizeof(sample_t));
|
||||
for(int i = 0; i < NUM_CONVOLVERS; i++)
|
||||
m_vecOut.push_back((sample_t*)std::calloc(m_L, sizeof(sample_t)));
|
||||
}
|
||||
|
||||
BinauralReader::~BinauralReader()
|
||||
{
|
||||
std::free(m_outBuffer);
|
||||
std::free(m_inBuffer);
|
||||
for(int i = 0; i < m_vecOut.size(); i++)
|
||||
std::free(m_vecOut[i]);
|
||||
}
|
||||
|
||||
bool BinauralReader::isSeekable() const
|
||||
{
|
||||
return m_reader->isSeekable();
|
||||
}
|
||||
|
||||
void BinauralReader::seek(int position)
|
||||
{
|
||||
m_position = position;
|
||||
m_reader->seek(position);
|
||||
for(int i = 0; i < NUM_CONVOLVERS; i++)
|
||||
m_convolvers[i]->reset();
|
||||
m_eosTail = false;
|
||||
m_eosReader = false;
|
||||
m_outBufferPos = m_eOutBufLen = m_outBufLen;
|
||||
m_transition = false;
|
||||
m_transPos = CROSSFADE_SAMPLES*NUM_OUTCHANNELS;
|
||||
}
|
||||
|
||||
int BinauralReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength();
|
||||
}
|
||||
|
||||
int BinauralReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
Specs BinauralReader::getSpecs() const
|
||||
{
|
||||
Specs specs = m_reader->getSpecs();
|
||||
specs.channels = CHANNELS_STEREO;
|
||||
return specs;
|
||||
}
|
||||
|
||||
void BinauralReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
int samples = 0;
|
||||
int iteration = 0;
|
||||
if(length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
eos = (m_eosTail && m_outBufferPos >= m_eOutBufLen);
|
||||
return;
|
||||
}
|
||||
|
||||
eos = false;
|
||||
int writePos = 0;
|
||||
do
|
||||
{
|
||||
int bufRest = m_eOutBufLen - m_outBufferPos;
|
||||
int writeLength = std::min((length*NUM_OUTCHANNELS) - writePos, m_eOutBufLen + bufRest);
|
||||
if(bufRest < writeLength || (m_eOutBufLen == 0 && m_eosTail))
|
||||
{
|
||||
if(bufRest > 0)
|
||||
std::memcpy(buffer + writePos, m_outBuffer + m_outBufferPos, bufRest*sizeof(sample_t));
|
||||
if(!m_eosTail)
|
||||
{
|
||||
int n = NUM_OUTCHANNELS;
|
||||
if(m_transition)
|
||||
n = NUM_CONVOLVERS;
|
||||
else if(checkSource())
|
||||
n = NUM_CONVOLVERS;
|
||||
loadBuffer(n);
|
||||
|
||||
int len = std::min(std::abs(writeLength - bufRest), m_eOutBufLen);
|
||||
std::memcpy(buffer + writePos + bufRest, m_outBuffer, len*sizeof(sample_t));
|
||||
samples += len;
|
||||
m_outBufferPos = len;
|
||||
writeLength = std::min((length*NUM_OUTCHANNELS) - writePos, m_eOutBufLen + bufRest);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_outBufferPos += bufRest;
|
||||
length = (writePos+bufRest) / NUM_OUTCHANNELS;
|
||||
eos = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(buffer + writePos, m_outBuffer + m_outBufferPos, writeLength*sizeof(sample_t));
|
||||
m_outBufferPos += writeLength;
|
||||
}
|
||||
writePos += writeLength;
|
||||
iteration++;
|
||||
} while(writePos < length*NUM_OUTCHANNELS);
|
||||
m_position += length;
|
||||
}
|
||||
|
||||
bool BinauralReader::checkSource()
|
||||
{
|
||||
if((m_Azimuth != m_source->getAzimuth() || m_Elevation != m_source->getElevation()) && (!m_eosReader && !m_eosTail))
|
||||
{
|
||||
float az = m_Azimuth = m_source->getAzimuth();
|
||||
float el = m_Elevation = m_source->getElevation();
|
||||
auto irs = m_hrtfs->getImpulseResponse(az, el);
|
||||
if(az != m_RealAzimuth || el != m_RealElevation)
|
||||
{
|
||||
m_RealAzimuth = az;
|
||||
m_RealElevation = el;
|
||||
for(int i = 0; i < NUM_OUTCHANNELS; i++)
|
||||
{
|
||||
auto temp = std::move(m_convolvers[i]);
|
||||
m_convolvers[i] = std::move(m_convolvers[i + NUM_OUTCHANNELS]);
|
||||
m_convolvers[i + NUM_OUTCHANNELS] = std::move(temp);
|
||||
}
|
||||
for(int i = 0; i < NUM_OUTCHANNELS; i++)
|
||||
if(i%NUM_OUTCHANNELS == 0)
|
||||
m_convolvers[i]->setImpulseResponse(irs.first->getChannel(0));
|
||||
else
|
||||
m_convolvers[i]->setImpulseResponse(irs.second->getChannel(0));
|
||||
|
||||
m_transPos = CROSSFADE_SAMPLES*NUM_OUTCHANNELS;
|
||||
m_transition = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BinauralReader::loadBuffer(int nConvolvers)
|
||||
{
|
||||
m_lastLengthIn = m_L;
|
||||
m_reader->read(m_lastLengthIn, m_eosReader, m_inBuffer);
|
||||
if(!m_eosReader || m_lastLengthIn > 0)
|
||||
{
|
||||
int len = m_lastLengthIn;
|
||||
for(int i = 0; i < nConvolvers; i++)
|
||||
m_futures[i] = m_threadPool->enqueue(&BinauralReader::threadFunction, this, i, true);
|
||||
for(int i = 0; i < nConvolvers; i++)
|
||||
len = m_futures[i].get();
|
||||
|
||||
joinByChannel(0, len, nConvolvers);
|
||||
m_eOutBufLen = len*NUM_OUTCHANNELS;
|
||||
}
|
||||
else if(!m_eosTail)
|
||||
{
|
||||
int len = m_lastLengthIn = m_L;
|
||||
for(int i = 0; i < nConvolvers; i++)
|
||||
m_futures[i] = m_threadPool->enqueue(&BinauralReader::threadFunction, this, i, false);
|
||||
for(int i = 0; i < nConvolvers; i++)
|
||||
len = m_futures[i].get();
|
||||
|
||||
joinByChannel(0, len, nConvolvers);
|
||||
m_eOutBufLen = len*NUM_OUTCHANNELS;
|
||||
}
|
||||
}
|
||||
|
||||
void BinauralReader::joinByChannel(int start, int len, int nConvolvers)
|
||||
{
|
||||
int k = 0;
|
||||
float vol = 0;
|
||||
const int l = CROSSFADE_SAMPLES*NUM_OUTCHANNELS;
|
||||
for(int i = 0; i < len*NUM_OUTCHANNELS; i += NUM_OUTCHANNELS)
|
||||
{
|
||||
if(m_transition)
|
||||
{
|
||||
vol = (m_transPos - i) / (float)l;
|
||||
if(vol > 1.0f)
|
||||
vol = 1.0f;
|
||||
else if(vol < 0.0f)
|
||||
vol = 0.0f;
|
||||
}
|
||||
|
||||
for(int j = 0; j < NUM_OUTCHANNELS; j++)
|
||||
m_outBuffer[i + j + start] = ((m_vecOut[j][k] * (1.0f - vol)) + (m_vecOut[j + NUM_OUTCHANNELS][k] * vol))*m_source->getVolume();
|
||||
k++;
|
||||
}
|
||||
if(m_transition)
|
||||
{
|
||||
m_transPos -= len*NUM_OUTCHANNELS;
|
||||
if(m_transPos <= 0)
|
||||
{
|
||||
m_transition = false;
|
||||
m_transPos = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BinauralReader::threadFunction(int id, bool input)
|
||||
{
|
||||
int l = m_lastLengthIn;
|
||||
if(input)
|
||||
m_convolvers[id]->getNext(m_inBuffer, m_vecOut[id], l, m_eosTail);
|
||||
else
|
||||
m_convolvers[id]->getNext(nullptr, m_vecOut[id], l, m_eosTail);
|
||||
return l;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
60
blender-5.2.0/extern/audaspace/src/fx/BinauralSound.cpp
vendored
Normal file
60
blender-5.2.0/extern/audaspace/src/fx/BinauralSound.cpp
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/BinauralSound.h"
|
||||
#include "fx/BinauralReader.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
BinauralSound::BinauralSound(std::shared_ptr<ISound> sound, std::shared_ptr<HRTF> hrtfs, std::shared_ptr<Source> source, std::shared_ptr<ThreadPool> threadPool) :
|
||||
BinauralSound(sound, hrtfs, source, threadPool, std::make_shared<FFTPlan>(0.0))
|
||||
{
|
||||
}
|
||||
|
||||
BinauralSound::BinauralSound(std::shared_ptr<ISound> sound, std::shared_ptr<HRTF> hrtfs, std::shared_ptr<Source> source, std::shared_ptr<ThreadPool> threadPool, std::shared_ptr<FFTPlan> plan) :
|
||||
m_sound(sound), m_hrtfs(hrtfs), m_source(source), m_threadPool(threadPool), m_plan(plan)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> BinauralSound::createReader()
|
||||
{
|
||||
return std::make_shared<BinauralReader>(m_sound->createReader(), m_hrtfs, m_source, m_threadPool, m_plan);
|
||||
}
|
||||
|
||||
std::shared_ptr<HRTF> BinauralSound::getHRTFs()
|
||||
{
|
||||
return m_hrtfs;
|
||||
}
|
||||
|
||||
void BinauralSound::setHRTFs(std::shared_ptr<HRTF> hrtfs)
|
||||
{
|
||||
m_hrtfs = hrtfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<Source> BinauralSound::getSource()
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
void BinauralSound::setSource(std::shared_ptr<Source> source)
|
||||
{
|
||||
m_source = source;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
28
blender-5.2.0/extern/audaspace/src/fx/Butterworth.cpp
vendored
Normal file
28
blender-5.2.0/extern/audaspace/src/fx/Butterworth.cpp
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Butterworth.h"
|
||||
#include "fx/ButterworthCalculator.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Butterworth::Butterworth(std::shared_ptr<ISound> sound, float frequency) :
|
||||
DynamicIIRFilter(sound, std::shared_ptr<IDynamicIIRFilterCalculator>(new ButterworthCalculator(frequency)))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
54
blender-5.2.0/extern/audaspace/src/fx/ButterworthCalculator.cpp
vendored
Normal file
54
blender-5.2.0/extern/audaspace/src/fx/ButterworthCalculator.cpp
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/ButterworthCalculator.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#define BWPB41 0.76536686473
|
||||
#define BWPB42 1.84775906502
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
ButterworthCalculator::ButterworthCalculator(float frequency) :
|
||||
m_frequency(frequency)
|
||||
{
|
||||
}
|
||||
|
||||
void ButterworthCalculator::recalculateCoefficients(SampleRate rate, std::vector<float> &b, std::vector<float> &a)
|
||||
{
|
||||
float omega = 2 * std::tan(m_frequency * M_PI / rate);
|
||||
float o2 = omega * omega;
|
||||
float o4 = o2 * o2;
|
||||
float x1 = o2 + 2.0f * (float)BWPB41 * omega + 4.0f;
|
||||
float x2 = o2 + 2.0f * (float)BWPB42 * omega + 4.0f;
|
||||
float y1 = o2 - 2.0f * (float)BWPB41 * omega + 4.0f;
|
||||
float y2 = o2 - 2.0f * (float)BWPB42 * omega + 4.0f;
|
||||
float o228 = 2.0f * o2 - 8.0f;
|
||||
float norm = x1 * x2;
|
||||
a.push_back(1);
|
||||
a.push_back((x1 + x2) * o228 / norm);
|
||||
a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm);
|
||||
a.push_back((y1 + y2) * o228 / norm);
|
||||
a.push_back(y1 * y2 / norm);
|
||||
b.push_back(o4 / norm);
|
||||
b.push_back(4 * o4 / norm);
|
||||
b.push_back(6 * o4 / norm);
|
||||
b.push_back(b[1]);
|
||||
b.push_back(b[0]);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
38
blender-5.2.0/extern/audaspace/src/fx/CallbackIIRFilterReader.cpp
vendored
Normal file
38
blender-5.2.0/extern/audaspace/src/fx/CallbackIIRFilterReader.cpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/CallbackIIRFilterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
CallbackIIRFilterReader::CallbackIIRFilterReader(std::shared_ptr<IReader> reader, int in, int out, doFilterIIR doFilter, endFilterIIR endFilter, void* data) :
|
||||
BaseIIRFilterReader(reader, in, out),
|
||||
m_filter(doFilter), m_endFilter(endFilter), m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
CallbackIIRFilterReader::~CallbackIIRFilterReader()
|
||||
{
|
||||
if(m_endFilter)
|
||||
m_endFilter(m_data);
|
||||
}
|
||||
|
||||
sample_t CallbackIIRFilterReader::filter()
|
||||
{
|
||||
return m_filter(this, m_data);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
156
blender-5.2.0/extern/audaspace/src/fx/Convolver.cpp
vendored
Normal file
156
blender-5.2.0/extern/audaspace/src/fx/Convolver.cpp
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Convolver.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
Convolver::Convolver(std::shared_ptr<std::vector<std::shared_ptr<std::vector<std::complex<sample_t>>>>> ir, int irLength, std::shared_ptr<ThreadPool> threadPool, std::shared_ptr<FFTPlan> plan) :
|
||||
m_N(plan->getSize()), m_M(plan->getSize()/2), m_L(plan->getSize()/2), m_irBuffers(ir), m_numThreads(std::min(threadPool->getNumOfThreads(), static_cast<unsigned int>(m_irBuffers->size() - 1))), m_threadPool(threadPool), m_irLength(irLength), m_tailCounter(0), m_eos(false)
|
||||
|
||||
{
|
||||
m_resetFlag = false;
|
||||
m_futures.resize(m_numThreads);
|
||||
for(int i = 0; i < m_irBuffers->size(); i++)
|
||||
{
|
||||
m_fftConvolvers.push_back(std::unique_ptr<FFTConvolver>(new FFTConvolver((*m_irBuffers)[i], plan)));
|
||||
m_delayLine.push_front((fftwf_complex*)std::calloc((m_N / 2) + 1, sizeof(fftwf_complex)));
|
||||
}
|
||||
|
||||
m_accBuffer = (fftwf_complex*)std::calloc((m_N / 2) + 1, sizeof(fftwf_complex));
|
||||
for(int i = 0; i < m_numThreads; i++)
|
||||
m_threadAccBuffers.push_back((fftwf_complex*)std::calloc((m_N / 2) + 1, sizeof(fftwf_complex)));
|
||||
}
|
||||
|
||||
Convolver::~Convolver()
|
||||
{
|
||||
m_resetFlag = true;
|
||||
for(auto &fut : m_futures)
|
||||
if(fut.valid())
|
||||
fut.get();
|
||||
|
||||
std::free(m_accBuffer);
|
||||
for(auto buf : m_threadAccBuffers)
|
||||
std::free(buf);
|
||||
while(!m_delayLine.empty())
|
||||
{
|
||||
std::free(m_delayLine.front());
|
||||
m_delayLine.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void Convolver::getNext(sample_t* inBuffer, sample_t* outBuffer, int& length, bool& eos)
|
||||
{
|
||||
if(length > m_L)
|
||||
{
|
||||
length = 0;
|
||||
eos = m_eos;
|
||||
return;
|
||||
}
|
||||
if(m_eos)
|
||||
{
|
||||
eos = m_eos;
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
eos = false;
|
||||
for(auto &fut : m_futures)
|
||||
if(fut.valid())
|
||||
fut.get();
|
||||
|
||||
if(inBuffer != nullptr)
|
||||
m_fftConvolvers[0]->getNextFDL(inBuffer, reinterpret_cast<std::complex<sample_t>*>(m_accBuffer), length, m_delayLine[0]);
|
||||
else
|
||||
{
|
||||
m_tailCounter++;
|
||||
std::memset(outBuffer, 0, m_L*sizeof(sample_t));
|
||||
m_fftConvolvers[0]->getNextFDL(outBuffer, reinterpret_cast<std::complex<sample_t>*>(m_accBuffer), length, m_delayLine[0]);
|
||||
}
|
||||
m_delayLine.push_front(m_delayLine.back());
|
||||
m_delayLine.pop_back();
|
||||
length = m_L;
|
||||
m_fftConvolvers[0]->IFFT_FDL(m_accBuffer, outBuffer, length);
|
||||
std::memset(m_accBuffer, 0, ((m_N / 2) + 1)*sizeof(fftwf_complex));
|
||||
|
||||
if(m_tailCounter >= m_delayLine.size() && inBuffer == nullptr)
|
||||
{
|
||||
eos = m_eos = true;
|
||||
length = m_irLength%m_M;
|
||||
if(length == 0)
|
||||
length = m_M;
|
||||
}
|
||||
else
|
||||
for(int i = 0; i < m_futures.size(); i++)
|
||||
m_futures[i] = m_threadPool->enqueue(&Convolver::threadFunction, this, i);
|
||||
}
|
||||
|
||||
void Convolver::reset()
|
||||
{
|
||||
m_resetFlag = true;
|
||||
for(auto &fut : m_futures)
|
||||
if(fut.valid())
|
||||
fut.get();
|
||||
|
||||
for(int i = 0; i < m_delayLine.size();i++)
|
||||
std::memset(m_delayLine[i], 0, ((m_N / 2) + 1)*sizeof(fftwf_complex));
|
||||
for(int i = 0; i < m_fftConvolvers.size(); i++)
|
||||
m_fftConvolvers[i]->clear();
|
||||
std::memset(m_accBuffer, 0, ((m_N / 2) + 1)*sizeof(fftwf_complex));
|
||||
m_tailCounter = 0;
|
||||
m_eos = false;
|
||||
m_resetFlag = false;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::shared_ptr<std::vector<std::complex<sample_t>>>>> Convolver::getImpulseResponse()
|
||||
{
|
||||
return m_irBuffers;
|
||||
}
|
||||
|
||||
void Convolver::setImpulseResponse(std::shared_ptr<std::vector<std::shared_ptr<std::vector<std::complex<sample_t>>>>> ir)
|
||||
{
|
||||
reset();
|
||||
m_irBuffers = ir;
|
||||
for(int i = 0; i < m_irBuffers->size(); i++)
|
||||
m_fftConvolvers[i]->setImpulseResponse((*m_irBuffers)[i]);
|
||||
}
|
||||
|
||||
bool Convolver::threadFunction(int id)
|
||||
{
|
||||
int total = m_irBuffers->size();
|
||||
int share = std::ceil(((float)total - 1) / (float)m_numThreads);
|
||||
int start = id*share + 1;
|
||||
int end = std::min(start + share, total);
|
||||
|
||||
std::memset(m_threadAccBuffers[id], 0, ((m_N / 2) + 1)*sizeof(fftwf_complex));
|
||||
|
||||
for(int i = start; i < end && !m_resetFlag; i++)
|
||||
m_fftConvolvers[i]->getNextFDL(reinterpret_cast<std::complex<sample_t>*>(m_delayLine[i]), reinterpret_cast<std::complex<sample_t>*>(m_threadAccBuffers[id]));
|
||||
|
||||
m_sumMutex.lock();
|
||||
for(int i = 0; (i < m_N / 2 + 1) && !m_resetFlag; i++)
|
||||
{
|
||||
m_accBuffer[i][0] += m_threadAccBuffers[id][i][0];
|
||||
m_accBuffer[i][1] += m_threadAccBuffers[id][i][1];
|
||||
}
|
||||
m_sumMutex.unlock();
|
||||
return true;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
203
blender-5.2.0/extern/audaspace/src/fx/ConvolverReader.cpp
vendored
Normal file
203
blender-5.2.0/extern/audaspace/src/fx/ConvolverReader.cpp
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/ConvolverReader.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
ConvolverReader::ConvolverReader(std::shared_ptr<IReader> reader, std::shared_ptr<ImpulseResponse> ir, std::shared_ptr<ThreadPool> threadPool, std::shared_ptr<FFTPlan> plan) :
|
||||
m_position(0), m_reader(reader), m_ir(ir), m_N(plan->getSize()), m_eosReader(false), m_eosTail(false), m_inChannels(reader->getSpecs().channels), m_irChannels(ir->getSpecs().channels), m_threadPool(threadPool)
|
||||
{
|
||||
m_nChannelThreads = std::min((int)threadPool->getNumOfThreads(), m_inChannels);
|
||||
m_futures.resize(m_nChannelThreads);
|
||||
|
||||
int irLength = m_ir->getLength();
|
||||
if(m_irChannels != 1 && m_irChannels != m_inChannels)
|
||||
AUD_THROW(StateException, "The impulse response and the sound must either have the same amount of channels or the impulse response must be mono");
|
||||
if(m_reader->getSpecs().rate != m_ir->getSpecs().rate)
|
||||
AUD_THROW(StateException, "The sound and the impulse response. must have the same rate");
|
||||
|
||||
m_M = m_L = m_N / 2;
|
||||
|
||||
if(m_irChannels > 1)
|
||||
for(int i = 0; i < m_inChannels; i++)
|
||||
m_convolvers.push_back(std::unique_ptr<Convolver>(new Convolver(ir->getChannel(i), irLength, m_threadPool, plan)));
|
||||
else
|
||||
for(int i = 0; i < m_inChannels; i++)
|
||||
m_convolvers.push_back(std::unique_ptr<Convolver>(new Convolver(ir->getChannel(0), irLength, m_threadPool, plan)));
|
||||
|
||||
for(int i = 0; i < m_inChannels; i++)
|
||||
m_vecInOut.push_back((sample_t*)std::malloc(m_L*sizeof(sample_t)));
|
||||
m_outBuffer = (sample_t*)std::malloc(m_L*m_inChannels*sizeof(sample_t));
|
||||
m_outBufLen = m_eOutBufLen = m_outBufferPos = m_L*m_inChannels;
|
||||
}
|
||||
|
||||
ConvolverReader::~ConvolverReader()
|
||||
{
|
||||
std::free(m_outBuffer);
|
||||
for(int i = 0; i < m_inChannels; i++)
|
||||
std::free(m_vecInOut[i]);
|
||||
}
|
||||
|
||||
bool ConvolverReader::isSeekable() const
|
||||
{
|
||||
return m_reader->isSeekable();
|
||||
}
|
||||
|
||||
void ConvolverReader::seek(int position)
|
||||
{
|
||||
m_position = position;
|
||||
m_reader->seek(position);
|
||||
for(int i = 0; i < m_inChannels; i++)
|
||||
m_convolvers[i]->reset();
|
||||
m_eosTail = false;
|
||||
m_eosReader = false;
|
||||
m_outBufferPos = m_eOutBufLen = m_outBufLen;
|
||||
}
|
||||
|
||||
int ConvolverReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength();
|
||||
}
|
||||
|
||||
int ConvolverReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
Specs ConvolverReader::getSpecs() const
|
||||
{
|
||||
return m_reader->getSpecs();
|
||||
}
|
||||
|
||||
void ConvolverReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
if(length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
eos = (m_eosTail && m_outBufferPos >= m_eOutBufLen);
|
||||
return;
|
||||
}
|
||||
eos = false;
|
||||
int writePos = 0;
|
||||
do
|
||||
{
|
||||
int bufRest = m_eOutBufLen - m_outBufferPos;
|
||||
int writeLength = std::min((length*m_inChannels) - writePos, m_eOutBufLen + bufRest);
|
||||
if(bufRest < writeLength || (m_eOutBufLen == 0 && m_eosTail))
|
||||
{
|
||||
if(bufRest > 0)
|
||||
std::memcpy(buffer + writePos, m_outBuffer + m_outBufferPos, bufRest*sizeof(sample_t));
|
||||
if(!m_eosTail)
|
||||
{
|
||||
loadBuffer();
|
||||
int len = std::min(std::abs(writeLength - bufRest), m_eOutBufLen);
|
||||
std::memcpy(buffer + writePos + bufRest, m_outBuffer, len*sizeof(sample_t));
|
||||
m_outBufferPos = len;
|
||||
writeLength = std::min((length*m_inChannels) - writePos, m_eOutBufLen + bufRest);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_outBufferPos += bufRest;
|
||||
length = (writePos + bufRest) / m_inChannels;
|
||||
eos = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(buffer + writePos, m_outBuffer + m_outBufferPos, writeLength*sizeof(sample_t));
|
||||
m_outBufferPos += writeLength;
|
||||
}
|
||||
writePos += writeLength;
|
||||
} while(writePos < length*m_inChannels);
|
||||
m_position += length;
|
||||
}
|
||||
|
||||
void ConvolverReader::loadBuffer()
|
||||
{
|
||||
m_lastLengthIn = m_L;
|
||||
m_reader->read(m_lastLengthIn, m_eosReader, m_outBuffer);
|
||||
if(!m_eosReader || m_lastLengthIn>0)
|
||||
{
|
||||
divideByChannel(m_outBuffer, m_lastLengthIn*m_inChannels);
|
||||
int len = m_lastLengthIn;
|
||||
|
||||
for(int i = 0; i < m_futures.size(); i++)
|
||||
m_futures[i] = m_threadPool->enqueue(&ConvolverReader::threadFunction, this, i, true);
|
||||
for(auto &fut : m_futures)
|
||||
len = fut.get();
|
||||
|
||||
joinByChannel(0, len);
|
||||
m_eOutBufLen = len*m_inChannels;
|
||||
}
|
||||
else if(!m_eosTail)
|
||||
{
|
||||
int len = m_lastLengthIn = m_L;
|
||||
for(int i = 0; i < m_futures.size(); i++)
|
||||
m_futures[i] = m_threadPool->enqueue(&ConvolverReader::threadFunction, this, i, false);
|
||||
for(auto &fut : m_futures)
|
||||
len = fut.get();
|
||||
|
||||
joinByChannel(0, len);
|
||||
m_eOutBufLen = len*m_inChannels;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvolverReader::divideByChannel(const sample_t* buffer, int len)
|
||||
{
|
||||
int k = 0;
|
||||
for(int i = 0; i < len; i += m_inChannels)
|
||||
{
|
||||
for(int j = 0; j < m_inChannels; j++)
|
||||
m_vecInOut[j][k] = buffer[i + j];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvolverReader::joinByChannel(int start, int len)
|
||||
{
|
||||
int k = 0;
|
||||
for(int i = 0; i < len*m_inChannels; i += m_inChannels)
|
||||
{
|
||||
for(int j = 0; j < m_vecInOut.size(); j++)
|
||||
m_outBuffer[i + j + start] = m_vecInOut[j][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
int ConvolverReader::threadFunction(int id, bool input)
|
||||
{
|
||||
int share = std::ceil((float)m_inChannels / (float)m_nChannelThreads);
|
||||
int start = id*share;
|
||||
int end = std::min(start + share, m_inChannels);
|
||||
|
||||
int l=m_lastLengthIn;
|
||||
for(int i = start; i < end; i++)
|
||||
if(input)
|
||||
m_convolvers[i]->getNext(m_vecInOut[i], m_vecInOut[i], l, m_eosTail);
|
||||
else
|
||||
m_convolvers[i]->getNext(nullptr, m_vecInOut[i], l, m_eosTail);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
50
blender-5.2.0/extern/audaspace/src/fx/ConvolverSound.cpp
vendored
Normal file
50
blender-5.2.0/extern/audaspace/src/fx/ConvolverSound.cpp
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/ConvolverSound.h"
|
||||
#include "fx/ConvolverReader.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
ConvolverSound::ConvolverSound(std::shared_ptr<ISound> sound, std::shared_ptr<ImpulseResponse> impulseResponse, std::shared_ptr<ThreadPool> threadPool) :
|
||||
ConvolverSound(sound, impulseResponse, threadPool, std::make_shared<FFTPlan>(0.0))
|
||||
{
|
||||
}
|
||||
|
||||
ConvolverSound::ConvolverSound(std::shared_ptr<ISound> sound, std::shared_ptr<ImpulseResponse> impulseResponse, std::shared_ptr<ThreadPool> threadPool, std::shared_ptr<FFTPlan> plan) :
|
||||
m_sound(sound), m_impulseResponse(impulseResponse), m_threadPool(threadPool), m_plan(plan)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> ConvolverSound::createReader()
|
||||
{
|
||||
return std::make_shared<ConvolverReader>(m_sound->createReader(), m_impulseResponse, m_threadPool, m_plan);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImpulseResponse> ConvolverSound::getImpulseResponse()
|
||||
{
|
||||
return m_impulseResponse;
|
||||
}
|
||||
|
||||
void ConvolverSound::setImpulseResponse(std::shared_ptr<ImpulseResponse> impulseResponse)
|
||||
{
|
||||
m_impulseResponse = impulseResponse;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
38
blender-5.2.0/extern/audaspace/src/fx/Delay.cpp
vendored
Normal file
38
blender-5.2.0/extern/audaspace/src/fx/Delay.cpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Delay.h"
|
||||
#include "fx/DelayReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Delay::Delay(std::shared_ptr<ISound> sound, double delay) :
|
||||
Effect(sound),
|
||||
m_delay(delay)
|
||||
{
|
||||
}
|
||||
|
||||
double Delay::getDelay() const
|
||||
{
|
||||
return m_delay;
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Delay::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new DelayReader(getReader(), m_delay));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
87
blender-5.2.0/extern/audaspace/src/fx/DelayReader.cpp
vendored
Normal file
87
blender-5.2.0/extern/audaspace/src/fx/DelayReader.cpp
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/DelayReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
DelayReader::DelayReader(std::shared_ptr<IReader> reader, double delay) :
|
||||
EffectReader(reader),
|
||||
m_delay(int((SampleRate)delay * reader->getSpecs().rate)),
|
||||
m_remdelay(int((SampleRate)delay * reader->getSpecs().rate))
|
||||
{
|
||||
}
|
||||
|
||||
void DelayReader::seek(int position)
|
||||
{
|
||||
if(position < m_delay)
|
||||
{
|
||||
m_remdelay = m_delay - position;
|
||||
m_reader->seek(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_remdelay = 0;
|
||||
m_reader->seek(position - m_delay);
|
||||
}
|
||||
}
|
||||
|
||||
int DelayReader::getLength() const
|
||||
{
|
||||
int len = m_reader->getLength();
|
||||
if(len < 0)
|
||||
return len;
|
||||
return len + m_delay;
|
||||
}
|
||||
|
||||
int DelayReader::getPosition() const
|
||||
{
|
||||
if(m_remdelay > 0)
|
||||
return m_delay - m_remdelay;
|
||||
return m_reader->getPosition() + m_delay;
|
||||
}
|
||||
|
||||
void DelayReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
if(m_remdelay > 0)
|
||||
{
|
||||
Specs specs = m_reader->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
if(length > m_remdelay)
|
||||
{
|
||||
std::memset(buffer, 0, m_remdelay * samplesize);
|
||||
|
||||
int len = length - m_remdelay;
|
||||
m_reader->read(len, eos, buffer + m_remdelay * specs.channels);
|
||||
|
||||
length = m_remdelay + len;
|
||||
|
||||
m_remdelay = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memset(buffer, 0, length * samplesize);
|
||||
m_remdelay -= length;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_reader->read(length, eos, buffer);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
35
blender-5.2.0/extern/audaspace/src/fx/DynamicIIRFilter.cpp
vendored
Normal file
35
blender-5.2.0/extern/audaspace/src/fx/DynamicIIRFilter.cpp
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/DynamicIIRFilter.h"
|
||||
#include "fx/DynamicIIRFilterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
DynamicIIRFilter::DynamicIIRFilter(std::shared_ptr<ISound> sound,
|
||||
std::shared_ptr<IDynamicIIRFilterCalculator> calculator) :
|
||||
Effect(sound),
|
||||
m_calculator(calculator)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> DynamicIIRFilter::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new DynamicIIRFilterReader(getReader(), m_calculator));
|
||||
}
|
||||
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
36
blender-5.2.0/extern/audaspace/src/fx/DynamicIIRFilterReader.cpp
vendored
Normal file
36
blender-5.2.0/extern/audaspace/src/fx/DynamicIIRFilterReader.cpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/DynamicIIRFilterReader.h"
|
||||
#include "fx/IDynamicIIRFilterCalculator.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
DynamicIIRFilterReader::DynamicIIRFilterReader(std::shared_ptr<IReader> reader, std::shared_ptr<IDynamicIIRFilterCalculator> calculator) :
|
||||
IIRFilterReader(reader, std::vector<float>(), std::vector<float>()),
|
||||
m_calculator(calculator)
|
||||
{
|
||||
sampleRateChanged(reader->getSpecs().rate);
|
||||
}
|
||||
|
||||
void DynamicIIRFilterReader::sampleRateChanged(SampleRate rate)
|
||||
{
|
||||
std::vector<float> a, b;
|
||||
m_calculator->recalculateCoefficients(rate, b, a);
|
||||
setCoefficients(b, a);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
343
blender-5.2.0/extern/audaspace/src/fx/DynamicMusic.cpp
vendored
Normal file
343
blender-5.2.0/extern/audaspace/src/fx/DynamicMusic.cpp
vendored
Normal file
@@ -0,0 +1,343 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/DynamicMusic.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
DynamicMusic::DynamicMusic(std::shared_ptr<IDevice> device) :
|
||||
m_fadeTime(1.0f), m_device(device)
|
||||
{
|
||||
m_id = 0;
|
||||
m_transitioning = false;
|
||||
m_stopThread = false;
|
||||
m_volume = m_device->getVolume();
|
||||
m_scenes.push_back(std::vector<std::shared_ptr<ISound>>(1, nullptr));
|
||||
}
|
||||
|
||||
DynamicMusic::~DynamicMusic()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
int DynamicMusic::addScene(std::shared_ptr<ISound> sound)
|
||||
{
|
||||
std::vector<std::shared_ptr<ISound>> v;
|
||||
m_scenes.push_back(v);
|
||||
for(int i = 0; i < m_scenes.size()-1; i++)
|
||||
m_scenes.back().push_back(nullptr);
|
||||
for(int i = 0; i < m_scenes.size()-1; i++)
|
||||
m_scenes[i].push_back(nullptr);
|
||||
m_scenes.back().push_back(sound);
|
||||
|
||||
return m_scenes.size() - 1;
|
||||
}
|
||||
|
||||
bool DynamicMusic::changeScene(int id)
|
||||
{
|
||||
if(id >= m_scenes.size() || m_transitioning)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if(m_fadeThread.joinable())
|
||||
m_fadeThread.join();
|
||||
m_device->lock();
|
||||
if(id == m_id)
|
||||
{
|
||||
m_currentHandle->setVolume(m_volume);
|
||||
m_currentHandle->setLoopCount(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_soundTarget = id;
|
||||
if(m_scenes[m_id][id] == nullptr)
|
||||
{
|
||||
m_stopThread = false;
|
||||
if((m_scenes[m_id][m_id] != nullptr && m_currentHandle->getStatus() != STATUS_INVALID) || m_scenes[m_soundTarget][m_soundTarget] != nullptr)
|
||||
{
|
||||
m_transitioning = true;
|
||||
if(m_scenes[m_id][m_id] == nullptr || m_currentHandle->getStatus() == STATUS_INVALID)
|
||||
{
|
||||
m_device->lock();
|
||||
m_currentHandle = m_device->play(m_scenes[m_soundTarget][m_soundTarget]);
|
||||
m_currentHandle->setVolume(0.0f);
|
||||
m_currentHandle->setLoopCount(-1);
|
||||
m_device->unlock();
|
||||
m_fadeThread = std::thread(&DynamicMusic::fadeInThread, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_scenes[m_soundTarget][m_soundTarget] != nullptr)
|
||||
{
|
||||
m_device->lock();
|
||||
m_transitionHandle = m_currentHandle;
|
||||
m_currentHandle = m_device->play(m_scenes[m_soundTarget][m_soundTarget]);
|
||||
m_currentHandle->setVolume(0.0f);
|
||||
m_currentHandle->setLoopCount(-1);
|
||||
m_device->unlock();
|
||||
m_fadeThread = std::thread(&DynamicMusic::crossfadeThread, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_transitionHandle = m_currentHandle;
|
||||
m_currentHandle = nullptr;
|
||||
m_fadeThread = std::thread(&DynamicMusic::fadeOutThread, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_scenes[m_id][m_id] == nullptr || m_currentHandle->getStatus() == STATUS_INVALID)
|
||||
transitionCallback(this);
|
||||
else
|
||||
{
|
||||
m_currentHandle->setLoopCount(0);
|
||||
m_currentHandle->setStopCallback(transitionCallback, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_device->unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int DynamicMusic::getScene()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool DynamicMusic::addTransition(int init, int end, std::shared_ptr<ISound> sound)
|
||||
{
|
||||
if(init != end && init < m_scenes.size() && end < m_scenes.size() && init >= 0 && end >= 0)
|
||||
{
|
||||
m_scenes[init][end] = sound;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DynamicMusic::setFadeTime(double seconds)
|
||||
{
|
||||
m_device->lock();
|
||||
m_fadeTime = seconds;
|
||||
m_device->unlock();
|
||||
}
|
||||
|
||||
double DynamicMusic::getFadeTime()
|
||||
{
|
||||
return m_fadeTime;
|
||||
}
|
||||
|
||||
bool DynamicMusic::resume()
|
||||
{
|
||||
bool result = false, resultTrans = false;
|
||||
|
||||
if(m_currentHandle != nullptr)
|
||||
result = m_currentHandle->resume();
|
||||
if(m_transitionHandle != nullptr)
|
||||
resultTrans = m_transitionHandle->resume();
|
||||
|
||||
return result || resultTrans;
|
||||
}
|
||||
|
||||
bool DynamicMusic::pause()
|
||||
{
|
||||
bool result = false, resultTrans = false;
|
||||
|
||||
if(m_currentHandle != nullptr)
|
||||
result = m_currentHandle->pause();
|
||||
if(m_transitionHandle != nullptr)
|
||||
resultTrans = m_transitionHandle->pause();
|
||||
|
||||
return result || resultTrans;
|
||||
}
|
||||
|
||||
bool DynamicMusic::seek(double position)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if(m_currentHandle != nullptr)
|
||||
{
|
||||
result = m_currentHandle->seek(position);
|
||||
if(m_transitionHandle != nullptr && result == true)
|
||||
m_transitionHandle->stop();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
double DynamicMusic::getPosition()
|
||||
{
|
||||
double result = 0.0f;
|
||||
|
||||
if(m_currentHandle != nullptr)
|
||||
result = m_currentHandle->getPosition();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float DynamicMusic::getVolume()
|
||||
{
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
bool DynamicMusic::setVolume(float volume)
|
||||
{
|
||||
m_volume = volume;
|
||||
bool result = false, resultTrans = false;
|
||||
|
||||
if(m_currentHandle != nullptr)
|
||||
result = m_currentHandle->setVolume(volume);
|
||||
if(m_transitionHandle != nullptr)
|
||||
{
|
||||
m_device->lock();
|
||||
if(volume<m_transitionHandle->getVolume())
|
||||
resultTrans = m_transitionHandle->setVolume(0.0f);
|
||||
m_device->unlock();
|
||||
}
|
||||
if(m_currentHandle == nullptr && m_transitionHandle == nullptr)
|
||||
result = true;
|
||||
|
||||
return result || resultTrans;
|
||||
}
|
||||
|
||||
Status DynamicMusic::getStatus()
|
||||
{
|
||||
if(m_currentHandle != nullptr)
|
||||
{
|
||||
Status result = m_currentHandle->getStatus();
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return STATUS_INVALID;
|
||||
}
|
||||
|
||||
bool DynamicMusic::stop()
|
||||
{
|
||||
m_stopThread = true;
|
||||
bool result = false, resultTrans = false;
|
||||
|
||||
if(m_currentHandle != nullptr)
|
||||
result = m_currentHandle->stop();
|
||||
if(m_transitionHandle != nullptr)
|
||||
|
||||
resultTrans = m_transitionHandle->stop();
|
||||
|
||||
if(m_fadeThread.joinable())
|
||||
m_fadeThread.join();
|
||||
m_id = 0;
|
||||
|
||||
return result || resultTrans;
|
||||
}
|
||||
|
||||
void DynamicMusic::transitionCallback(void* player)
|
||||
{
|
||||
auto dat = reinterpret_cast<DynamicMusic*>(player);
|
||||
dat->m_transitioning = true;
|
||||
dat->m_device->lock();
|
||||
dat->m_currentHandle = dat->m_device->play(dat->m_scenes[dat->m_id][dat->m_soundTarget]);
|
||||
dat->m_currentHandle->setVolume(dat->m_volume);
|
||||
if(dat->m_scenes[dat->m_soundTarget][dat->m_soundTarget] != nullptr)
|
||||
dat->m_currentHandle->setStopCallback(sceneCallback, player);
|
||||
dat->m_device->unlock();
|
||||
}
|
||||
|
||||
void DynamicMusic::sceneCallback(void* player)
|
||||
{
|
||||
auto dat = reinterpret_cast<DynamicMusic*>(player);
|
||||
dat->m_device->lock();
|
||||
dat->m_currentHandle = dat->m_device->play(dat->m_scenes[dat->m_soundTarget][dat->m_soundTarget]);
|
||||
dat->m_currentHandle->setVolume(dat->m_volume);
|
||||
dat->m_currentHandle->setLoopCount(-1);
|
||||
dat->m_device->unlock();
|
||||
dat->m_id = int(dat->m_soundTarget);
|
||||
dat->m_soundTarget = -1;
|
||||
dat->m_transitioning = false;
|
||||
}
|
||||
|
||||
void DynamicMusic::crossfadeThread()
|
||||
{
|
||||
float currentVol = m_transitionHandle->getVolume();
|
||||
float nextVol = m_currentHandle->getVolume();
|
||||
float increment;
|
||||
|
||||
while(nextVol < m_volume && !m_stopThread)
|
||||
{
|
||||
increment = (m_volume / (m_fadeTime * 1000)) * 20;
|
||||
currentVol -= increment;
|
||||
nextVol += increment;
|
||||
if(currentVol < 0)
|
||||
currentVol = 0;
|
||||
if(nextVol > m_volume)
|
||||
nextVol = m_volume;
|
||||
m_transitionHandle->setVolume(currentVol);
|
||||
m_currentHandle->setVolume(nextVol);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
if(m_stopThread)
|
||||
m_transitionHandle->setVolume(m_volume);
|
||||
|
||||
m_transitionHandle->stop();
|
||||
|
||||
m_id = int(m_soundTarget);
|
||||
m_transitioning = false;
|
||||
}
|
||||
|
||||
void DynamicMusic::fadeInThread()
|
||||
{
|
||||
float nextVol = m_currentHandle->getVolume();
|
||||
float increment;
|
||||
|
||||
while(nextVol < m_volume && !m_stopThread)
|
||||
{
|
||||
increment = (m_volume / (m_fadeTime * 1000)) * 20;
|
||||
nextVol += increment;
|
||||
if(nextVol > m_volume)
|
||||
nextVol = m_volume;
|
||||
m_currentHandle->setVolume(nextVol);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
if(m_stopThread)
|
||||
m_currentHandle->setVolume(m_volume);
|
||||
|
||||
m_id = int(m_soundTarget);
|
||||
m_transitioning = false;
|
||||
}
|
||||
|
||||
void DynamicMusic::fadeOutThread()
|
||||
{
|
||||
float currentVol = m_transitionHandle->getVolume();
|
||||
float increment;
|
||||
|
||||
while(currentVol > 0.0f && !m_stopThread)
|
||||
{
|
||||
increment = (m_volume / (m_fadeTime * 1000)) * 20;
|
||||
currentVol -= increment;
|
||||
if(currentVol < 0)
|
||||
currentVol = 0;
|
||||
m_transitionHandle->setVolume(currentVol);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
|
||||
m_transitionHandle->stop();
|
||||
m_id = int(m_soundTarget);
|
||||
m_transitioning = false;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
17
blender-5.2.0/extern/audaspace/src/fx/Echo.cpp
vendored
Normal file
17
blender-5.2.0/extern/audaspace/src/fx/Echo.cpp
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "fx/Echo.h"
|
||||
|
||||
#include "fx/EchoReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Echo::Echo(std::shared_ptr<ISound> sound, float delay, float feedback, float mix, bool resetBuffer) :
|
||||
Effect(sound), m_delay(delay), m_feedback(feedback), m_mix(mix), m_resetBuffer(resetBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Echo::createReader()
|
||||
{
|
||||
return std::make_shared<EchoReader>(getReader(), m_delay, m_feedback, m_mix, m_resetBuffer);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
79
blender-5.2.0/extern/audaspace/src/fx/EchoReader.cpp
vendored
Normal file
79
blender-5.2.0/extern/audaspace/src/fx/EchoReader.cpp
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2025 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/EchoReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "IReader.h"
|
||||
|
||||
#include "util/Buffer.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
EchoReader::EchoReader(std::shared_ptr<IReader> reader, float delay, float feedback, float mix, bool resetBuffer) :
|
||||
EffectReader(reader), m_delay(delay), m_feedback(feedback), m_mix(mix), m_resetBuffer(resetBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
void EchoReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
auto specs = m_reader->getSpecs();
|
||||
auto delaySamples = static_cast<int>(m_delay * specs.rate);
|
||||
|
||||
m_inBuffer.assureSize(length * AUD_SAMPLE_SIZE(specs));
|
||||
|
||||
// Note: should this ever do something another time than in the beginning,
|
||||
// it will likely cause an audible glitch, as samples are not reordered
|
||||
m_delayBuffer.assureSize(delaySamples * AUD_SAMPLE_SIZE(specs));
|
||||
|
||||
m_reader->read(length, eos, m_inBuffer.getBuffer());
|
||||
|
||||
sample_t* delayBuffer = m_delayBuffer.getBuffer();
|
||||
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
for(int channel = 0; channel < specs.channels; channel++)
|
||||
{
|
||||
int delayPosition = ((m_writePosition + i) % delaySamples) * specs.channels + channel;
|
||||
|
||||
sample_t inSample = m_inBuffer.getBuffer()[i * specs.channels + channel];
|
||||
sample_t delayedSample = delayPosition < m_samplesAvailable * specs.channels ? delayBuffer[delayPosition] : 0;
|
||||
|
||||
sample_t outSample = inSample + delayedSample * m_feedback;
|
||||
buffer[i * specs.channels + channel] = inSample * (1.0f - m_mix) + outSample * m_mix;
|
||||
|
||||
// Update delay buffer with feedback
|
||||
delayBuffer[delayPosition] = outSample;
|
||||
}
|
||||
}
|
||||
|
||||
m_writePosition = (m_writePosition + length) % delaySamples;
|
||||
m_samplesAvailable = std::min(delaySamples, m_samplesAvailable + length);
|
||||
}
|
||||
|
||||
void EchoReader::seek(int position)
|
||||
{
|
||||
m_reader->seek(position);
|
||||
|
||||
if(m_resetBuffer)
|
||||
{
|
||||
m_samplesAvailable = 0;
|
||||
m_writePosition = 0;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
35
blender-5.2.0/extern/audaspace/src/fx/Effect.cpp
vendored
Normal file
35
blender-5.2.0/extern/audaspace/src/fx/Effect.cpp
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Effect.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Effect::Effect(std::shared_ptr<ISound> sound)
|
||||
{
|
||||
m_sound = sound;
|
||||
}
|
||||
|
||||
Effect::~Effect()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<ISound> Effect::getSound() const
|
||||
{
|
||||
return m_sound;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
60
blender-5.2.0/extern/audaspace/src/fx/EffectReader.cpp
vendored
Normal file
60
blender-5.2.0/extern/audaspace/src/fx/EffectReader.cpp
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/EffectReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
EffectReader::EffectReader(std::shared_ptr<IReader> reader)
|
||||
{
|
||||
m_reader = reader;
|
||||
}
|
||||
|
||||
EffectReader::~EffectReader()
|
||||
{
|
||||
}
|
||||
|
||||
bool EffectReader::isSeekable() const
|
||||
{
|
||||
return m_reader->isSeekable();
|
||||
}
|
||||
|
||||
void EffectReader::seek(int position)
|
||||
{
|
||||
m_reader->seek(position);
|
||||
}
|
||||
|
||||
int EffectReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength();
|
||||
}
|
||||
|
||||
int EffectReader::getPosition() const
|
||||
{
|
||||
return m_reader->getPosition();
|
||||
}
|
||||
|
||||
Specs EffectReader::getSpecs() const
|
||||
{
|
||||
return m_reader->getSpecs();
|
||||
}
|
||||
|
||||
void EffectReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
m_reader->read(length, eos, buffer);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
71
blender-5.2.0/extern/audaspace/src/fx/Envelope.cpp
vendored
Normal file
71
blender-5.2.0/extern/audaspace/src/fx/Envelope.cpp
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Envelope.h"
|
||||
#include "fx/CallbackIIRFilterReader.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
struct EnvelopeParameters
|
||||
{
|
||||
float attack;
|
||||
float release;
|
||||
float threshold;
|
||||
float arthreshold;
|
||||
};
|
||||
|
||||
sample_t Envelope::envelopeFilter(CallbackIIRFilterReader* reader, EnvelopeParameters* param)
|
||||
{
|
||||
float in = std::fabs(reader->x(0));
|
||||
float out = reader->y(-1);
|
||||
if(in < param->threshold)
|
||||
in = 0.0f;
|
||||
return (in > out ? param->attack : param->release) * (out - in) + in;
|
||||
}
|
||||
|
||||
void Envelope::endEnvelopeFilter(EnvelopeParameters* param)
|
||||
{
|
||||
delete param;
|
||||
}
|
||||
|
||||
Envelope::Envelope(std::shared_ptr<ISound> sound, float attack, float release, float threshold, float arthreshold) :
|
||||
Effect(sound),
|
||||
m_attack(attack),
|
||||
m_release(release),
|
||||
m_threshold(threshold),
|
||||
m_arthreshold(arthreshold)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Envelope::createReader()
|
||||
{
|
||||
std::shared_ptr<IReader> reader = getReader();
|
||||
|
||||
EnvelopeParameters* param = new EnvelopeParameters();
|
||||
param->arthreshold = m_arthreshold;
|
||||
param->attack = std::pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_attack));
|
||||
param->release = std::pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_release));
|
||||
param->threshold = m_threshold;
|
||||
|
||||
return std::shared_ptr<IReader>(new CallbackIIRFilterReader(reader, 1, 2,
|
||||
(doFilterIIR) envelopeFilter,
|
||||
(endFilterIIR) endEnvelopeFilter,
|
||||
param));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
367
blender-5.2.0/extern/audaspace/src/fx/Equalizer.cpp
vendored
Normal file
367
blender-5.2.0/extern/audaspace/src/fx/Equalizer.cpp
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2022 Marcos Perez Gonzalez
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Equalizer.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "Exception.h"
|
||||
|
||||
#include "fx/ConvolverReader.h"
|
||||
#include "fx/ImpulseResponse.h"
|
||||
#include "util/Buffer.h"
|
||||
#include "util/FFTPlan.h"
|
||||
#include "util/ThreadPool.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Equalizer::Equalizer(std::shared_ptr<ISound> sound, std::shared_ptr<Buffer> bufEQ, int externalSizeEq, float maxFreqEq, int sizeConversion) : m_sound(sound), m_bufEQ(bufEQ)
|
||||
{
|
||||
this->maxFreqEq = maxFreqEq;
|
||||
this->external_size_eq = externalSizeEq;
|
||||
|
||||
filter_length = sizeConversion;
|
||||
}
|
||||
|
||||
Equalizer::~Equalizer()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Equalizer::createReader()
|
||||
{
|
||||
std::shared_ptr<FFTPlan> fp = std::shared_ptr<FFTPlan>(new FFTPlan(filter_length));
|
||||
// 2 threads to start with
|
||||
return std::shared_ptr<ConvolverReader>(new ConvolverReader(m_sound->createReader(), createImpulseResponse(), std::shared_ptr<ThreadPool>(new ThreadPool(2)), fp));
|
||||
}
|
||||
|
||||
float calculateValueArray(float* data, float minX, float maxX, int length, float posX)
|
||||
{
|
||||
if(posX < minX)
|
||||
return 1.0;
|
||||
if(posX > maxX)
|
||||
return data[length - 1];
|
||||
float interval = (maxX - minX) / (float) length;
|
||||
int idx = (int) ((posX - minX) / interval);
|
||||
return data[idx];
|
||||
}
|
||||
|
||||
void complex_prod(float a, float b, float c, float d, float* r, float* imag)
|
||||
{
|
||||
float prod1 = a * c;
|
||||
float prod2 = b * d;
|
||||
float prod3 = (a + b) * (c + d);
|
||||
|
||||
// Real Part
|
||||
*r = prod1 - prod2;
|
||||
|
||||
// Imaginary Part
|
||||
*imag = prod3 - (prod1 + prod2);
|
||||
}
|
||||
|
||||
/**
|
||||
* The creation of the ImpuseResponse which will be convoluted with the sound
|
||||
*
|
||||
* The implementation is based on scikit-signal
|
||||
*/
|
||||
std::shared_ptr<ImpulseResponse> Equalizer::createImpulseResponse()
|
||||
{
|
||||
std::shared_ptr<FFTPlan> fp = std::shared_ptr<FFTPlan>(new FFTPlan(filter_length));
|
||||
fftwf_complex* buffer = (fftwf_complex*) fp->getBuffer();
|
||||
std::memset(buffer, 0, filter_length * sizeof(fftwf_complex));
|
||||
std::shared_ptr<IReader> soundReader = m_sound.get()->createReader();
|
||||
Specs specsSound = soundReader.get()->getSpecs();
|
||||
|
||||
int sampleRate = specsSound.rate;
|
||||
|
||||
for(unsigned i = 0; i < filter_length / 2; i++)
|
||||
{
|
||||
double freq = (((float) i) / (float) filter_length) * (float) sampleRate;
|
||||
|
||||
double dbGain = calculateValueArray(m_bufEQ->getBuffer(), 0.0, maxFreqEq, external_size_eq, freq);
|
||||
|
||||
// gain = 10^(decibels / 20.0)
|
||||
// 0 db = 1
|
||||
// 20 db = 10
|
||||
// 40 db = 100
|
||||
float gain = (float) pow(10.0, dbGain / 20.0);
|
||||
|
||||
if(i == filter_length / 2 - 1)
|
||||
{
|
||||
gain = 0;
|
||||
}
|
||||
// IMPORTANT!!!! It is needed for the minimum phase step.
|
||||
// Without this, the amplitude would be square rooted
|
||||
//
|
||||
gain *= gain;
|
||||
|
||||
// Calculation of exponential with std.. or "by hand"
|
||||
/*
|
||||
std::complex<float> preShift= std::complex<float>(0.0, -(filter_length - 1)
|
||||
/ 2. * M_PI * freq / ( sampleRate/2)); std::complex<float> shift =
|
||||
std::exp(preShift);
|
||||
|
||||
std::complex<float> cGain = gain * shift;
|
||||
*/
|
||||
|
||||
float imaginary_shift = -(filter_length - 1) / 2. * M_PI * freq / (sampleRate / 2);
|
||||
float cGain_real = gain * cos(imaginary_shift);
|
||||
float cGain_imag = gain * sin(imaginary_shift);
|
||||
|
||||
int i2 = filter_length - i - 1;
|
||||
|
||||
buffer[i][0] = cGain_real; // Real
|
||||
buffer[i][1] = cGain_imag; // Imag
|
||||
|
||||
if(i > 0 && i2 < filter_length)
|
||||
{
|
||||
buffer[i2][0] = cGain_real; // Real
|
||||
buffer[i2][1] = cGain_imag; // Imag
|
||||
}
|
||||
}
|
||||
|
||||
// In place. From Complex to sample_t
|
||||
fp->IFFT(buffer);
|
||||
|
||||
// Window Hamming
|
||||
sample_t* pt_sample_t = (sample_t*) buffer;
|
||||
float half_filter = ((float) filter_length) / 2.0;
|
||||
for(int i = 0; i < filter_length; i++)
|
||||
{
|
||||
// Centered in filter_length/2
|
||||
float window = 0.54 - 0.46 * cos((2 * M_PI * (float) i) / (float) (filter_length - 1));
|
||||
pt_sample_t[i] *= window;
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> b2 = std::shared_ptr<Buffer>(new Buffer(filter_length * sizeof(sample_t)));
|
||||
|
||||
sample_t* buffer_real = (sample_t*) buffer;
|
||||
sample_t* buffer2 = b2->getBuffer();
|
||||
float normaliziter = (float) filter_length;
|
||||
for(int i = 0; i < filter_length; i++)
|
||||
{
|
||||
buffer2[i] = (buffer_real[i] / normaliziter);
|
||||
}
|
||||
|
||||
fp->freeBuffer(buffer);
|
||||
|
||||
//
|
||||
// Here b2 is the buffer with a "valid" FIR (remember the squared amplitude
|
||||
//
|
||||
std::shared_ptr<Buffer> ir_minimum = minimumPhaseFilterHomomorphic(b2, filter_length, -1);
|
||||
|
||||
Specs specsIR;
|
||||
specsIR.rate = sampleRate;
|
||||
specsIR.channels = CHANNELS_MONO;
|
||||
|
||||
return std::shared_ptr<ImpulseResponse>(new ImpulseResponse(std::shared_ptr<StreamBuffer>(new StreamBuffer(ir_minimum, specsIR)), fp));
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> Equalizer::minimumPhaseFilterHomomorphic(std::shared_ptr<Buffer> original, int lOriginal, int lWork)
|
||||
{
|
||||
void* b_orig = original->getBuffer();
|
||||
|
||||
if(lWork < lOriginal || lWork < 0)
|
||||
{
|
||||
lWork = (int) pow(2, ceil(log2((float) (2 * (lOriginal - 1) / 0.01))));
|
||||
}
|
||||
|
||||
std::shared_ptr<FFTPlan> fp = std::shared_ptr<FFTPlan>(new FFTPlan(lWork, 0.1));
|
||||
fftwf_complex* buffer = (fftwf_complex*) fp->getBuffer();
|
||||
sample_t* b_work = (sample_t*) buffer;
|
||||
// Padding with 0
|
||||
std::memset(b_work, 0, lWork * sizeof(sample_t));
|
||||
std::memcpy(b_work, b_orig, lOriginal * sizeof(sample_t));
|
||||
|
||||
fp->FFT(b_work);
|
||||
|
||||
for(int i = 0; i < lWork / 2; i++)
|
||||
{
|
||||
buffer[i][0] = fabs(sqrt(buffer[i][0] * buffer[i][0] + buffer[i][1] * buffer[i][1]));
|
||||
buffer[i][1] = 0.0;
|
||||
int conjugate = lWork - i - 1;
|
||||
buffer[conjugate][0] = buffer[i][0];
|
||||
buffer[conjugate][1] = 0.0;
|
||||
}
|
||||
|
||||
double threshold = pow(10.0, -7);
|
||||
float logThreshold = (float) log(threshold);
|
||||
// take 0.25*log(|H|**2) = 0.5*log(|H|)
|
||||
for(int i = 0; i < lWork; i++)
|
||||
{
|
||||
if(buffer[i][0] < threshold)
|
||||
{
|
||||
buffer[i][0] = 0.5 * logThreshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[i][0] = 0.5 * log(buffer[i][0]);
|
||||
}
|
||||
}
|
||||
|
||||
fp->IFFT(buffer);
|
||||
|
||||
// homomorphic filter
|
||||
int stop = (lOriginal + 1) / 2;
|
||||
b_work[0] = b_work[0] / (float) lWork;
|
||||
for(int i = 1; i < stop; i++)
|
||||
{
|
||||
b_work[i] = b_work[i] / (float) lWork * 2.0;
|
||||
}
|
||||
for(int i = stop; i < lWork; i++)
|
||||
{
|
||||
b_work[i] = 0;
|
||||
}
|
||||
|
||||
fp->FFT(buffer);
|
||||
// EXP
|
||||
// e^x = e^ (a+bi)= e^a * e^bi = e^a * (cos b + i sin b)
|
||||
for(int i = 0; i < lWork / 2; i++)
|
||||
{
|
||||
float new_real;
|
||||
float new_imag;
|
||||
new_real = exp(buffer[i][0]) * cos(buffer[i][1]);
|
||||
new_imag = exp(buffer[i][0]) * sin(buffer[i][1]);
|
||||
|
||||
buffer[i][0] = new_real;
|
||||
buffer[i][1] = new_imag;
|
||||
int conjugate = lWork - i - 1;
|
||||
buffer[conjugate][0] = new_real;
|
||||
buffer[conjugate][1] = new_imag;
|
||||
}
|
||||
|
||||
// IFFT
|
||||
fp->IFFT(buffer);
|
||||
|
||||
// Create new clean Buffer with only the result and normalization
|
||||
int lOut = (lOriginal / 2) + lOriginal % 2;
|
||||
std::shared_ptr<Buffer> bOut = std::shared_ptr<Buffer>(new Buffer(sizeof(float) * lOut));
|
||||
float* bbOut = (float*) bOut->getBuffer();
|
||||
|
||||
// Copy and normalize
|
||||
for(int i = 0; i < lOut; i++)
|
||||
{
|
||||
bbOut[i] = b_work[i] / (float) lWork;
|
||||
}
|
||||
|
||||
fp->freeBuffer(buffer);
|
||||
return bOut;
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> Equalizer::minimumPhaseFilterHilbert(std::shared_ptr<Buffer> original, int lOriginal, int lWork)
|
||||
{
|
||||
void* b_orig = original->getBuffer();
|
||||
|
||||
if(lWork < lOriginal || lWork < 0)
|
||||
{
|
||||
lWork = (int) pow(2, ceil(log2((float) (2 * (lOriginal - 1) / 0.01))));
|
||||
}
|
||||
|
||||
std::shared_ptr<FFTPlan> fp = std::shared_ptr<FFTPlan>(new FFTPlan(lWork, 0.1));
|
||||
fftwf_complex* buffer = (fftwf_complex*) fp->getBuffer();
|
||||
sample_t* b_work = (sample_t*) buffer;
|
||||
// Padding with 0
|
||||
std::memset(b_work, 0, lWork * sizeof(sample_t));
|
||||
std::memcpy(b_work, b_orig, lOriginal * sizeof(sample_t));
|
||||
|
||||
fp->FFT(b_work);
|
||||
float mymax, mymin;
|
||||
float n_half = (float) (lOriginal >> 1);
|
||||
for(int i = 0; i < lWork; i++)
|
||||
{
|
||||
float w = ((float) i) * 2.0 * M_PI / (float) lWork * n_half;
|
||||
float f1 = cos(w);
|
||||
float f2 = sin(w);
|
||||
float f3, f4;
|
||||
complex_prod(buffer[i][0], buffer[i][1], f1, f2, &f3, &f4);
|
||||
buffer[i][0] = f3;
|
||||
buffer[i][1] = 0.0;
|
||||
if(i == 0)
|
||||
{
|
||||
mymax = f3;
|
||||
mymin = f3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(f3 < mymin)
|
||||
mymin = f3;
|
||||
if(f3 > mymax)
|
||||
mymax = f3;
|
||||
}
|
||||
}
|
||||
float dp = mymax - 1;
|
||||
float ds = 0 - mymin;
|
||||
float S = 4.0 / pow(2, (sqrt(1 + dp + ds) + sqrt(1 - dp + ds)));
|
||||
for(int i = 0; i < lWork; i++)
|
||||
{
|
||||
buffer[i][0] = sqrt((buffer[i][0] + ds) * S) + 1.0E-10;
|
||||
}
|
||||
|
||||
fftwf_complex* buffer_tmp = (fftwf_complex*) std::malloc(lWork * sizeof(fftwf_complex));
|
||||
std::memcpy(buffer_tmp, buffer, lWork * sizeof(fftwf_complex));
|
||||
|
||||
//
|
||||
// Hilbert transform
|
||||
//
|
||||
int midpt = lWork >> 1;
|
||||
for(int i = 0; i < lWork; i++)
|
||||
buffer[i][0] = log(buffer[i][0]);
|
||||
fp->IFFT(buffer);
|
||||
b_work[0] = 0.0;
|
||||
for(int i = 1; i < midpt; i++)
|
||||
{
|
||||
b_work[i] /= (float) lWork;
|
||||
}
|
||||
b_work[midpt] = 0.0;
|
||||
for(int i = midpt + 1; i < lWork; i++)
|
||||
{
|
||||
b_work[i] /= (-1.0 * lWork);
|
||||
}
|
||||
|
||||
fp->FFT(b_work);
|
||||
|
||||
// Exp
|
||||
for(int i = 0; i < lWork; i++)
|
||||
{
|
||||
float base = exp(buffer[i][0]);
|
||||
buffer[i][0] = base * cos(buffer[i][1]);
|
||||
buffer[i][1] = base * sin(buffer[i][1]);
|
||||
complex_prod(buffer_tmp[i][0], buffer_tmp[i][1], buffer[i][0], buffer[i][1], &(buffer[i][0]), &(buffer[i][1]));
|
||||
}
|
||||
std::free(buffer_tmp);
|
||||
|
||||
fp->IFFT(buffer);
|
||||
|
||||
//
|
||||
// Copy and normalization
|
||||
//
|
||||
int n_out = n_half + lOriginal % 2;
|
||||
std::shared_ptr<Buffer> b_minimum = std::shared_ptr<Buffer>(new Buffer(n_out * sizeof(sample_t)));
|
||||
std::memcpy(b_minimum->getBuffer(), buffer, n_out * sizeof(sample_t));
|
||||
sample_t* b_final = (sample_t*) b_minimum->getBuffer();
|
||||
for(int i = 0; i < n_out; i++)
|
||||
{
|
||||
b_final[i] /= (float) lWork;
|
||||
}
|
||||
return b_minimum;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
214
blender-5.2.0/extern/audaspace/src/fx/FFTConvolver.cpp
vendored
Normal file
214
blender-5.2.0/extern/audaspace/src/fx/FFTConvolver.cpp
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/FFTConvolver.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
FFTConvolver::FFTConvolver(std::shared_ptr<std::vector<std::complex<sample_t>>> ir, std::shared_ptr<FFTPlan> plan) :
|
||||
m_plan(plan), m_N(plan->getSize()), m_M(plan->getSize()/2), m_L(plan->getSize()/2), m_irBuffer(ir), m_tailPos(0)
|
||||
{
|
||||
m_tail = (float*)calloc(m_M - 1, sizeof(float));
|
||||
m_realBufLen = ((m_N / 2) + 1) * 2;
|
||||
m_inBuffer = nullptr;
|
||||
m_shiftBuffer = (sample_t*)std::calloc(m_N, sizeof(sample_t));
|
||||
}
|
||||
|
||||
FFTConvolver::~FFTConvolver()
|
||||
{
|
||||
std::free(m_tail);
|
||||
std::free(m_shiftBuffer);
|
||||
if(m_inBuffer != nullptr)
|
||||
m_plan->freeBuffer(m_inBuffer);
|
||||
}
|
||||
|
||||
void FFTConvolver::getNext(const sample_t* inBuffer, sample_t* outBuffer, int& length)
|
||||
{
|
||||
if(length > m_L || length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
if(m_inBuffer == nullptr)
|
||||
m_inBuffer = reinterpret_cast<std::complex<sample_t>*>(m_plan->getBuffer());
|
||||
|
||||
std::memset(m_inBuffer, 0, m_realBufLen * sizeof(fftwf_complex));
|
||||
std::memcpy(m_inBuffer, inBuffer, length*sizeof(sample_t));
|
||||
|
||||
m_plan->FFT(m_inBuffer);
|
||||
for(int i = 0; i < m_realBufLen / 2; i++)
|
||||
{
|
||||
m_inBuffer[i] = m_inBuffer[i] * (*m_irBuffer)[i] / sample_t(m_N);
|
||||
}
|
||||
m_plan->IFFT(m_inBuffer);
|
||||
|
||||
for(int i = 0; i < m_M - 1; i++)
|
||||
((float*)m_inBuffer)[i] += m_tail[i];
|
||||
|
||||
for(int i = 0; i < m_M - 1; i++)
|
||||
m_tail[i] = ((float*)m_inBuffer)[i + length];
|
||||
|
||||
std::memcpy(outBuffer, m_inBuffer, length * sizeof(sample_t));
|
||||
}
|
||||
|
||||
void FFTConvolver::getNext(const sample_t* inBuffer, sample_t* outBuffer, int& length, fftwf_complex* transformedData)
|
||||
{
|
||||
if(length > m_L || length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
if(m_inBuffer == nullptr)
|
||||
m_inBuffer = reinterpret_cast<std::complex<sample_t>*>(m_plan->getBuffer());
|
||||
|
||||
std::memset(m_inBuffer, 0, m_realBufLen * sizeof(fftwf_complex));
|
||||
std::memcpy(m_inBuffer, inBuffer, length*sizeof(sample_t));
|
||||
|
||||
m_plan->FFT(m_inBuffer);
|
||||
std::memcpy(transformedData, m_inBuffer, (m_realBufLen / 2)*sizeof(fftwf_complex));
|
||||
for(int i = 0; i < m_realBufLen / 2; i++)
|
||||
{
|
||||
m_inBuffer[i] = m_inBuffer[i] * (*m_irBuffer)[i] / sample_t(m_N);
|
||||
}
|
||||
m_plan->IFFT(m_inBuffer);
|
||||
|
||||
for(int i = 0; i < m_M - 1; i++)
|
||||
((float*)m_inBuffer)[i] += m_tail[i];
|
||||
|
||||
for(int i = 0; i < m_M - 1; i++)
|
||||
m_tail[i] = ((float*)m_inBuffer)[i + length];
|
||||
|
||||
std::memcpy(outBuffer, m_inBuffer, length * sizeof(sample_t));
|
||||
}
|
||||
|
||||
void FFTConvolver::getNext(const fftwf_complex* inBuffer, sample_t* outBuffer, int& length)
|
||||
{
|
||||
if(length > m_L || length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
if(m_inBuffer == nullptr)
|
||||
m_inBuffer = reinterpret_cast<std::complex<sample_t>*>(m_plan->getBuffer());
|
||||
|
||||
std::memset(m_inBuffer, 0, m_realBufLen * sizeof(fftwf_complex));
|
||||
for(int i = 0; i < m_realBufLen / 2; i++)
|
||||
{
|
||||
m_inBuffer[i] = m_inBuffer[i] * (*m_irBuffer)[i] / sample_t(m_N);
|
||||
}
|
||||
m_plan->IFFT(m_inBuffer);
|
||||
|
||||
for(int i = 0; i < m_M - 1; i++)
|
||||
((float*)m_inBuffer)[i] += m_tail[i];
|
||||
|
||||
for(int i = 0; i < m_M - 1; i++)
|
||||
m_tail[i] = ((float*)m_inBuffer)[i + length];
|
||||
|
||||
std::memcpy(outBuffer, m_inBuffer, length * sizeof(sample_t));
|
||||
}
|
||||
|
||||
void FFTConvolver::getTail(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
if(length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
eos = m_tailPos >= m_M - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
eos = false;
|
||||
if(m_tailPos + length > m_M - 1)
|
||||
{
|
||||
length = m_M - 1 - m_tailPos;
|
||||
if(length < 0)
|
||||
length = 0;
|
||||
eos = true;
|
||||
m_tailPos = m_M - 1;
|
||||
}
|
||||
else
|
||||
m_tailPos += length;
|
||||
std::memcpy(buffer, m_tail, length*sizeof(sample_t));
|
||||
}
|
||||
|
||||
void FFTConvolver::clear()
|
||||
{
|
||||
std::memset(m_shiftBuffer, 0, m_N * sizeof(sample_t));
|
||||
std::memset(m_tail, 0, m_M - 1);
|
||||
}
|
||||
|
||||
void FFTConvolver::IFFT_FDL(const fftwf_complex* inBuffer, sample_t* outBuffer, int& length)
|
||||
{
|
||||
if(length > m_L || length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
if(m_inBuffer == nullptr)
|
||||
m_inBuffer = reinterpret_cast<std::complex<sample_t>*>(m_plan->getBuffer());
|
||||
|
||||
std::memset(m_inBuffer, 0, m_realBufLen * sizeof(fftwf_complex));
|
||||
std::memcpy(m_inBuffer, inBuffer, (m_realBufLen / 2)*sizeof(fftwf_complex));
|
||||
m_plan->IFFT(m_inBuffer);
|
||||
std::memcpy(outBuffer, ((sample_t*)m_inBuffer)+m_L, length*sizeof(sample_t));
|
||||
}
|
||||
|
||||
void FFTConvolver::getNextFDL(const std::complex<sample_t>* inBuffer, std::complex<sample_t>* accBuffer)
|
||||
{
|
||||
for(int i = 0; i < m_realBufLen / 2; i++)
|
||||
{
|
||||
accBuffer[i] += (inBuffer[i] * (*m_irBuffer)[i]) / sample_t(m_N);
|
||||
}
|
||||
}
|
||||
|
||||
void FFTConvolver::getNextFDL(const sample_t* inBuffer, std::complex<sample_t>* accBuffer, int& length, fftwf_complex* transformedData)
|
||||
{
|
||||
if(length > m_L || length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
if(m_inBuffer == nullptr)
|
||||
m_inBuffer = reinterpret_cast<std::complex<sample_t>*>(m_plan->getBuffer());
|
||||
|
||||
std::memcpy(m_shiftBuffer, m_shiftBuffer + m_L, m_L*sizeof(sample_t));
|
||||
std::memcpy(m_shiftBuffer + m_L, inBuffer, length*sizeof(sample_t));
|
||||
|
||||
std::memset(m_inBuffer, 0, m_realBufLen * sizeof(fftwf_complex));
|
||||
std::memcpy(m_inBuffer, m_shiftBuffer, (m_L+length)*sizeof(sample_t));
|
||||
|
||||
m_plan->FFT(m_inBuffer);
|
||||
std::memcpy(transformedData, m_inBuffer, (m_realBufLen / 2)*sizeof(fftwf_complex));
|
||||
for(int i = 0; i < m_realBufLen / 2; i++)
|
||||
{
|
||||
accBuffer[i] += (m_inBuffer[i] * (*m_irBuffer)[i]) / sample_t(m_N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FFTConvolver::setImpulseResponse(std::shared_ptr<std::vector<std::complex<sample_t>>> ir)
|
||||
{
|
||||
clear();
|
||||
m_irBuffer = ir;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::complex<sample_t>>> FFTConvolver::getImpulseResponse()
|
||||
{
|
||||
return m_irBuffer;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
49
blender-5.2.0/extern/audaspace/src/fx/Fader.cpp
vendored
Normal file
49
blender-5.2.0/extern/audaspace/src/fx/Fader.cpp
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Fader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Fader::Fader(std::shared_ptr<ISound> sound, FadeType type, double start, double length) :
|
||||
Effect(sound),
|
||||
m_type(type),
|
||||
m_start(start),
|
||||
m_length(length)
|
||||
{
|
||||
}
|
||||
|
||||
FadeType Fader::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
double Fader::getStart() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
double Fader::getLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Fader::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new FaderReader(getReader(), m_type, m_start, m_length));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
76
blender-5.2.0/extern/audaspace/src/fx/FaderReader.cpp
vendored
Normal file
76
blender-5.2.0/extern/audaspace/src/fx/FaderReader.cpp
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/FaderReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
FaderReader::FaderReader(std::shared_ptr<IReader> reader, FadeType type, double start, double length) :
|
||||
EffectReader(reader),
|
||||
m_type(type),
|
||||
m_start(start),
|
||||
m_length(length)
|
||||
{
|
||||
}
|
||||
|
||||
void FaderReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
int position = m_reader->getPosition();
|
||||
Specs specs = m_reader->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
m_reader->read(length, eos, buffer);
|
||||
|
||||
if((position + length) / specs.rate <= m_start)
|
||||
{
|
||||
if(m_type != FADE_OUT)
|
||||
{
|
||||
std::memset(buffer, 0, length * samplesize);
|
||||
}
|
||||
}
|
||||
else if(position / specs.rate >= m_start+m_length)
|
||||
{
|
||||
if(m_type == FADE_OUT)
|
||||
{
|
||||
std::memset(buffer, 0, length * samplesize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float volume = 1.0f;
|
||||
|
||||
for(int i = 0; i < length * specs.channels; i++)
|
||||
{
|
||||
if(i % specs.channels == 0)
|
||||
{
|
||||
volume = float((((position + i) / specs.rate) - m_start) / m_length);
|
||||
if(volume > 1.0f)
|
||||
volume = 1.0f;
|
||||
else if(volume < 0.0f)
|
||||
volume = 0.0f;
|
||||
|
||||
if(m_type == FADE_OUT)
|
||||
volume = 1.0f - volume;
|
||||
}
|
||||
|
||||
buffer[i] = buffer[i] * volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
122
blender-5.2.0/extern/audaspace/src/fx/HRTF.cpp
vendored
Normal file
122
blender-5.2.0/extern/audaspace/src/fx/HRTF.cpp
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/HRTF.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
HRTF::HRTF() :
|
||||
HRTF(std::make_shared<FFTPlan>(0.0))
|
||||
{
|
||||
}
|
||||
|
||||
HRTF::HRTF(std::shared_ptr<FFTPlan> plan) :
|
||||
m_plan(plan)
|
||||
{
|
||||
m_specs.channels = CHANNELS_INVALID;
|
||||
m_specs.rate = 0;
|
||||
m_empty = true;
|
||||
}
|
||||
|
||||
bool HRTF::addImpulseResponse(std::shared_ptr<StreamBuffer> impulseResponse, float azimuth, float elevation)
|
||||
{
|
||||
Specs spec = impulseResponse->getSpecs();
|
||||
|
||||
azimuth = std::fmod(azimuth, 360);
|
||||
if(azimuth < 0)
|
||||
azimuth += 360;
|
||||
|
||||
if((spec.channels != CHANNELS_MONO) || (spec.rate != m_specs.rate && m_specs.rate > 0.0))
|
||||
return false;
|
||||
|
||||
m_hrtfs[elevation][azimuth] = std::make_shared<ImpulseResponse>(impulseResponse, m_plan);
|
||||
m_specs.channels = CHANNELS_MONO;
|
||||
m_specs.rate = spec.rate;
|
||||
m_empty = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<ImpulseResponse>, std::shared_ptr<ImpulseResponse>> HRTF::getImpulseResponse(float &azimuth, float &elevation)
|
||||
{
|
||||
if(m_hrtfs.empty())
|
||||
return std::make_pair(nullptr, nullptr);
|
||||
azimuth = std::fmod(azimuth, 360);
|
||||
if(azimuth < 0)
|
||||
azimuth += 360;
|
||||
|
||||
std::shared_ptr<ImpulseResponse> R, L;
|
||||
float az = 0, el = 0, dif=0, minDif=360;
|
||||
|
||||
for(auto elem : m_hrtfs)
|
||||
{
|
||||
dif = std::fabs(elevation - elem.first);
|
||||
if(dif < minDif)
|
||||
{
|
||||
minDif = dif;
|
||||
el = elem.first;
|
||||
}
|
||||
}
|
||||
elevation = el;
|
||||
dif = 0;
|
||||
minDif = 360;
|
||||
|
||||
for(auto elem : m_hrtfs[elevation])
|
||||
{
|
||||
dif = std::fabs(azimuth - elem.first);
|
||||
if(dif < minDif)
|
||||
{
|
||||
minDif = dif;
|
||||
az = elem.first;
|
||||
R = elem.second;
|
||||
}
|
||||
}
|
||||
azimuth = az;
|
||||
float azL = 360 - azimuth;
|
||||
if(azL == 360)
|
||||
azL = 0;
|
||||
|
||||
auto iter = m_hrtfs[elevation].find(azL);
|
||||
if(iter != m_hrtfs[elevation].end())
|
||||
L = iter->second;
|
||||
else
|
||||
{
|
||||
dif = 0;
|
||||
minDif = 360;
|
||||
for(auto elem : m_hrtfs[elevation])
|
||||
{
|
||||
dif = std::fabs(azL - elem.first);
|
||||
if(dif < minDif)
|
||||
{
|
||||
minDif = dif;
|
||||
L = elem.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_pair(L, R);
|
||||
}
|
||||
|
||||
Specs HRTF::getSpecs()
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
bool HRTF::isEmpty()
|
||||
{
|
||||
return m_empty;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
89
blender-5.2.0/extern/audaspace/src/fx/HRTFLoaderUnix.cpp
vendored
Normal file
89
blender-5.2.0/extern/audaspace/src/fx/HRTFLoaderUnix.cpp
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/HRTFLoader.h"
|
||||
#include "file/File.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <exception>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
std::shared_ptr<HRTF> HRTFLoader::loadLeftHRTFs(std::shared_ptr<FFTPlan> plan, const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::shared_ptr<HRTF> hrtfs(std::make_shared<HRTF>(plan));
|
||||
loadHRTFs(hrtfs, 'L', fileExtension, path);
|
||||
return hrtfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<HRTF> HRTFLoader::loadRightHRTFs(std::shared_ptr<FFTPlan> plan, const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::shared_ptr<HRTF> hrtfs(std::make_shared<HRTF>(plan));
|
||||
loadHRTFs(hrtfs, 'R', fileExtension, path);
|
||||
return hrtfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<HRTF> HRTFLoader::loadLeftHRTFs(const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::shared_ptr<HRTF> hrtfs(std::make_shared<HRTF>());
|
||||
loadHRTFs(hrtfs, 'L', fileExtension, path);
|
||||
return hrtfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<HRTF> HRTFLoader::loadRightHRTFs(const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::shared_ptr<HRTF> hrtfs(std::make_shared<HRTF>());
|
||||
loadHRTFs(hrtfs, 'R', fileExtension, path);
|
||||
return hrtfs;
|
||||
}
|
||||
|
||||
void HRTFLoader::loadHRTFs(std::shared_ptr<HRTF> hrtfs, char ear, const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::string readpath = path;
|
||||
if(path == "")
|
||||
readpath = ".";
|
||||
|
||||
DIR* dir = opendir(path.c_str());
|
||||
if(!dir)
|
||||
return;
|
||||
|
||||
float azim, elev;
|
||||
|
||||
while(dirent* entry = readdir(dir))
|
||||
{
|
||||
std::string filename = entry->d_name;
|
||||
if(filename.front() == ear && filename.length() >= fileExtension.length() && filename.substr(filename.length() - fileExtension.length()) == fileExtension)
|
||||
{
|
||||
try
|
||||
{
|
||||
elev = std::stof(filename.substr(1, filename.find("e") - 1));
|
||||
azim = std::stof(filename.substr(filename.find("e") + 1, filename.find("a") - filename.find("e") - 1));
|
||||
if(ear == 'L')
|
||||
azim = 360 - azim;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
AUD_THROW(FileException, "The HRTF name doesn't follow the naming scheme: " + filename);
|
||||
}
|
||||
hrtfs->addImpulseResponse(std::make_shared<StreamBuffer>(std::make_shared<File>(readpath + "/" + filename)), azim, elev);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
93
blender-5.2.0/extern/audaspace/src/fx/HRTFLoaderWindows.cpp
vendored
Normal file
93
blender-5.2.0/extern/audaspace/src/fx/HRTFLoaderWindows.cpp
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/HRTFLoader.h"
|
||||
#include "file/File.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <exception>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
std::shared_ptr<HRTF> HRTFLoader::loadLeftHRTFs(std::shared_ptr<FFTPlan> plan, const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::shared_ptr<HRTF> hrtfs(std::make_shared<HRTF>(plan));
|
||||
loadHRTFs(hrtfs, 'L', fileExtension, path);
|
||||
return hrtfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<HRTF> HRTFLoader::loadRightHRTFs(std::shared_ptr<FFTPlan> plan, const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::shared_ptr<HRTF> hrtfs(std::make_shared<HRTF>(plan));
|
||||
loadHRTFs(hrtfs, 'R', fileExtension, path);
|
||||
return hrtfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<HRTF> HRTFLoader::loadLeftHRTFs(const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::shared_ptr<HRTF> hrtfs(std::make_shared<HRTF>());
|
||||
loadHRTFs(hrtfs, 'L', fileExtension, path);
|
||||
return hrtfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<HRTF> HRTFLoader::loadRightHRTFs(const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::shared_ptr<HRTF> hrtfs(std::make_shared<HRTF>());
|
||||
loadHRTFs(hrtfs, 'R', fileExtension, path);
|
||||
return hrtfs;
|
||||
}
|
||||
|
||||
void HRTFLoader::loadHRTFs(std::shared_ptr<HRTF> hrtfs, char ear, const std::string& fileExtension, const std::string& path)
|
||||
{
|
||||
std::string readpath = path;
|
||||
if(path == "")
|
||||
readpath = ".";
|
||||
|
||||
WIN32_FIND_DATA entry;
|
||||
bool found_file = true;
|
||||
std::string search = readpath + "\\*";
|
||||
HANDLE dir = FindFirstFile(search.c_str(), &entry);
|
||||
if(dir == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
float azim, elev;
|
||||
|
||||
while(found_file)
|
||||
{
|
||||
std::string filename = entry.cFileName;
|
||||
if(filename.front() == ear && filename.length() >= fileExtension.length() && filename.substr(filename.length() - fileExtension.length()) == fileExtension)
|
||||
{
|
||||
try
|
||||
{
|
||||
elev = std::stof(filename.substr(1, filename.find("e") - 1));
|
||||
azim = std::stof(filename.substr(filename.find("e") + 1, filename.find("a") - filename.find("e") - 1));
|
||||
if(ear == 'L')
|
||||
azim = 360 - azim;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
AUD_THROW(FileException, "The HRTF name doesn't follow the naming scheme: " + filename);
|
||||
}
|
||||
hrtfs->addImpulseResponse(std::make_shared<StreamBuffer>(std::make_shared<File>(readpath + "/" + filename)), azim, elev);
|
||||
}
|
||||
found_file = FindNextFile(dir, &entry);
|
||||
}
|
||||
FindClose(dir);
|
||||
return;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
28
blender-5.2.0/extern/audaspace/src/fx/Highpass.cpp
vendored
Normal file
28
blender-5.2.0/extern/audaspace/src/fx/Highpass.cpp
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Highpass.h"
|
||||
#include "fx/IIRFilterReader.h"
|
||||
#include "fx/HighpassCalculator.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Highpass::Highpass(std::shared_ptr<ISound> sound, float frequency, float Q) :
|
||||
DynamicIIRFilter(sound, std::shared_ptr<IDynamicIIRFilterCalculator>(new HighpassCalculator(frequency, Q)))
|
||||
{
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
43
blender-5.2.0/extern/audaspace/src/fx/HighpassCalculator.cpp
vendored
Normal file
43
blender-5.2.0/extern/audaspace/src/fx/HighpassCalculator.cpp
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/HighpassCalculator.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
HighpassCalculator::HighpassCalculator(float frequency, float Q) :
|
||||
m_frequency(frequency),
|
||||
m_Q(Q)
|
||||
{
|
||||
}
|
||||
|
||||
void HighpassCalculator::recalculateCoefficients(SampleRate rate, std::vector<float> &b, std::vector<float> &a)
|
||||
{
|
||||
float w0 = 2.0 * M_PI * (SampleRate)m_frequency / rate;
|
||||
float alpha = (float)(std::sin(w0) / (2.0 * (double)m_Q));
|
||||
float norm = 1 + alpha;
|
||||
float c = std::cos(w0);
|
||||
a.push_back(1);
|
||||
a.push_back(-2 * c / norm);
|
||||
a.push_back((1 - alpha) / norm);
|
||||
b.push_back((1 + c) / (2 * norm));
|
||||
b.push_back((-1 - c) / norm);
|
||||
b.push_back(b[0]);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
32
blender-5.2.0/extern/audaspace/src/fx/IIRFilter.cpp
vendored
Normal file
32
blender-5.2.0/extern/audaspace/src/fx/IIRFilter.cpp
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/IIRFilter.h"
|
||||
#include "fx/IIRFilterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
IIRFilter::IIRFilter(std::shared_ptr<ISound> sound, const std::vector<float>& b, const std::vector<float>& a) :
|
||||
Effect(sound), m_a(a), m_b(b)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> IIRFilter::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new IIRFilterReader(getReader(), m_b, m_a));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
53
blender-5.2.0/extern/audaspace/src/fx/IIRFilterReader.cpp
vendored
Normal file
53
blender-5.2.0/extern/audaspace/src/fx/IIRFilterReader.cpp
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/IIRFilterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
IIRFilterReader::IIRFilterReader(std::shared_ptr<IReader> reader, const std::vector<float>& b, const std::vector<float>& a) :
|
||||
BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b)
|
||||
{
|
||||
if(m_a.empty() == false)
|
||||
{
|
||||
for(int i = 1; i < m_a.size(); i++)
|
||||
m_a[i] /= m_a[0];
|
||||
for(int i = 0; i < m_b.size(); i++)
|
||||
m_b[i] /= m_a[0];
|
||||
m_a[0] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sample_t IIRFilterReader::filter()
|
||||
{
|
||||
sample_t out = 0;
|
||||
|
||||
for(int i = 1; i < m_a.size(); i++)
|
||||
out -= y(-i) * m_a[i];
|
||||
for(int i = 0; i < m_b.size(); i++)
|
||||
out += x(-i) * m_b[i];
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void IIRFilterReader::setCoefficients(const std::vector<float>& b, const std::vector<float>& a)
|
||||
{
|
||||
setLengths(b.size(), a.size());
|
||||
m_a = a;
|
||||
m_b = b;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
97
blender-5.2.0/extern/audaspace/src/fx/ImpulseResponse.cpp
vendored
Normal file
97
blender-5.2.0/extern/audaspace/src/fx/ImpulseResponse.cpp
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/ImpulseResponse.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
ImpulseResponse::ImpulseResponse(std::shared_ptr<StreamBuffer> impulseResponse) :
|
||||
ImpulseResponse(impulseResponse, std::make_shared<FFTPlan>(0.0))
|
||||
{
|
||||
}
|
||||
|
||||
ImpulseResponse::ImpulseResponse(std::shared_ptr<StreamBuffer> impulseResponse, std::shared_ptr<FFTPlan> plan)
|
||||
{
|
||||
auto reader = impulseResponse->createReader();
|
||||
m_length = reader->getLength();
|
||||
processImpulseResponse(impulseResponse->createReader(), plan);
|
||||
}
|
||||
|
||||
Specs ImpulseResponse::getSpecs()
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
int ImpulseResponse::getLength()
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::shared_ptr<std::vector<std::complex<sample_t>>>>> ImpulseResponse::getChannel(int n)
|
||||
{
|
||||
return m_processedIR[n];
|
||||
}
|
||||
|
||||
void ImpulseResponse::processImpulseResponse(std::shared_ptr<IReader> reader, std::shared_ptr<FFTPlan> plan)
|
||||
{
|
||||
m_specs.channels = reader->getSpecs().channels;
|
||||
m_specs.rate = reader->getSpecs().rate;
|
||||
int N = plan->getSize();
|
||||
bool eos = false;
|
||||
int length = reader->getLength();
|
||||
sample_t* buffer = (sample_t*)std::malloc(length * m_specs.channels * sizeof(sample_t));
|
||||
int numParts = std::ceil((float)length / (plan->getSize() / 2));
|
||||
|
||||
for(int i = 0; i < m_specs.channels; i++)
|
||||
{
|
||||
m_processedIR.push_back(std::make_shared<std::vector<std::shared_ptr<std::vector<std::complex<sample_t>>>>>());
|
||||
for(int j = 0; j < numParts; j++)
|
||||
(*m_processedIR[i]).push_back(std::make_shared<std::vector<std::complex<sample_t>>>((N / 2) + 1));
|
||||
}
|
||||
length += reader->getSpecs().rate;
|
||||
reader->read(length, eos, buffer);
|
||||
|
||||
|
||||
void* bufferFFT = plan->getBuffer();
|
||||
for(int i = 0; i < m_specs.channels; i++)
|
||||
{
|
||||
int partStart = 0;
|
||||
for(int h = 0; h < numParts; h++)
|
||||
{
|
||||
int k = 0;
|
||||
int len = std::min(partStart + ((N / 2)*m_specs.channels), length*m_specs.channels);
|
||||
std::memset(bufferFFT, 0, ((N / 2) + 1) * 2 * sizeof(fftwf_complex));
|
||||
for(int j = partStart; j < len; j += m_specs.channels)
|
||||
{
|
||||
((float*)bufferFFT)[k] = buffer[j + i];
|
||||
k++;
|
||||
}
|
||||
plan->FFT(bufferFFT);
|
||||
for(int j = 0; j < (N / 2) + 1; j++)
|
||||
{
|
||||
(*(*m_processedIR[i])[h])[j] = reinterpret_cast<std::complex<sample_t>*>(bufferFFT)[j];
|
||||
}
|
||||
partStart += N / 2 * m_specs.channels;
|
||||
}
|
||||
}
|
||||
plan->freeBuffer(bufferFFT);
|
||||
std::free(buffer);
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
45
blender-5.2.0/extern/audaspace/src/fx/Limiter.cpp
vendored
Normal file
45
blender-5.2.0/extern/audaspace/src/fx/Limiter.cpp
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Limiter.h"
|
||||
#include "fx/LimiterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Limiter::Limiter(std::shared_ptr<ISound> sound,
|
||||
double start, double end) :
|
||||
Effect(sound),
|
||||
m_start(start),
|
||||
m_end(end)
|
||||
{
|
||||
}
|
||||
|
||||
double Limiter::getStart() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
double Limiter::getEnd() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Limiter::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new LimiterReader(getReader(), m_start, m_end));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
139
blender-5.2.0/extern/audaspace/src/fx/LimiterReader.cpp
vendored
Normal file
139
blender-5.2.0/extern/audaspace/src/fx/LimiterReader.cpp
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/LimiterReader.h"
|
||||
#include "util/Buffer.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
LimiterReader::LimiterReader(std::shared_ptr<IReader> reader, double start, double end) :
|
||||
EffectReader(reader),
|
||||
m_start(start),
|
||||
m_end(end)
|
||||
{
|
||||
if(m_start > 0)
|
||||
{
|
||||
Specs specs = m_reader->getSpecs();
|
||||
Specs specs2;
|
||||
|
||||
if(m_reader->isSeekable())
|
||||
m_reader->seek(m_start * specs.rate);
|
||||
else
|
||||
{
|
||||
// skip first m_start samples by reading them
|
||||
int length = AUD_DEFAULT_BUFFER_SIZE;
|
||||
Buffer buffer(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs));
|
||||
bool eos = false;
|
||||
for(int len = m_start * specs.rate;
|
||||
length > 0 && !eos;
|
||||
len -= length)
|
||||
{
|
||||
if(len < AUD_DEFAULT_BUFFER_SIZE)
|
||||
length = len;
|
||||
|
||||
m_reader->read(length, eos, buffer.getBuffer());
|
||||
|
||||
specs2 = m_reader->getSpecs();
|
||||
if(specs2.rate != specs.rate)
|
||||
{
|
||||
len = len * specs2.rate / specs.rate;
|
||||
specs.rate = specs2.rate;
|
||||
}
|
||||
|
||||
if(specs2.channels != specs.channels)
|
||||
{
|
||||
specs = specs2;
|
||||
buffer.assureSize(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LimiterReader::seek(int position)
|
||||
{
|
||||
m_reader->seek(position + m_start * m_reader->getSpecs().rate);
|
||||
}
|
||||
|
||||
int LimiterReader::getLength() const
|
||||
{
|
||||
int len = m_reader->getLength();
|
||||
SampleRate rate = m_reader->getSpecs().rate;
|
||||
if(len < 0 || (len > m_end * rate && m_end >= 0))
|
||||
len = m_end * rate;
|
||||
return len - m_start * rate;
|
||||
}
|
||||
|
||||
int LimiterReader::getPosition() const
|
||||
{
|
||||
int pos = m_reader->getPosition();
|
||||
SampleRate rate = m_reader->getSpecs().rate;
|
||||
return std::min(pos, int(m_end * rate)) - m_start * rate;
|
||||
}
|
||||
|
||||
void LimiterReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
eos = false;
|
||||
if(m_end >= 0)
|
||||
{
|
||||
int position = m_reader->getPosition();
|
||||
SampleRate rate = m_reader->getSpecs().rate;
|
||||
|
||||
if(position + length > m_end * rate)
|
||||
{
|
||||
length = m_end * rate - position;
|
||||
eos = true;
|
||||
}
|
||||
|
||||
if(position < int(m_start * rate))
|
||||
{
|
||||
int len2 = length;
|
||||
for(int len = int(m_start * rate) - position;
|
||||
len2 == length && !eos;
|
||||
len -= length)
|
||||
{
|
||||
if(len < length)
|
||||
len2 = len;
|
||||
|
||||
m_reader->read(len2, eos, buffer);
|
||||
position += len2;
|
||||
}
|
||||
|
||||
if(position < m_start * rate)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(length < 0)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(eos)
|
||||
{
|
||||
m_reader->read(length, eos, buffer);
|
||||
eos = true;
|
||||
}
|
||||
else
|
||||
m_reader->read(length, eos, buffer);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
38
blender-5.2.0/extern/audaspace/src/fx/Loop.cpp
vendored
Normal file
38
blender-5.2.0/extern/audaspace/src/fx/Loop.cpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Loop.h"
|
||||
#include "fx/LoopReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Loop::Loop(std::shared_ptr<ISound> sound, int loop) :
|
||||
Effect(sound),
|
||||
m_loop(loop)
|
||||
{
|
||||
}
|
||||
|
||||
int Loop::getLoop() const
|
||||
{
|
||||
return m_loop;
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Loop::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new LoopReader(getReader(), m_loop));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
91
blender-5.2.0/extern/audaspace/src/fx/LoopReader.cpp
vendored
Normal file
91
blender-5.2.0/extern/audaspace/src/fx/LoopReader.cpp
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/LoopReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
LoopReader::LoopReader(std::shared_ptr<IReader> reader, int loop) :
|
||||
EffectReader(reader), m_count(loop), m_left(loop)
|
||||
{
|
||||
}
|
||||
|
||||
void LoopReader::seek(int position)
|
||||
{
|
||||
int len = m_reader->getLength();
|
||||
if(len < 0)
|
||||
m_reader->seek(position);
|
||||
else
|
||||
{
|
||||
if(m_count >= 0)
|
||||
{
|
||||
m_left = m_count - (position / len);
|
||||
if(m_left < 0)
|
||||
m_left = 0;
|
||||
}
|
||||
m_reader->seek(position % len);
|
||||
}
|
||||
}
|
||||
|
||||
int LoopReader::getLength() const
|
||||
{
|
||||
if(m_count < 0)
|
||||
return -1;
|
||||
return m_reader->getLength() * m_count;
|
||||
}
|
||||
|
||||
int LoopReader::getPosition() const
|
||||
{
|
||||
return m_reader->getPosition() * (m_count < 0 ? 1 : m_count);
|
||||
}
|
||||
|
||||
void LoopReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
const Specs specs = m_reader->getSpecs();
|
||||
|
||||
int len = length;
|
||||
|
||||
m_reader->read(length, eos, buffer);
|
||||
|
||||
if(length < len && eos && m_left)
|
||||
{
|
||||
int pos = length;
|
||||
length = len;
|
||||
|
||||
while(pos < length && eos && m_left)
|
||||
{
|
||||
if(m_left > 0)
|
||||
m_left--;
|
||||
|
||||
m_reader->seek(0);
|
||||
|
||||
len = length - pos;
|
||||
m_reader->read(len, eos, buffer + pos * specs.channels);
|
||||
|
||||
// prevent endless loop
|
||||
if(!len)
|
||||
break;
|
||||
|
||||
pos += len;
|
||||
}
|
||||
|
||||
length = pos;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
27
blender-5.2.0/extern/audaspace/src/fx/Lowpass.cpp
vendored
Normal file
27
blender-5.2.0/extern/audaspace/src/fx/Lowpass.cpp
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Lowpass.h"
|
||||
#include "fx/LowpassCalculator.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Lowpass::Lowpass(std::shared_ptr<ISound> sound, float frequency, float Q) :
|
||||
DynamicIIRFilter(sound, std::shared_ptr<IDynamicIIRFilterCalculator>(new LowpassCalculator(frequency, Q)))
|
||||
{
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
43
blender-5.2.0/extern/audaspace/src/fx/LowpassCalculator.cpp
vendored
Normal file
43
blender-5.2.0/extern/audaspace/src/fx/LowpassCalculator.cpp
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/LowpassCalculator.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
LowpassCalculator::LowpassCalculator(float frequency, float Q) :
|
||||
m_frequency(frequency),
|
||||
m_Q(Q)
|
||||
{
|
||||
}
|
||||
|
||||
void LowpassCalculator::recalculateCoefficients(SampleRate rate, std::vector<float> &b, std::vector<float> &a)
|
||||
{
|
||||
float w0 = 2 * M_PI * m_frequency / rate;
|
||||
float alpha = std::sin(w0) / (2 * m_Q);
|
||||
float norm = 1 + alpha;
|
||||
float c = std::cos(w0);
|
||||
a.push_back(1);
|
||||
a.push_back(-2 * c / norm);
|
||||
a.push_back((1 - alpha) / norm);
|
||||
b.push_back((1 - c) / (2 * norm));
|
||||
b.push_back((1 - c) / norm);
|
||||
b.push_back(b[0]);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
35
blender-5.2.0/extern/audaspace/src/fx/Modulator.cpp
vendored
Normal file
35
blender-5.2.0/extern/audaspace/src/fx/Modulator.cpp
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Modulator.h"
|
||||
#include "fx/ModulatorReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Modulator::Modulator(std::shared_ptr<ISound> sound1, std::shared_ptr<ISound> sound2) :
|
||||
m_sound1(sound1), m_sound2(sound2)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Modulator::createReader()
|
||||
{
|
||||
std::shared_ptr<IReader> reader1 = m_sound1->createReader();
|
||||
std::shared_ptr<IReader> reader2 = m_sound2->createReader();
|
||||
|
||||
return std::shared_ptr<IReader>(new ModulatorReader(reader1, reader2));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
95
blender-5.2.0/extern/audaspace/src/fx/ModulatorReader.cpp
vendored
Normal file
95
blender-5.2.0/extern/audaspace/src/fx/ModulatorReader.cpp
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/ModulatorReader.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
ModulatorReader::ModulatorReader(std::shared_ptr<IReader> reader1, std::shared_ptr<IReader> reader2) :
|
||||
m_reader1(reader1), m_reader2(reader2)
|
||||
{
|
||||
}
|
||||
|
||||
ModulatorReader::~ModulatorReader()
|
||||
{
|
||||
}
|
||||
|
||||
bool ModulatorReader::isSeekable() const
|
||||
{
|
||||
return m_reader1->isSeekable() && m_reader2->isSeekable();
|
||||
}
|
||||
|
||||
void ModulatorReader::seek(int position)
|
||||
{
|
||||
m_reader1->seek(position);
|
||||
m_reader2->seek(position);
|
||||
}
|
||||
|
||||
int ModulatorReader::getLength() const
|
||||
{
|
||||
int len1 = m_reader1->getLength();
|
||||
int len2 = m_reader2->getLength();
|
||||
if((len1 < 0) || (len2 < 0))
|
||||
return -1;
|
||||
return std::max(len1, len2);
|
||||
}
|
||||
|
||||
int ModulatorReader::getPosition() const
|
||||
{
|
||||
int pos1 = m_reader1->getPosition();
|
||||
int pos2 = m_reader2->getPosition();
|
||||
return std::max(pos1, pos2);
|
||||
}
|
||||
|
||||
Specs ModulatorReader::getSpecs() const
|
||||
{
|
||||
return m_reader1->getSpecs();
|
||||
}
|
||||
|
||||
void ModulatorReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
Specs specs = m_reader1->getSpecs();
|
||||
Specs s2 = m_reader2->getSpecs();
|
||||
if(!AUD_COMPARE_SPECS(specs, s2))
|
||||
AUD_THROW(StateException, "Two readers with different specifiactions cannot be modulated.");
|
||||
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
m_buffer.assureSize(length * samplesize);
|
||||
|
||||
int len1 = length;
|
||||
m_reader1->read(len1, eos, buffer);
|
||||
|
||||
if(len1 < length)
|
||||
std::memset(buffer + len1 * specs.channels, 0, (length - len1) * samplesize);
|
||||
|
||||
int len2 = length;
|
||||
bool eos2;
|
||||
sample_t* buf = m_buffer.getBuffer();
|
||||
m_reader2->read(len2, eos2, buf);
|
||||
|
||||
for(int i = 0; i < len2 * specs.channels; i++)
|
||||
buffer[i] *= buf[i];
|
||||
|
||||
length = std::max(len1, len2);
|
||||
eos &= eos2;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
64
blender-5.2.0/extern/audaspace/src/fx/MutableReader.cpp
vendored
Normal file
64
blender-5.2.0/extern/audaspace/src/fx/MutableReader.cpp
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/MutableReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
MutableReader::MutableReader(std::shared_ptr<ISound> sound) :
|
||||
m_sound(sound)
|
||||
{
|
||||
m_reader = m_sound->createReader();
|
||||
}
|
||||
|
||||
bool MutableReader::isSeekable() const
|
||||
{
|
||||
return m_reader->isSeekable();
|
||||
}
|
||||
|
||||
void MutableReader::seek(int position)
|
||||
{
|
||||
if(position < m_reader->getPosition())
|
||||
{
|
||||
m_reader = m_sound->createReader();
|
||||
}
|
||||
else
|
||||
m_reader->seek(position);
|
||||
}
|
||||
|
||||
int MutableReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength();
|
||||
}
|
||||
|
||||
int MutableReader::getPosition() const
|
||||
{
|
||||
return m_reader->getPosition();
|
||||
}
|
||||
|
||||
Specs MutableReader::getSpecs() const
|
||||
{
|
||||
return m_reader->getSpecs();
|
||||
}
|
||||
|
||||
void MutableReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
m_reader->read(length, eos, buffer);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
35
blender-5.2.0/extern/audaspace/src/fx/MutableSound.cpp
vendored
Normal file
35
blender-5.2.0/extern/audaspace/src/fx/MutableSound.cpp
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/MutableSound.h"
|
||||
#include "fx/MutableReader.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
MutableSound::MutableSound(std::shared_ptr<ISound> sound) :
|
||||
m_sound(sound)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> MutableSound::createReader()
|
||||
{
|
||||
return std::make_shared<MutableReader>(m_sound);
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
33
blender-5.2.0/extern/audaspace/src/fx/Pitch.cpp
vendored
Normal file
33
blender-5.2.0/extern/audaspace/src/fx/Pitch.cpp
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Pitch.h"
|
||||
#include "fx/PitchReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Pitch::Pitch(std::shared_ptr<ISound> sound, float pitch) :
|
||||
Effect(sound),
|
||||
m_pitch(pitch)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Pitch::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new PitchReader(getReader(), m_pitch));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
44
blender-5.2.0/extern/audaspace/src/fx/PitchReader.cpp
vendored
Normal file
44
blender-5.2.0/extern/audaspace/src/fx/PitchReader.cpp
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/PitchReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
PitchReader::PitchReader(std::shared_ptr<IReader> reader, float pitch) :
|
||||
EffectReader(reader), m_pitch(pitch)
|
||||
{
|
||||
}
|
||||
|
||||
Specs PitchReader::getSpecs() const
|
||||
{
|
||||
Specs specs = m_reader->getSpecs();
|
||||
specs.rate *= m_pitch;
|
||||
return specs;
|
||||
}
|
||||
|
||||
float PitchReader::getPitch() const
|
||||
{
|
||||
return m_pitch;
|
||||
}
|
||||
|
||||
void PitchReader::setPitch(float pitch)
|
||||
{
|
||||
if(pitch > 0.0f)
|
||||
m_pitch = pitch;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
144
blender-5.2.0/extern/audaspace/src/fx/PlaybackCategory.cpp
vendored
Normal file
144
blender-5.2.0/extern/audaspace/src/fx/PlaybackCategory.cpp
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/PlaybackCategory.h"
|
||||
#include "fx/VolumeSound.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
struct HandleData {
|
||||
unsigned int id;
|
||||
PlaybackCategory* category;
|
||||
};
|
||||
|
||||
PlaybackCategory::PlaybackCategory(std::shared_ptr<IDevice> device) :
|
||||
m_currentID(0), m_device(device), m_status(STATUS_PLAYING), m_volumeStorage(std::make_shared<VolumeStorage>(1.0f))
|
||||
{
|
||||
}
|
||||
|
||||
PlaybackCategory::~PlaybackCategory()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
std::shared_ptr<IHandle> PlaybackCategory::play(std::shared_ptr<ISound> sound)
|
||||
{
|
||||
std::shared_ptr<ISound> vs(std::make_shared<VolumeSound>(sound, m_volumeStorage));
|
||||
m_device->lock();
|
||||
auto handle = m_device->play(vs);
|
||||
if(handle == nullptr)
|
||||
return nullptr;
|
||||
switch (m_status)
|
||||
{
|
||||
case STATUS_PAUSED:
|
||||
handle->pause();
|
||||
break;
|
||||
default:
|
||||
m_status = STATUS_PLAYING;
|
||||
};
|
||||
m_handles[m_currentID] = handle;
|
||||
HandleData* data = new HandleData;
|
||||
data->category = this;
|
||||
data->id = m_currentID;
|
||||
handle->setStopCallback(cleanHandleCallback, data);
|
||||
m_device->unlock();
|
||||
|
||||
m_currentID++;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void PlaybackCategory::resume()
|
||||
{
|
||||
m_device->lock();
|
||||
for(auto i = m_handles.begin(); i != m_handles.end();)
|
||||
{
|
||||
if(i->second->getStatus() == STATUS_INVALID)
|
||||
i = m_handles.erase(i);
|
||||
else
|
||||
{
|
||||
i->second->resume();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
m_device->unlock();
|
||||
m_status = STATUS_PLAYING;
|
||||
}
|
||||
|
||||
void PlaybackCategory::pause()
|
||||
{
|
||||
m_device->lock();
|
||||
for(auto i = m_handles.begin(); i != m_handles.end();)
|
||||
{
|
||||
if(i->second->getStatus() == STATUS_INVALID)
|
||||
i = m_handles.erase(i);
|
||||
else
|
||||
{
|
||||
i->second->pause();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
m_device->unlock();
|
||||
m_status = STATUS_PAUSED;
|
||||
}
|
||||
|
||||
float PlaybackCategory::getVolume()
|
||||
{
|
||||
return m_volumeStorage->getVolume();
|
||||
}
|
||||
|
||||
void PlaybackCategory::setVolume(float volume)
|
||||
{
|
||||
m_volumeStorage->setVolume(volume);
|
||||
}
|
||||
|
||||
void PlaybackCategory::stop()
|
||||
{
|
||||
m_device->lock();
|
||||
for(auto i = m_handles.begin(); i != m_handles.end();)
|
||||
{
|
||||
i->second->stop();
|
||||
if(i->second->getStatus() == STATUS_INVALID)
|
||||
i = m_handles.erase(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
m_device->unlock();
|
||||
m_status = STATUS_STOPPED;
|
||||
}
|
||||
|
||||
std::shared_ptr<VolumeStorage> PlaybackCategory::getSharedVolume()
|
||||
{
|
||||
return m_volumeStorage;
|
||||
}
|
||||
|
||||
void PlaybackCategory::cleanHandles()
|
||||
{
|
||||
for(auto i = m_handles.begin(); i != m_handles.end();)
|
||||
{
|
||||
if(i->second->getStatus() == STATUS_INVALID)
|
||||
i = m_handles.erase(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackCategory::cleanHandleCallback(void* data)
|
||||
{
|
||||
auto dat = reinterpret_cast<HandleData*>(data);
|
||||
dat->category->m_handles.erase(dat->id);
|
||||
delete dat;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
186
blender-5.2.0/extern/audaspace/src/fx/PlaybackManager.cpp
vendored
Normal file
186
blender-5.2.0/extern/audaspace/src/fx/PlaybackManager.cpp
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/PlaybackManager.h"
|
||||
#include "fx/VolumeSound.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
PlaybackManager::PlaybackManager(std::shared_ptr<IDevice> device) :
|
||||
m_device(device), m_currentKey(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int PlaybackManager::addCategory(std::shared_ptr<PlaybackCategory> category)
|
||||
{
|
||||
bool flag = true;
|
||||
unsigned int k = -1;
|
||||
do {
|
||||
auto iter = m_categories.find(m_currentKey);
|
||||
if(iter == m_categories.end())
|
||||
{
|
||||
m_categories[m_currentKey] = category;
|
||||
k = m_currentKey;
|
||||
m_currentKey++;
|
||||
flag = false;
|
||||
}
|
||||
else
|
||||
m_currentKey++;
|
||||
} while(flag);
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
unsigned int PlaybackManager::addCategory(float volume)
|
||||
{
|
||||
std::shared_ptr<PlaybackCategory> category = std::make_shared<PlaybackCategory>(m_device);
|
||||
category->setVolume(volume);
|
||||
bool flag = true;
|
||||
unsigned int k = -1;
|
||||
do {
|
||||
auto iter = m_categories.find(m_currentKey);
|
||||
if(iter == m_categories.end())
|
||||
{
|
||||
m_categories[m_currentKey] = category;
|
||||
k = m_currentKey;
|
||||
m_currentKey++;
|
||||
flag = false;
|
||||
}
|
||||
else
|
||||
m_currentKey++;
|
||||
} while(flag);
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
std::shared_ptr<IHandle> PlaybackManager::play(std::shared_ptr<ISound> sound, unsigned int catKey)
|
||||
{
|
||||
auto iter = m_categories.find(catKey);
|
||||
std::shared_ptr<PlaybackCategory> category;
|
||||
|
||||
if(iter != m_categories.end())
|
||||
{
|
||||
category = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
category = std::make_shared<PlaybackCategory>(m_device);
|
||||
m_categories[catKey] = category;
|
||||
}
|
||||
return category->play(sound);
|
||||
}
|
||||
|
||||
bool PlaybackManager::resume(unsigned int catKey)
|
||||
{
|
||||
auto iter = m_categories.find(catKey);
|
||||
|
||||
if(iter != m_categories.end())
|
||||
{
|
||||
iter->second->resume();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PlaybackManager::pause(unsigned int catKey)
|
||||
{
|
||||
auto iter = m_categories.find(catKey);
|
||||
|
||||
if(iter != m_categories.end())
|
||||
{
|
||||
iter->second->pause();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
float PlaybackManager::getVolume(unsigned int catKey)
|
||||
{
|
||||
auto iter = m_categories.find(catKey);
|
||||
|
||||
if(iter != m_categories.end())
|
||||
{
|
||||
return iter->second->getVolume();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
bool PlaybackManager::setVolume(float volume, unsigned int catKey)
|
||||
{
|
||||
auto iter = m_categories.find(catKey);
|
||||
|
||||
if(iter != m_categories.end())
|
||||
{
|
||||
iter->second->setVolume(volume);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PlaybackManager::stop(unsigned int catKey)
|
||||
{
|
||||
auto iter = m_categories.find(catKey);
|
||||
|
||||
if(iter != m_categories.end())
|
||||
{
|
||||
iter->second->stop();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackManager::clean()
|
||||
{
|
||||
for(auto cat : m_categories)
|
||||
cat.second->cleanHandles();
|
||||
}
|
||||
|
||||
bool PlaybackManager::clean(unsigned int catKey)
|
||||
{
|
||||
auto iter = m_categories.find(catKey);
|
||||
|
||||
if(iter != m_categories.end())
|
||||
{
|
||||
iter->second->cleanHandles();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<IDevice> PlaybackManager::getDevice()
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
32
blender-5.2.0/extern/audaspace/src/fx/Reverse.cpp
vendored
Normal file
32
blender-5.2.0/extern/audaspace/src/fx/Reverse.cpp
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Reverse.h"
|
||||
#include "fx/ReverseReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Reverse::Reverse(std::shared_ptr<ISound> sound) :
|
||||
Effect(sound)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Reverse::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new ReverseReader(getReader()));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
88
blender-5.2.0/extern/audaspace/src/fx/ReverseReader.cpp
vendored
Normal file
88
blender-5.2.0/extern/audaspace/src/fx/ReverseReader.cpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/ReverseReader.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
ReverseReader::ReverseReader(std::shared_ptr<IReader> reader) :
|
||||
EffectReader(reader),
|
||||
m_length(reader->getLength()),
|
||||
m_position(0)
|
||||
{
|
||||
if(m_length < 0 || !reader->isSeekable())
|
||||
AUD_THROW(StateException, "A reader has to be seekable and have finite length to be reversible.");
|
||||
}
|
||||
|
||||
void ReverseReader::seek(int position)
|
||||
{
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
int ReverseReader::getLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
int ReverseReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
void ReverseReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
// first correct the length
|
||||
if(m_position + length > m_length)
|
||||
length = m_length - m_position;
|
||||
|
||||
if(length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
eos = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const Specs specs = getSpecs();
|
||||
const int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
sample_t temp[CHANNEL_MAX];
|
||||
|
||||
int len = length;
|
||||
|
||||
// read from reader
|
||||
m_reader->seek(m_length - m_position - len);
|
||||
m_reader->read(len, eos, buffer);
|
||||
|
||||
// set null if reader didn't give enough data
|
||||
if(len < length)
|
||||
std::memset(buffer, 0, (length - len) * samplesize);
|
||||
|
||||
// copy the samples reverted
|
||||
for(int i = 0; i < length / 2; i++)
|
||||
{
|
||||
std::memcpy(temp, buffer + (len - 1 - i) * specs.channels, samplesize);
|
||||
std::memcpy(buffer + (len - 1 - i) * specs.channels, buffer + i * specs.channels, samplesize);
|
||||
std::memcpy(buffer + i * specs.channels, temp, samplesize);
|
||||
}
|
||||
|
||||
m_position += length;
|
||||
eos = false;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
84
blender-5.2.0/extern/audaspace/src/fx/SoundList.cpp
vendored
Normal file
84
blender-5.2.0/extern/audaspace/src/fx/SoundList.cpp
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/SoundList.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <chrono>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
SoundList::SoundList(bool random) :
|
||||
m_random(random)
|
||||
{
|
||||
std::srand(time(NULL));
|
||||
}
|
||||
|
||||
SoundList::SoundList(std::vector<std::shared_ptr<ISound>>& list, bool random) :
|
||||
m_list(list), m_random(random)
|
||||
{
|
||||
std::srand(time(NULL));
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> SoundList::createReader()
|
||||
{
|
||||
if(m_list.size() > 0)
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
if(!m_random){
|
||||
m_index++;
|
||||
if(m_index >= m_list.size())
|
||||
m_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int temp;
|
||||
do{
|
||||
temp = std::rand() % m_list.size();
|
||||
} while(temp == m_index && m_list.size()>1);
|
||||
m_index = temp;
|
||||
}
|
||||
auto reader = m_list[m_index]->createReader();
|
||||
m_mutex.unlock();
|
||||
return reader;
|
||||
}
|
||||
else
|
||||
AUD_THROW(FileException, "The sound list is empty");
|
||||
}
|
||||
|
||||
void SoundList::addSound(std::shared_ptr<ISound> sound)
|
||||
{
|
||||
m_list.push_back(sound);
|
||||
}
|
||||
|
||||
void SoundList::setRandomMode(bool random)
|
||||
{
|
||||
m_random = random;
|
||||
}
|
||||
|
||||
bool SoundList::getRandomMode()
|
||||
{
|
||||
return m_random;
|
||||
}
|
||||
|
||||
int SoundList::getSize()
|
||||
{
|
||||
return m_list.size();
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
71
blender-5.2.0/extern/audaspace/src/fx/Source.cpp
vendored
Normal file
71
blender-5.2.0/extern/audaspace/src/fx/Source.cpp
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Source.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
Source::Source(float azimuth, float elevation, float distance) :
|
||||
m_elevation(elevation), m_distance(distance)
|
||||
{
|
||||
azimuth = std::fmod(azimuth, 360);
|
||||
if(azimuth < 0)
|
||||
azimuth += 360;
|
||||
m_azimuth = azimuth;
|
||||
}
|
||||
|
||||
float Source::getAzimuth()
|
||||
{
|
||||
return m_azimuth;
|
||||
}
|
||||
|
||||
float Source::getElevation()
|
||||
{
|
||||
return m_elevation;
|
||||
}
|
||||
|
||||
float Source::getDistance()
|
||||
{
|
||||
return m_distance;
|
||||
}
|
||||
|
||||
float Source::getVolume()
|
||||
{
|
||||
float volume = 1.0f - m_distance;
|
||||
if(volume < 0.0f)
|
||||
volume = 0.0f;
|
||||
return volume;
|
||||
}
|
||||
|
||||
void Source::setAzimuth(float azimuth)
|
||||
{
|
||||
azimuth = std::fmod(azimuth, 360);
|
||||
if(azimuth < 0)
|
||||
azimuth += 360;
|
||||
m_azimuth = azimuth;
|
||||
}
|
||||
|
||||
void Source::setElevation(float elevation)
|
||||
{
|
||||
m_elevation = elevation;
|
||||
}
|
||||
|
||||
void Source::setDistance(float distance)
|
||||
{
|
||||
m_distance = distance;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
36
blender-5.2.0/extern/audaspace/src/fx/Sum.cpp
vendored
Normal file
36
blender-5.2.0/extern/audaspace/src/fx/Sum.cpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Sum.h"
|
||||
#include "fx/IIRFilterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Sum::Sum(std::shared_ptr<ISound> sound) :
|
||||
Effect(sound)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Sum::createReader()
|
||||
{
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
a.push_back(-1);
|
||||
b.push_back(1);
|
||||
return std::shared_ptr<IReader>(new IIRFilterReader(getReader(), b, a));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
54
blender-5.2.0/extern/audaspace/src/fx/Threshold.cpp
vendored
Normal file
54
blender-5.2.0/extern/audaspace/src/fx/Threshold.cpp
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Threshold.h"
|
||||
#include "fx/CallbackIIRFilterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
sample_t Threshold::thresholdFilter(CallbackIIRFilterReader* reader, float* threshold)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
if(in >= *threshold)
|
||||
return 1;
|
||||
else if(in <= -*threshold)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Threshold::endThresholdFilter(float* threshold)
|
||||
{
|
||||
delete threshold;
|
||||
}
|
||||
|
||||
Threshold::Threshold(std::shared_ptr<ISound> sound, float threshold) :
|
||||
Effect(sound),
|
||||
m_threshold(threshold)
|
||||
{
|
||||
}
|
||||
|
||||
float Threshold::getThreshold() const
|
||||
{
|
||||
return m_threshold;
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Threshold::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new CallbackIIRFilterReader(getReader(), 1, 0, doFilterIIR(thresholdFilter), endFilterIIR(endThresholdFilter), new float(m_threshold)));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
53
blender-5.2.0/extern/audaspace/src/fx/TimeStretchPitchScale.cpp
vendored
Normal file
53
blender-5.2.0/extern/audaspace/src/fx/TimeStretchPitchScale.cpp
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2025 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/TimeStretchPitchScale.h"
|
||||
|
||||
#include "fx/TimeStretchPitchScaleReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
TimeStretchPitchScale::TimeStretchPitchScale(std::shared_ptr<ISound> sound, double timeRatio, double pitchScale, StretcherQuality quality, bool preserveFormant) :
|
||||
Effect(sound), m_timeRatio(timeRatio), m_pitchScale(pitchScale), m_quality(quality), m_preserveFormant(preserveFormant)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> TimeStretchPitchScale::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new TimeStretchPitchScaleReader(getReader(), m_timeRatio, m_pitchScale, m_quality, m_preserveFormant));
|
||||
}
|
||||
|
||||
double TimeStretchPitchScale::getTimeRatio() const
|
||||
{
|
||||
return m_timeRatio;
|
||||
}
|
||||
|
||||
double TimeStretchPitchScale::getPitchScale() const
|
||||
{
|
||||
return m_pitchScale;
|
||||
}
|
||||
|
||||
bool TimeStretchPitchScale::getPreserveFormant() const
|
||||
{
|
||||
return m_preserveFormant;
|
||||
}
|
||||
|
||||
StretcherQuality TimeStretchPitchScale::getStretcherQuality() const
|
||||
{
|
||||
return m_quality;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
205
blender-5.2.0/extern/audaspace/src/fx/TimeStretchPitchScaleReader.cpp
vendored
Normal file
205
blender-5.2.0/extern/audaspace/src/fx/TimeStretchPitchScaleReader.cpp
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2025 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/TimeStretchPitchScaleReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "Exception.h"
|
||||
#include "IReader.h"
|
||||
|
||||
#include "util/Buffer.h"
|
||||
|
||||
using namespace RubberBand;
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
void TimeStretchPitchScaleReader::reset()
|
||||
{
|
||||
auto startPad{m_stretcher->getPreferredStartPad()};
|
||||
|
||||
m_samplesToDrop = m_stretcher->getStartDelay();
|
||||
|
||||
m_deinterleaved[0].assureSize(startPad * sizeof(sample_t));
|
||||
std::memset(m_deinterleaved[0].getBuffer(), 0, startPad * sizeof(sample_t));
|
||||
|
||||
for(auto& channel : m_channelData)
|
||||
channel = m_deinterleaved[0].getBuffer();
|
||||
|
||||
m_stretcher->process(m_channelData.data(), startPad, m_finishedReader);
|
||||
}
|
||||
|
||||
TimeStretchPitchScaleReader::TimeStretchPitchScaleReader(std::shared_ptr<IReader> reader, double timeRatio, double pitchScale, StretcherQuality quality, bool preserveFormant) :
|
||||
EffectReader(reader), m_position(0), m_finishedReader(false), m_deinterleaved(reader->getSpecs().channels), m_channelData(reader->getSpecs().channels)
|
||||
{
|
||||
if (pitchScale < 1.0 / 256.0 || pitchScale > 256.0)
|
||||
AUD_THROW(StateException, "The pitch scale must be between 1/256 and 256");
|
||||
|
||||
if (timeRatio < 1.0 / 256.0 || timeRatio > 256.0)
|
||||
AUD_THROW(StateException, "The time-stretch ratio must be between 1/256 and 256");
|
||||
|
||||
RubberBandStretcher::Options options = RubberBandStretcher::OptionProcessRealTime | RubberBandStretcher::OptionEngineFiner | RubberBandStretcher::OptionChannelsTogether;
|
||||
|
||||
switch(quality)
|
||||
{
|
||||
case StretcherQuality::HIGH:
|
||||
options |= RubberBandStretcher::OptionPitchHighQuality;
|
||||
break;
|
||||
case StretcherQuality::FAST:
|
||||
options |= RubberBandStretcher::OptionPitchHighSpeed;
|
||||
options |= RubberBandStretcher::OptionWindowShort;
|
||||
break;
|
||||
case StretcherQuality::CONSISTENT:
|
||||
options |= RubberBandStretcher::OptionPitchHighConsistency;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
options |= preserveFormant ? RubberBandStretcher::OptionFormantPreserved : RubberBandStretcher::OptionFormantShifted;
|
||||
m_stretcher = std::make_unique<RubberBandStretcher>(m_reader->getSpecs().rate, m_reader->getSpecs().channels, options, timeRatio, pitchScale);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void TimeStretchPitchScaleReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
if(length == 0)
|
||||
return;
|
||||
|
||||
int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
|
||||
int channels = m_reader->getSpecs().channels;
|
||||
int samplesRead = 0;
|
||||
|
||||
eos = false;
|
||||
while(samplesRead < length)
|
||||
{
|
||||
int len = m_stretcher->getSamplesRequired();
|
||||
if(!m_finishedReader && len != 0)
|
||||
{
|
||||
m_buffer.assureSize(len * samplesize);
|
||||
sample_t* buf = m_buffer.getBuffer();
|
||||
|
||||
m_reader->read(len, m_finishedReader, buf);
|
||||
|
||||
// Deinterleave the input reader buffer for processing
|
||||
for(int channel = 0; channel < channels; channel++)
|
||||
{
|
||||
m_deinterleaved[channel].assureSize(len * sizeof(sample_t));
|
||||
sample_t* channelBuf = m_deinterleaved[channel].getBuffer();
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
channelBuf[i] = buf[i * channels + channel];
|
||||
}
|
||||
|
||||
m_channelData[channel] = channelBuf;
|
||||
}
|
||||
|
||||
m_stretcher->process(m_channelData.data(), len, m_finishedReader);
|
||||
}
|
||||
|
||||
int available = m_stretcher->available();
|
||||
if(available == -1)
|
||||
{
|
||||
eos = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(available == 0)
|
||||
continue;
|
||||
|
||||
available = std::min(m_samplesToDrop ? m_samplesToDrop : length - samplesRead, available);
|
||||
|
||||
for(int channel = 0; channel < channels; channel++)
|
||||
{
|
||||
m_deinterleaved[channel].assureSize(available * sizeof(sample_t));
|
||||
m_channelData[channel] = m_deinterleaved[channel].getBuffer();
|
||||
}
|
||||
|
||||
m_stretcher->retrieve(m_channelData.data(), available);
|
||||
|
||||
if(m_samplesToDrop)
|
||||
{
|
||||
m_samplesToDrop -= available;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Interleave the retrieved data into the buffer
|
||||
for(int channel = 0; channel < channels; channel++)
|
||||
{
|
||||
sample_t* outputBuf = m_deinterleaved[channel].getBuffer();
|
||||
for(int i = 0; i < available; i++)
|
||||
{
|
||||
buffer[(samplesRead + i) * channels + channel] = outputBuf[i];
|
||||
}
|
||||
}
|
||||
|
||||
samplesRead += available;
|
||||
}
|
||||
}
|
||||
|
||||
length = samplesRead;
|
||||
m_position += length;
|
||||
eos = m_stretcher->available() == -1;
|
||||
}
|
||||
|
||||
double TimeStretchPitchScaleReader::getTimeRatio() const
|
||||
{
|
||||
return m_stretcher->getTimeRatio();
|
||||
}
|
||||
|
||||
void TimeStretchPitchScaleReader::setTimeRatio(double timeRatio)
|
||||
{
|
||||
if(timeRatio >= 1.0 / 256.0 && timeRatio <= 256.0)
|
||||
{
|
||||
m_stretcher->setTimeRatio(timeRatio);
|
||||
}
|
||||
}
|
||||
|
||||
double TimeStretchPitchScaleReader::getPitchScale() const
|
||||
{
|
||||
return m_stretcher->getPitchScale();
|
||||
}
|
||||
|
||||
void TimeStretchPitchScaleReader::setPitchScale(double pitchScale)
|
||||
{
|
||||
if(pitchScale >= 1.0 / 256.0 && pitchScale <= 256.0)
|
||||
{
|
||||
m_stretcher->setPitchScale(pitchScale);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeStretchPitchScaleReader::seek(int position)
|
||||
{
|
||||
m_reader->seek(int(position / getTimeRatio()));
|
||||
m_finishedReader = false;
|
||||
m_stretcher->reset();
|
||||
reset();
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
int TimeStretchPitchScaleReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength() * getTimeRatio();
|
||||
}
|
||||
|
||||
int TimeStretchPitchScaleReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
41
blender-5.2.0/extern/audaspace/src/fx/Volume.cpp
vendored
Normal file
41
blender-5.2.0/extern/audaspace/src/fx/Volume.cpp
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/Volume.h"
|
||||
#include "fx/IIRFilterReader.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
Volume::Volume(std::shared_ptr<ISound> sound, float volume) :
|
||||
Effect(sound),
|
||||
m_volume(volume)
|
||||
{
|
||||
}
|
||||
|
||||
float Volume::getVolume() const
|
||||
{
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Volume::createReader()
|
||||
{
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
b.push_back(m_volume);
|
||||
return std::shared_ptr<IReader>(new IIRFilterReader(getReader(), b, a));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
60
blender-5.2.0/extern/audaspace/src/fx/VolumeReader.cpp
vendored
Normal file
60
blender-5.2.0/extern/audaspace/src/fx/VolumeReader.cpp
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/VolumeReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
VolumeReader::VolumeReader(std::shared_ptr<IReader> reader, std::shared_ptr<VolumeStorage> volumeStorage) :
|
||||
m_reader(reader), m_volumeStorage(volumeStorage)
|
||||
{
|
||||
}
|
||||
|
||||
bool VolumeReader::isSeekable() const
|
||||
{
|
||||
return m_reader->isSeekable();
|
||||
}
|
||||
|
||||
void VolumeReader::seek(int position)
|
||||
{
|
||||
m_reader->seek(position);
|
||||
}
|
||||
|
||||
int VolumeReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength();
|
||||
}
|
||||
|
||||
int VolumeReader::getPosition() const
|
||||
{
|
||||
return m_reader->getPosition();
|
||||
}
|
||||
|
||||
Specs VolumeReader::getSpecs() const
|
||||
{
|
||||
return m_reader->getSpecs();
|
||||
}
|
||||
|
||||
void VolumeReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
m_reader->read(length, eos, buffer);
|
||||
for(int i = 0; i < length * m_reader->getSpecs().channels; i++)
|
||||
buffer[i] = buffer[i] * m_volumeStorage->getVolume();
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
45
blender-5.2.0/extern/audaspace/src/fx/VolumeSound.cpp
vendored
Normal file
45
blender-5.2.0/extern/audaspace/src/fx/VolumeSound.cpp
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/VolumeSound.h"
|
||||
#include "fx/VolumeReader.h"
|
||||
#include "Exception.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
VolumeSound::VolumeSound(std::shared_ptr<ISound> sound, std::shared_ptr<VolumeStorage> volumeStorage) :
|
||||
m_sound(sound), m_volumeStorage(volumeStorage)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> VolumeSound::createReader()
|
||||
{
|
||||
return std::make_shared<VolumeReader>(m_sound->createReader(), m_volumeStorage);
|
||||
}
|
||||
|
||||
std::shared_ptr<VolumeStorage> VolumeSound::getSharedVolume()
|
||||
{
|
||||
return m_volumeStorage;
|
||||
}
|
||||
|
||||
void VolumeSound::setSharedVolume(std::shared_ptr<VolumeStorage> volumeStorage)
|
||||
{
|
||||
m_volumeStorage = volumeStorage;
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
39
blender-5.2.0/extern/audaspace/src/fx/VolumeStorage.cpp
vendored
Normal file
39
blender-5.2.0/extern/audaspace/src/fx/VolumeStorage.cpp
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "fx/VolumeStorage.h"
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
VolumeStorage::VolumeStorage() :
|
||||
m_volume(1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
VolumeStorage::VolumeStorage(float volume) :
|
||||
m_volume(volume)
|
||||
{
|
||||
}
|
||||
|
||||
float VolumeStorage::getVolume()
|
||||
{
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
void VolumeStorage::setVolume(float volume)
|
||||
{
|
||||
m_volume = volume;
|
||||
}
|
||||
AUD_NAMESPACE_END
|
||||
Reference in New Issue
Block a user