Added minimum sample counting method for noise reduction

This commit is contained in:
Philip Rosedale 2014-02-11 23:44:22 -08:00
parent 1412d49a2f
commit 0322c8b934
3 changed files with 60 additions and 13 deletions

View file

@ -65,10 +65,10 @@ var numColors = 8;
var whichColor = -1; // Starting color is 'Copy' mode var whichColor = -1; // Starting color is 'Copy' mode
// Create sounds for adding, deleting, recoloring voxels // Create sounds for adding, deleting, recoloring voxels
var addSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst1.raw"); var addSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Switches+and+sliders/slider+-+whoosh1.raw");
var deleteSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Bubbles/bubbles1.raw"); var deleteSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Switches+and+sliders/slider+-+whoosh2.raw");
var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst6.raw"); var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst6.raw");
var clickSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Collisions-ballhitsandcatches/ballcatch2.raw"); var clickSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Switches+and+sliders/toggle+switch+-+medium.raw");
var audioOptions = new AudioInjectionOptions(); var audioOptions = new AudioInjectionOptions();
audioOptions.volume = 0.5; audioOptions.volume = 0.5;
@ -94,18 +94,18 @@ function mousePressEvent(event) {
if (intersection.intersects) { if (intersection.intersects) {
if (event.isAlt) { if (event.isAlt) {
// start orbit camera! // start orbit camera!
var cameraPosition = Camera.getPosition();
oldMode = Camera.getMode(); oldMode = Camera.getMode();
Camera.setMode("independent"); Camera.setMode("independent");
isOrbiting = true; isOrbiting = true;
Camera.keepLookingAt(intersection.intersection); Camera.keepLookingAt(intersection.intersection);
// get position for initial azimuth, elevation // get position for initial azimuth, elevation
orbitCenter = intersection.intersection; orbitCenter = intersection.intersection;
var cameraPosition = Camera.getPosition();
var orbitVector = Vec3.subtract(cameraPosition, orbitCenter); var orbitVector = Vec3.subtract(cameraPosition, orbitCenter);
orbitRadius = vLength(orbitVector); orbitRadius = vLength(orbitVector);
print("Orbit radius = " + orbitRadius);
orbitAzimuth = Math.atan(orbitVector.z / orbitVector.x); orbitAzimuth = Math.atan(orbitVector.z / orbitVector.x);
orbitAltitude = Math.atan(orbitVector.y / orbitVector.x); orbitAltitude = Math.atan(orbitVector.y / Math.sqrt(orbitVector.z * orbitVector.z + orbitVector.x * orbitVector.x));
print("start: radius, azimuth, altitude = " + orbitRadius + ", " + orbitAzimuth + ", " + orbitAltitude);
} else if (event.isRightButton || event.isControl) { } else if (event.isRightButton || event.isControl) {
// Delete voxel // Delete voxel
@ -210,6 +210,7 @@ function mouseMoveEvent(event) {
var dy = event.y - mouseY; var dy = event.y - mouseY;
orbitAzimuth += dx / ORBIT_RATE_AZIMUTH; orbitAzimuth += dx / ORBIT_RATE_AZIMUTH;
orbitAltitude += dy / ORBIT_RATE_ALTITUDE; orbitAltitude += dy / ORBIT_RATE_ALTITUDE;
print("drag: radius, azimuth, altitude = " + orbitRadius + ", " + orbitAzimuth + ", " + orbitAltitude);
//print("Azimuth, Altitude: " + orbitAzimuth + ", " + orbitAltitude); //print("Azimuth, Altitude: " + orbitAzimuth + ", " + orbitAltitude);
var orbitVector = { x:(Math.cos(orbitAzimuth) * Math.cos(orbitAltitude)) * orbitRadius, var orbitVector = { x:(Math.cos(orbitAzimuth) * Math.cos(orbitAltitude)) * orbitRadius,
y:Math.sin(orbitAltitude) * orbitRadius, y:Math.sin(orbitAltitude) * orbitRadius,
@ -261,11 +262,18 @@ function mouseMoveEvent(event) {
} }
function mouseReleaseEvent(event) { function mouseReleaseEvent(event) {
if (isOrbiting) {
var cameraOrientation = Camera.getOrientation();
var eulers = Quat.safeEulerAngles(cameraOrientation);
Camera.stopLooking();
print("pitch, yaw " + eulers.x + ", " + eulers.y);
MyAvatar.headPitch = eulers.x;
MyAvatar.bodyYaw = eulers.y;
MyAvatar.position = Camera.getPosition();
Camera.setMode(oldMode);
}
isAdding = false; isAdding = false;
isOrbiting = false; isOrbiting = false;
MyAvatar.position = orbitPosition;
Camera.stopLooking();
Camera.setMode(oldMode);
} }
Controller.mousePressEvent.connect(mousePressEvent); Controller.mousePressEvent.connect(mousePressEvent);

View file

@ -37,6 +37,8 @@ static const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_LENGTH_MSECS * NUM_AUDI
static const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float)SAMPLE_RATE * 1000.0; static const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float)SAMPLE_RATE * 1000.0;
static const int NUMBER_OF_NOISE_SAMPLE_FRAMES = 100;
// Mute icon configration // Mute icon configration
static const int ICON_SIZE = 24; static const int ICON_SIZE = 24;
static const int ICON_LEFT = 0; static const int ICON_LEFT = 0;
@ -66,6 +68,7 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
_jitterBufferSamples(initialJitterBufferSamples), _jitterBufferSamples(initialJitterBufferSamples),
_lastInputLoudness(0), _lastInputLoudness(0),
_averageInputLoudness(0), _averageInputLoudness(0),
_noiseGateSampleCounter(0),
_noiseGateOpen(false), _noiseGateOpen(false),
_noiseGateEnabled(true), _noiseGateEnabled(true),
_noiseGateFramesToClose(0), _noiseGateFramesToClose(0),
@ -82,6 +85,8 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
{ {
// clear the array of locally injected samples // clear the array of locally injected samples
memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
// Create the noise sample array
_noiseSampleFrames = new float[NUMBER_OF_NOISE_SAMPLE_FRAMES];
} }
void Audio::init(QGLWidget *parent) { void Audio::init(QGLWidget *parent) {
@ -355,9 +360,17 @@ void Audio::handleAudioInput() {
float thisSample = 0; float thisSample = 0;
int samplesOverNoiseGate = 0; int samplesOverNoiseGate = 0;
const float NOISE_GATE_HEIGHT = 3.f; #define NOISE_MIN_SAMPLE
#ifdef NOISE_MIN_SAMPLE
const float NOISE_GATE_HEIGHT = 12.f;
const int NOISE_GATE_WIDTH = 5; const int NOISE_GATE_WIDTH = 5;
const int NOISE_GATE_CLOSE_FRAME_DELAY = 30; const int NOISE_GATE_CLOSE_FRAME_DELAY = 5;
#else
const float NOISE_GATE_HEIGHT = 6.f;
const int NOISE_GATE_WIDTH = 5;
const int NOISE_GATE_CLOSE_FRAME_DELAY = 5;
#endif
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
thisSample = fabsf(monoAudioSamples[i]); thisSample = fabsf(monoAudioSamples[i]);
@ -368,8 +381,32 @@ void Audio::handleAudioInput() {
} }
} }
_lastInputLoudness = loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; _lastInputLoudness = loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
//qDebug("%.1f", _lastInputLoudness);
#ifdef NOISE_MIN_SAMPLE
_noiseSampleFrames[_noiseGateSampleCounter++] = _lastInputLoudness;
if (_noiseGateSampleCounter == NUMBER_OF_NOISE_SAMPLE_FRAMES) {
float smallestSample = MAXFLOAT;
for (int i = 0; i < NUMBER_OF_NOISE_SAMPLE_FRAMES; i++) {
if (_noiseSampleFrames[i] < smallestSample) {
smallestSample = _noiseSampleFrames[i];
}
}
_averageInputLoudness = smallestSample;
_noiseGateSampleCounter = 0;
qDebug("smallest sample = %.1f", _averageInputLoudness);
}
#else
_noiseGateSampleCounter++;
if (_noiseGateSampleCounter == NUMBER_OF_NOISE_SAMPLE_FRAMES) {
qDebug("average loudness = %.1f", _averageInputLoudness);
_noiseGateSampleCounter = 0;
}
const float LOUDNESS_AVERAGING_FRAMES = 1000.f; // This will be about 10 seconds const float LOUDNESS_AVERAGING_FRAMES = 1000.f; // This will be about 10 seconds
_averageInputLoudness = (1.f - 1.f / LOUDNESS_AVERAGING_FRAMES) * _averageInputLoudness + (1.f / LOUDNESS_AVERAGING_FRAMES) * _lastInputLoudness; _averageInputLoudness = (1.f - 1.f / LOUDNESS_AVERAGING_FRAMES) * _averageInputLoudness + (1.f / LOUDNESS_AVERAGING_FRAMES) * _lastInputLoudness;
#endif
if (_noiseGateEnabled) { if (_noiseGateEnabled) {
if (samplesOverNoiseGate > NOISE_GATE_WIDTH) { if (samplesOverNoiseGate > NOISE_GATE_WIDTH) {
@ -487,7 +524,7 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) {
if (!_ringBuffer.isStarved() && _audioOutput->bytesFree() == _audioOutput->bufferSize()) { if (!_ringBuffer.isStarved() && _audioOutput->bytesFree() == _audioOutput->bufferSize()) {
// we don't have any audio data left in the output buffer // we don't have any audio data left in the output buffer
// we just starved // we just starved
qDebug() << "Audio output just starved."; //qDebug() << "Audio output just starved.";
_ringBuffer.setIsStarved(true); _ringBuffer.setIsStarved(true);
_numFramesDisplayStarve = 10; _numFramesDisplayStarve = 10;
} }
@ -505,7 +542,7 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) {
if (!_ringBuffer.isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO if (!_ringBuffer.isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO
+ (_jitterBufferSamples * 2))) { + (_jitterBufferSamples * 2))) {
// starved and we don't have enough to start, keep waiting // starved and we don't have enough to start, keep waiting
qDebug() << "Buffer is starved and doesn't have enough samples to start. Held back."; //qDebug() << "Buffer is starved and doesn't have enough samples to start. Held back.";
} else { } else {
// We are either already playing back, or we have enough audio to start playing back. // We are either already playing back, or we have enough audio to start playing back.
_ringBuffer.setIsStarved(false); _ringBuffer.setIsStarved(false);

View file

@ -110,6 +110,8 @@ private:
int16_t _jitterBufferSamples; int16_t _jitterBufferSamples;
float _lastInputLoudness; float _lastInputLoudness;
float _averageInputLoudness; float _averageInputLoudness;
float* _noiseSampleFrames;
int _noiseGateSampleCounter;
bool _noiseGateOpen; bool _noiseGateOpen;
bool _noiseGateEnabled; bool _noiseGateEnabled;
int _noiseGateFramesToClose; int _noiseGateFramesToClose;