mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 12:12:32 +02:00
commit
33b859df33
9 changed files with 2171 additions and 121 deletions
69
examples/utilities/tools/reverbTest.js
Normal file
69
examples/utilities/tools/reverbTest.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
//
|
||||||
|
// reverbTest.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Ken Cooke on 11/23/2015.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
Script.include("cookies.js");
|
||||||
|
|
||||||
|
var audioOptions = new AudioEffectOptions({
|
||||||
|
maxRoomSize: 50,
|
||||||
|
roomSize: 50,
|
||||||
|
reverbTime: 4,
|
||||||
|
damping: 0.50,
|
||||||
|
inputBandwidth: 0.8,
|
||||||
|
earlyLevel: 0,
|
||||||
|
tailLevel: 0,
|
||||||
|
dryLevel: -6,
|
||||||
|
wetLevel: -6
|
||||||
|
});
|
||||||
|
|
||||||
|
AudioDevice.setReverbOptions(audioOptions);
|
||||||
|
AudioDevice.setReverb(true);
|
||||||
|
print("Reverb is ON.");
|
||||||
|
|
||||||
|
var panel = new Panel(10, 200);
|
||||||
|
|
||||||
|
var parameters = [
|
||||||
|
{ name: "roomSize", min: 0, max: 100, units: " feet" },
|
||||||
|
{ name: "reverbTime", min: 0, max: 10, units: " sec" },
|
||||||
|
{ name: "damping", min: 0, max: 1, units: " " },
|
||||||
|
{ name: "inputBandwidth", min: 0, max: 1, units: " " },
|
||||||
|
{ name: "earlyLevel", min: -48, max: 0, units: " dB" },
|
||||||
|
{ name: "tailLevel", min: -48, max: 0, units: " dB" },
|
||||||
|
{ name: "wetLevel", min: -48, max: 0, units: " dB" },
|
||||||
|
]
|
||||||
|
|
||||||
|
function setter(name) {
|
||||||
|
return function(value) { audioOptions[name] = value; AudioDevice.setReverbOptions(audioOptions); }
|
||||||
|
}
|
||||||
|
|
||||||
|
function getter(name) {
|
||||||
|
return function() { return audioOptions[name]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayer(units) {
|
||||||
|
return function(value) { return (value).toFixed(1) + units; };
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a slider for each parameter
|
||||||
|
for (var i = 0; i < parameters.length; i++) {
|
||||||
|
var p = parameters[i];
|
||||||
|
panel.newSlider(p.name, p.min, p.max, setter(p.name), getter(p.name), displayer(p.units));
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.mouseMoveEvent.connect(function panelMouseMoveEvent(event) { return panel.mouseMoveEvent(event); });
|
||||||
|
Controller.mousePressEvent.connect( function panelMousePressEvent(event) { return panel.mousePressEvent(event); });
|
||||||
|
Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseReleaseEvent(event); });
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
panel.destroy();
|
||||||
|
AudioDevice.setReverb(false);
|
||||||
|
print("Reverb is OFF.");
|
||||||
|
}
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
|
@ -33,29 +33,6 @@
|
||||||
#include <QtMultimedia/QAudioInput>
|
#include <QtMultimedia/QAudioInput>
|
||||||
#include <QtMultimedia/QAudioOutput>
|
#include <QtMultimedia/QAudioOutput>
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#pragma warning (push)
|
|
||||||
#pragma warning (disable: 4273 4305)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <gverb/gverb.h>
|
|
||||||
#include <gverb/gverbdsp.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#pragma warning (pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
#include <udt/PacketHeaders.h>
|
#include <udt/PacketHeaders.h>
|
||||||
#include <PositionalAudioStream.h>
|
#include <PositionalAudioStream.h>
|
||||||
|
@ -120,7 +97,6 @@ AudioClient::AudioClient() :
|
||||||
_audioSourceInjectEnabled(false),
|
_audioSourceInjectEnabled(false),
|
||||||
_reverb(false),
|
_reverb(false),
|
||||||
_reverbOptions(&_scriptReverbOptions),
|
_reverbOptions(&_scriptReverbOptions),
|
||||||
_gverb(NULL),
|
|
||||||
_inputToNetworkResampler(NULL),
|
_inputToNetworkResampler(NULL),
|
||||||
_networkToOutputResampler(NULL),
|
_networkToOutputResampler(NULL),
|
||||||
_loopbackResampler(NULL),
|
_loopbackResampler(NULL),
|
||||||
|
@ -145,9 +121,7 @@ AudioClient::AudioClient() :
|
||||||
connect(updateTimer, &QTimer::timeout, this, &AudioClient::checkDevices);
|
connect(updateTimer, &QTimer::timeout, this, &AudioClient::checkDevices);
|
||||||
updateTimer->start(DEVICE_CHECK_INTERVAL_MSECS);
|
updateTimer->start(DEVICE_CHECK_INTERVAL_MSECS);
|
||||||
|
|
||||||
// create GVerb filter
|
configureReverb();
|
||||||
_gverb = createGverbFilter();
|
|
||||||
configureGverbFilter(_gverb);
|
|
||||||
|
|
||||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||||
packetReceiver.registerListener(PacketType::AudioStreamStats, &_stats, "processStreamStatsPacket");
|
packetReceiver.registerListener(PacketType::AudioStreamStats, &_stats, "processStreamStatsPacket");
|
||||||
|
@ -160,10 +134,6 @@ AudioClient::AudioClient() :
|
||||||
|
|
||||||
AudioClient::~AudioClient() {
|
AudioClient::~AudioClient() {
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
if (_gverb) {
|
|
||||||
gverb_free(_gverb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::reset() {
|
void AudioClient::reset() {
|
||||||
|
@ -173,8 +143,8 @@ void AudioClient::reset() {
|
||||||
_toneSource.reset();
|
_toneSource.reset();
|
||||||
_sourceGain.reset();
|
_sourceGain.reset();
|
||||||
_inputGain.reset();
|
_inputGain.reset();
|
||||||
|
_sourceReverb.reset();
|
||||||
gverb_flush(_gverb);
|
_listenerReverb.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::audioMixerKilled() {
|
void AudioClient::audioMixerKilled() {
|
||||||
|
@ -569,27 +539,32 @@ bool AudioClient::switchOutputToAudioDevice(const QString& outputDeviceName) {
|
||||||
return switchOutputToAudioDevice(getNamedAudioDeviceForMode(QAudio::AudioOutput, outputDeviceName));
|
return switchOutputToAudioDevice(getNamedAudioDeviceForMode(QAudio::AudioOutput, outputDeviceName));
|
||||||
}
|
}
|
||||||
|
|
||||||
ty_gverb* AudioClient::createGverbFilter() {
|
void AudioClient::configureReverb() {
|
||||||
// Initialize a new gverb instance
|
ReverbParameters p;
|
||||||
ty_gverb* filter = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
|
_listenerReverb.getParameters(&p);
|
||||||
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
|
|
||||||
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
|
|
||||||
_reverbOptions->getTailLevel());
|
|
||||||
|
|
||||||
return filter;
|
// for now, reuse the gverb parameters
|
||||||
|
p.sampleRate = _outputFormat.sampleRate();
|
||||||
|
p.roomSize = _reverbOptions->getRoomSize();
|
||||||
|
p.reverbTime = _reverbOptions->getReverbTime();
|
||||||
|
p.highGain = -24.0f * (1.0f - _reverbOptions->getDamping());
|
||||||
|
p.bandwidth = 10000.0f * _reverbOptions->getInputBandwidth();
|
||||||
|
p.earlyGain = _reverbOptions->getEarlyLevel();
|
||||||
|
p.lateGain = _reverbOptions->getTailLevel();
|
||||||
|
p.wetDryMix = 100.0f * powf(10.0f, _reverbOptions->getWetLevel() * (1/20.0f));
|
||||||
|
_listenerReverb.setParameters(&p);
|
||||||
|
|
||||||
|
// used for adding self-reverb to loopback audio
|
||||||
|
p.wetDryMix = 100.0f;
|
||||||
|
p.preDelay = 0.0f;
|
||||||
|
p.earlyGain = -96.0f; // disable ER
|
||||||
|
p.lateGain -= 12.0f; // quieter than listener reverb
|
||||||
|
p.lateMixLeft = 0.0f;
|
||||||
|
p.lateMixRight = 0.0f;
|
||||||
|
_sourceReverb.setParameters(&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::configureGverbFilter(ty_gverb* filter) {
|
void AudioClient::updateReverbOptions() {
|
||||||
// Configure the instance (these functions are not super well named - they actually set several internal variables)
|
|
||||||
gverb_set_roomsize(filter, _reverbOptions->getRoomSize());
|
|
||||||
gverb_set_revtime(filter, _reverbOptions->getReverbTime());
|
|
||||||
gverb_set_damping(filter, _reverbOptions->getDamping());
|
|
||||||
gverb_set_inputbandwidth(filter, _reverbOptions->getInputBandwidth());
|
|
||||||
gverb_set_earlylevel(filter, DB_CO(_reverbOptions->getEarlyLevel()));
|
|
||||||
gverb_set_taillevel(filter, DB_CO(_reverbOptions->getTailLevel()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioClient::updateGverbOptions() {
|
|
||||||
bool reverbChanged = false;
|
bool reverbChanged = false;
|
||||||
if (_receivedAudioStream.hasReverb()) {
|
if (_receivedAudioStream.hasReverb()) {
|
||||||
|
|
||||||
|
@ -599,7 +574,7 @@ void AudioClient::updateGverbOptions() {
|
||||||
}
|
}
|
||||||
if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) {
|
if (_zoneReverbOptions.getWetLevel() != _receivedAudioStream.getWetLevel()) {
|
||||||
_zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel());
|
_zoneReverbOptions.setWetLevel(_receivedAudioStream.getWetLevel());
|
||||||
// Not part of actual filter config, no need to set reverbChanged to true
|
reverbChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_reverbOptions != &_zoneReverbOptions) {
|
if (_reverbOptions != &_zoneReverbOptions) {
|
||||||
|
@ -612,9 +587,7 @@ void AudioClient::updateGverbOptions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverbChanged) {
|
if (reverbChanged) {
|
||||||
gverb_free(_gverb);
|
configureReverb();
|
||||||
_gverb = createGverbFilter();
|
|
||||||
configureGverbFilter(_gverb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +595,8 @@ void AudioClient::setReverb(bool reverb) {
|
||||||
_reverb = reverb;
|
_reverb = reverb;
|
||||||
|
|
||||||
if (!_reverb) {
|
if (!_reverb) {
|
||||||
gverb_flush(_gverb);
|
_sourceReverb.reset();
|
||||||
|
_listenerReverb.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,47 +616,7 @@ void AudioClient::setReverbOptions(const AudioEffectOptions* options) {
|
||||||
|
|
||||||
if (_reverbOptions == &_scriptReverbOptions) {
|
if (_reverbOptions == &_scriptReverbOptions) {
|
||||||
// Apply them to the reverb instances
|
// Apply them to the reverb instances
|
||||||
gverb_free(_gverb);
|
configureReverb();
|
||||||
_gverb = createGverbFilter();
|
|
||||||
configureGverbFilter(_gverb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioClient::addReverb(ty_gverb* gverb, int16_t* samplesData, int16_t* reverbAlone, int numSamples,
|
|
||||||
QAudioFormat& audioFormat, bool noEcho) {
|
|
||||||
float wetFraction = DB_CO(_reverbOptions->getWetLevel());
|
|
||||||
float dryFraction = 1.0f - wetFraction;
|
|
||||||
|
|
||||||
float lValue,rValue;
|
|
||||||
for (int sample = 0; sample < numSamples; sample += audioFormat.channelCount()) {
|
|
||||||
// Run GVerb
|
|
||||||
float value = (float)samplesData[sample];
|
|
||||||
gverb_do(gverb, value, &lValue, &rValue);
|
|
||||||
|
|
||||||
// Mix, accounting for clipping, the left and right channels. Ignore the rest.
|
|
||||||
for (int j = sample; j < sample + audioFormat.channelCount(); j++) {
|
|
||||||
if (j == sample) {
|
|
||||||
// left channel
|
|
||||||
int lResult = glm::clamp((int)(samplesData[j] * dryFraction + lValue * wetFraction),
|
|
||||||
AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
|
|
||||||
samplesData[j] = (int16_t)lResult;
|
|
||||||
|
|
||||||
if (noEcho) {
|
|
||||||
reverbAlone[j] = (int16_t)lValue * wetFraction;
|
|
||||||
}
|
|
||||||
} else if (j == (sample + 1)) {
|
|
||||||
// right channel
|
|
||||||
int rResult = glm::clamp((int)(samplesData[j] * dryFraction + rValue * wetFraction),
|
|
||||||
AudioConstants::MIN_SAMPLE_VALUE, AudioConstants::MAX_SAMPLE_VALUE);
|
|
||||||
samplesData[j] = (int16_t)rResult;
|
|
||||||
|
|
||||||
if (noEcho) {
|
|
||||||
reverbAlone[j] = (int16_t)rValue * wetFraction;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// ignore channels above 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,30 +650,28 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
|
||||||
_loopbackResampler = new AudioSRC(_inputFormat.sampleRate(), _outputFormat.sampleRate(), channelCount);
|
_loopbackResampler = new AudioSRC(_inputFormat.sampleRate(), _outputFormat.sampleRate(), channelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QByteArray reverbAlone; // Intermediary for local reverb with no echo
|
|
||||||
static QByteArray loopBackByteArray;
|
static QByteArray loopBackByteArray;
|
||||||
|
|
||||||
int numInputSamples = inputByteArray.size() / sizeof(int16_t);
|
int numInputSamples = inputByteArray.size() / sizeof(int16_t);
|
||||||
int numLoopbackSamples = numDestinationSamplesRequired(_inputFormat, _outputFormat, numInputSamples);
|
int numLoopbackSamples = numDestinationSamplesRequired(_inputFormat, _outputFormat, numInputSamples);
|
||||||
|
|
||||||
reverbAlone.resize(numInputSamples * sizeof(int16_t));
|
|
||||||
loopBackByteArray.resize(numLoopbackSamples * sizeof(int16_t));
|
loopBackByteArray.resize(numLoopbackSamples * sizeof(int16_t));
|
||||||
|
|
||||||
int16_t* inputSamples = reinterpret_cast<int16_t*>(inputByteArray.data());
|
int16_t* inputSamples = reinterpret_cast<int16_t*>(inputByteArray.data());
|
||||||
int16_t* reverbAloneSamples = reinterpret_cast<int16_t*>(reverbAlone.data());
|
|
||||||
int16_t* loopbackSamples = reinterpret_cast<int16_t*>(loopBackByteArray.data());
|
int16_t* loopbackSamples = reinterpret_cast<int16_t*>(loopBackByteArray.data());
|
||||||
|
|
||||||
if (hasReverb) {
|
|
||||||
updateGverbOptions();
|
|
||||||
addReverb(_gverb, inputSamples, reverbAloneSamples, numInputSamples,
|
|
||||||
_inputFormat, !_shouldEchoLocally);
|
|
||||||
}
|
|
||||||
|
|
||||||
possibleResampling(_loopbackResampler,
|
possibleResampling(_loopbackResampler,
|
||||||
(_shouldEchoLocally) ? inputSamples : reverbAloneSamples, loopbackSamples,
|
inputSamples, loopbackSamples,
|
||||||
numInputSamples, numLoopbackSamples,
|
numInputSamples, numLoopbackSamples,
|
||||||
_inputFormat, _outputFormat);
|
_inputFormat, _outputFormat);
|
||||||
|
|
||||||
|
// apply stereo reverb at the source, to the loopback audio
|
||||||
|
if (!_shouldEchoLocally && hasReverb) {
|
||||||
|
assert(_outputFormat.channelCount() == 2);
|
||||||
|
updateReverbOptions();
|
||||||
|
_sourceReverb.render(loopbackSamples, loopbackSamples, numLoopbackSamples/2);
|
||||||
|
}
|
||||||
|
|
||||||
_loopbackOutputDevice->write(loopBackByteArray);
|
_loopbackOutputDevice->write(loopBackByteArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,12 +803,20 @@ void AudioClient::processReceivedSamples(const QByteArray& inputBuffer, QByteArr
|
||||||
outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t));
|
outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t));
|
||||||
|
|
||||||
const int16_t* receivedSamples = reinterpret_cast<const int16_t*>(inputBuffer.data());
|
const int16_t* receivedSamples = reinterpret_cast<const int16_t*>(inputBuffer.data());
|
||||||
|
int16_t* outputSamples = reinterpret_cast<int16_t*>(outputBuffer.data());
|
||||||
|
|
||||||
// copy the packet from the RB to the output
|
// copy the packet from the RB to the output
|
||||||
possibleResampling(_networkToOutputResampler, receivedSamples,
|
possibleResampling(_networkToOutputResampler, receivedSamples, outputSamples,
|
||||||
reinterpret_cast<int16_t*>(outputBuffer.data()),
|
|
||||||
numNetworkOutputSamples, numDeviceOutputSamples,
|
numNetworkOutputSamples, numDeviceOutputSamples,
|
||||||
_desiredOutputFormat, _outputFormat);
|
_desiredOutputFormat, _outputFormat);
|
||||||
|
|
||||||
|
// apply stereo reverb at the listener, to the received audio
|
||||||
|
bool hasReverb = _reverb || _receivedAudioStream.hasReverb();
|
||||||
|
if (hasReverb) {
|
||||||
|
assert(_outputFormat.channelCount() == 2);
|
||||||
|
updateReverbOptions();
|
||||||
|
_listenerReverb.render(outputSamples, outputSamples, numDeviceOutputSamples/2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::sendMuteEnvironmentPacket() {
|
void AudioClient::sendMuteEnvironmentPacket() {
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "AudioIOStats.h"
|
#include "AudioIOStats.h"
|
||||||
#include "AudioNoiseGate.h"
|
#include "AudioNoiseGate.h"
|
||||||
#include "AudioSRC.h"
|
#include "AudioSRC.h"
|
||||||
|
#include "AudioReverb.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#pragma warning( push )
|
#pragma warning( push )
|
||||||
|
@ -75,8 +76,6 @@ class QAudioOutput;
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
|
|
||||||
|
|
||||||
typedef struct ty_gverb ty_gverb;
|
|
||||||
|
|
||||||
class Transform;
|
class Transform;
|
||||||
class NLPacket;
|
class NLPacket;
|
||||||
|
|
||||||
|
@ -263,7 +262,8 @@ private:
|
||||||
AudioEffectOptions _scriptReverbOptions;
|
AudioEffectOptions _scriptReverbOptions;
|
||||||
AudioEffectOptions _zoneReverbOptions;
|
AudioEffectOptions _zoneReverbOptions;
|
||||||
AudioEffectOptions* _reverbOptions;
|
AudioEffectOptions* _reverbOptions;
|
||||||
ty_gverb* _gverb;
|
AudioReverb _sourceReverb { AudioConstants::SAMPLE_RATE };
|
||||||
|
AudioReverb _listenerReverb { AudioConstants::SAMPLE_RATE };
|
||||||
|
|
||||||
// possible streams needed for resample
|
// possible streams needed for resample
|
||||||
AudioSRC* _inputToNetworkResampler;
|
AudioSRC* _inputToNetworkResampler;
|
||||||
|
@ -271,10 +271,8 @@ private:
|
||||||
AudioSRC* _loopbackResampler;
|
AudioSRC* _loopbackResampler;
|
||||||
|
|
||||||
// Adds Reverb
|
// Adds Reverb
|
||||||
ty_gverb* createGverbFilter();
|
void configureReverb();
|
||||||
void configureGverbFilter(ty_gverb* filter);
|
void updateReverbOptions();
|
||||||
void updateGverbOptions();
|
|
||||||
void addReverb(ty_gverb* gverb, int16_t* samples, int16_t* reverbAlone, int numSamples, QAudioFormat& format, bool noEcho = false);
|
|
||||||
|
|
||||||
void handleLocalEchoAndReverb(QByteArray& inputByteArray);
|
void handleLocalEchoAndReverb(QByteArray& inputByteArray);
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,10 @@ AudioEffectOptions::AudioEffectOptions(QScriptValue arguments) :
|
||||||
_damping(0.5f),
|
_damping(0.5f),
|
||||||
_spread(15.0f),
|
_spread(15.0f),
|
||||||
_inputBandwidth(0.75f),
|
_inputBandwidth(0.75f),
|
||||||
_earlyLevel(-22.0f),
|
_earlyLevel(-12.0f),
|
||||||
_tailLevel(-28.0f),
|
_tailLevel(-18.0f),
|
||||||
_dryLevel(0.0f),
|
_dryLevel(0.0f),
|
||||||
_wetLevel(6.0f) {
|
_wetLevel(0.0f) {
|
||||||
if (arguments.property(MAX_ROOM_SIZE_HANDLE).isNumber()) {
|
if (arguments.property(MAX_ROOM_SIZE_HANDLE).isNumber()) {
|
||||||
_maxRoomSize = arguments.property(MAX_ROOM_SIZE_HANDLE).toNumber();
|
_maxRoomSize = arguments.property(MAX_ROOM_SIZE_HANDLE).toNumber();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include <QtScript/QScriptContext>
|
#include <QtScript/QScriptContext>
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
|
|
||||||
|
#include "AudioReverb.h"
|
||||||
|
|
||||||
class AudioEffectOptions : public QObject {
|
class AudioEffectOptions : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
1965
libraries/audio/src/AudioReverb.cpp
Normal file
1965
libraries/audio/src/AudioReverb.cpp
Normal file
File diff suppressed because it is too large
Load diff
76
libraries/audio/src/AudioReverb.h
Normal file
76
libraries/audio/src/AudioReverb.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
//
|
||||||
|
// AudioReverb.h
|
||||||
|
// libraries/audio/src
|
||||||
|
//
|
||||||
|
// Created by Ken Cooke on 10/11/15.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_AudioReverb_h
|
||||||
|
#define hifi_AudioReverb_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct ReverbParameters {
|
||||||
|
|
||||||
|
float sampleRate; // [24000, 48000] Hz
|
||||||
|
float bandwidth; // [20, 24000] Hz
|
||||||
|
|
||||||
|
float preDelay; // [0, 333] ms
|
||||||
|
float lateDelay; // [0, 166] ms
|
||||||
|
|
||||||
|
float reverbTime; // [0.1, 100] seconds
|
||||||
|
|
||||||
|
float earlyDiffusion; // [0, 100] percent
|
||||||
|
float lateDiffusion; // [0, 100] percent
|
||||||
|
|
||||||
|
float roomSize; // [0, 100] percent
|
||||||
|
float density; // [0, 100] percent
|
||||||
|
|
||||||
|
float bassMult; // [0.1, 10] ratio
|
||||||
|
float bassFreq; // [10, 500] Hz
|
||||||
|
float highGain; // [-24, 0] dB
|
||||||
|
float highFreq; // [1000, 12000] Hz
|
||||||
|
|
||||||
|
float modRate; // [0.1, 10] Hz
|
||||||
|
float modDepth; // [0, 100] percent
|
||||||
|
|
||||||
|
float earlyGain; // [-96, +24] dB
|
||||||
|
float lateGain; // [-96, +24] dB
|
||||||
|
|
||||||
|
float earlyMixLeft; // [0, 100] percent
|
||||||
|
float earlyMixRight; // [0, 100] percent
|
||||||
|
float lateMixLeft; // [0, 100] percent
|
||||||
|
float lateMixRight; // [0, 100] percent
|
||||||
|
|
||||||
|
float wetDryMix; // [0, 100] percent
|
||||||
|
|
||||||
|
} ReverbParameters;
|
||||||
|
|
||||||
|
class ReverbImpl;
|
||||||
|
|
||||||
|
class AudioReverb {
|
||||||
|
public:
|
||||||
|
AudioReverb(float sampleRate);
|
||||||
|
~AudioReverb();
|
||||||
|
|
||||||
|
void setParameters(ReverbParameters *p);
|
||||||
|
void getParameters(ReverbParameters *p);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
// deinterleaved float input/output (native format)
|
||||||
|
void render(float** inputs, float** outputs, int numFrames);
|
||||||
|
|
||||||
|
// interleaved int16_t input/output
|
||||||
|
void render(const int16_t* input, int16_t* output, int numFrames);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReverbImpl *_impl;
|
||||||
|
ReverbParameters _params;
|
||||||
|
|
||||||
|
float* _inout[2];
|
||||||
|
void convertInputFromInt16(const int16_t* input, float** outputs, int numFrames);
|
||||||
|
void convertOutputToInt16(float** inputs, int16_t* output, int numFrames);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_AudioReverb_h
|
|
@ -1218,7 +1218,7 @@ static inline float dither() {
|
||||||
rz = rz * 69069 + 1;
|
rz = rz * 69069 + 1;
|
||||||
int32_t r0 = rz & 0xffff;
|
int32_t r0 = rz & 0xffff;
|
||||||
int32_t r1 = rz >> 16;
|
int32_t r1 = rz >> 16;
|
||||||
return (r0 - r1) * (1/65536.0f);
|
return (int32_t)(r0 - r1) * (1/65536.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert float to int16_t, interleave stereo
|
// convert float to int16_t, interleave stereo
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#ifndef hifi_AudioSRC_h
|
#ifndef hifi_AudioSRC_h
|
||||||
#define hifi_AudioSRC_h
|
#define hifi_AudioSRC_h
|
||||||
|
|
||||||
#include "stdint.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
class AudioSRC {
|
class AudioSRC {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue