Improved the audio volume adjustment algorithm

This commit is contained in:
WolverinDEV 2020-08-09 14:58:16 +02:00
parent bb41c6e2a0
commit 598b1dd493
9 changed files with 61 additions and 43 deletions

View File

@ -10,6 +10,7 @@ set(SOURCE_FILES
src/connection/ft/FileTransferManager.cpp
src/connection/ft/FileTransferObject.cpp
src/audio/AudioGain.cpp
src/audio/AudioSamples.cpp
src/audio/AudioMerger.cpp
src/audio/AudioOutput.cpp

View File

@ -0,0 +1,27 @@
//
// Created by WolverinDEV on 09/08/2020.
//
#include "AudioGain.h"
#include "../logger.h"
bool tc::audio::apply_gain(void *vp_buffer, size_t channel_count, size_t sample_count, float gain) {
if(gain == 1.f)
return false;
bool audio_clipped{false};
auto buffer = (float*) vp_buffer;
auto elements_left = channel_count * sample_count;
while (elements_left--) {
auto& value = *buffer++;
value *= gain;
if(value > 1.f) {
log_debug(category::audio, tr("Audio gain apply clipped: {}"), (float) value);
value = 1.f;
audio_clipped = true;
}
}
return audio_clipped;
}

View File

@ -0,0 +1,8 @@
#pragma once
namespace tc::audio {
/**
* @return true if audio clipped
*/
extern bool apply_gain(void* /* buffer */, size_t /* channel count */, size_t /* sample count */, float /* gain */);
}

View File

@ -5,6 +5,7 @@
#include "./AudioReframer.h"
#include "./AudioResampler.h"
#include "../logger.h"
#include "AudioGain.h"
using namespace std;
using namespace tc;
@ -298,12 +299,7 @@ void AudioInput::consume(const void *input, size_t frameCount, size_t channels)
frameCount = (size_t) result;
input = this->resample_buffer;
if(this->_volume != 1) {
auto ptr = (float*) input;
auto left = frameCount * this->_channel_count;
while(left-- > 0)
*(ptr++) *= this->_volume;
}
audio::apply_gain(input, this->_channel_count, frameCount);
} else if(this->_volume != 1) {
const auto byte_size = frameCount * this->_channel_count * sizeof(float);
if(this->resample_buffer_size < byte_size) {
@ -316,10 +312,7 @@ void AudioInput::consume(const void *input, size_t frameCount, size_t channels)
input = this->resample_buffer;
auto ptr = (float*) input;
auto left = frameCount * this->_channel_count;
while(left-- > 0)
*(ptr++) *= this->_volume;
audio::apply_gain(input, this->_channel_count, frameCount);
}
auto begin = chrono::system_clock::now();

View File

@ -2,6 +2,7 @@
#include "./AudioMerger.h"
#include "./AudioResampler.h"
#include "../logger.h"
#include "AudioGain.h"
#include <cstring>
#include <algorithm>
#include <string>
@ -418,14 +419,7 @@ void AudioOutput::fill_buffer(void *output, size_t out_frame_count, size_t out_c
}
/* lets apply the volume */
auto volume = this->_volume;
if(volume != 1) {
auto float_length = this->_channel_count * out_frame_count;
auto data = (float*) output;
while(float_length-- > 0)
*data++ *= volume;
}
audio::apply_gain(output, this->_channel_count, out_frame_count, this->_volume);
} else {
clear_buffer_exit:
memset(output, 0, this->_channel_count * sizeof(float) * out_frame_count);

View File

@ -3,25 +3,23 @@
#include <functional>
#include <cstdio>
namespace tc {
namespace audio {
class Reframer {
public:
Reframer(size_t channels, size_t frame_size);
virtual ~Reframer();
namespace tc::audio {
class Reframer {
public:
Reframer(size_t channels, size_t frame_size);
virtual ~Reframer();
void process(const void* /* source */, size_t /* samples */);
void process(const void* /* source */, size_t /* samples */);
inline size_t channels() { return this->_channels; }
inline size_t frame_size() { return this->_frame_size; }
inline size_t channels() { return this->_channels; }
inline size_t frame_size() { return this->_frame_size; }
std::function<void(const void* /* buffer */)> on_frame;
private:
void* buffer;
size_t _buffer_index;
std::function<void(const void* /* buffer */)> on_frame;
private:
void* buffer;
size_t _buffer_index;
size_t _channels;
size_t _frame_size;
};
}
size_t _channels;
size_t _frame_size;
};
}

View File

@ -13,6 +13,7 @@
#include "../AudioEventLoop.h"
#include "../AudioResampler.h"
#include "../AudioMerger.h"
#include "../AudioGain.h"
#ifdef max
#undef max
@ -148,6 +149,7 @@ namespace tc::audio::sounds {
return;
}
audio::apply_gain(this->cache_buffer, this->output_source->channel_count, resampled_samples, this->settings_.volume);
this->output_source->enqueue_samples(this->cache_buffer, resampled_samples);
if(this->could_enqueue_next_buffer())
audio::decode_event_loop->schedule(this->shared_from_this());

View File

@ -18,7 +18,7 @@ namespace tc::audio::sounds {
typedef std::function<void(PlaybackResult, const std::string&)> callback_status_t;
struct PlaybackSettings {
std::string file{};
double volume{1.f};
float volume{1.f};
/* ATTENTION: This callback may be called within the audio loop! */
callback_status_t callback{};
};

View File

@ -6,6 +6,7 @@
#include "../../audio/js/AudioOutputStream.h"
#include "../../audio/AudioEventLoop.h"
#include "../../logger.h"
#include "../../audio/AudioGain.h"
using namespace std;
using namespace tc;
@ -706,13 +707,7 @@ std::shared_ptr<audio::SampleBuffer> VoiceClient::decode_buffer(const codec::val
return nullptr;
}
if(this->volume_ != 1) {
auto buf = (float*) target_buffer;
auto count = this->output_source->channel_count * resampled_samples;
while(count-- > 0)
*(buf++) *= this->volume_;
}
audio::apply_gain(target_buffer, this->output_source->channel_count, resampled_samples, this->volume_);
auto audio_buffer = audio::SampleBuffer::allocate((uint8_t) this->output_source->channel_count, (uint16_t) resampled_samples);
audio_buffer->sample_index = 0;