Apply master gain outside audio devices (#7135)
This commit is contained in:
@@ -96,11 +96,7 @@ public:
|
||||
protected:
|
||||
// subclasses can re-implement this for being used in conjunction with
|
||||
// processNextBuffer()
|
||||
virtual void writeBuffer( const surroundSampleFrame * /* _buf*/,
|
||||
const fpp_t /*_frames*/,
|
||||
const float /*_master_gain*/ )
|
||||
{
|
||||
}
|
||||
virtual void writeBuffer(const surroundSampleFrame* /* _buf*/, const fpp_t /*_frames*/) {}
|
||||
|
||||
// called by according driver for fetching new sound-data
|
||||
fpp_t getNextBuffer( surroundSampleFrame * _ab );
|
||||
@@ -109,7 +105,6 @@ protected:
|
||||
// returns num of bytes in outbuf
|
||||
int convertToS16( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain,
|
||||
int_sample_t * _output_buffer,
|
||||
const bool _convert_endian = false );
|
||||
|
||||
|
||||
@@ -65,9 +65,7 @@ private:
|
||||
SF_INFO m_sfinfo;
|
||||
SNDFILE* m_sf;
|
||||
|
||||
void writeBuffer(surroundSampleFrame const* _ab,
|
||||
fpp_t const frames,
|
||||
float master_gain) override;
|
||||
void writeBuffer(surroundSampleFrame const* _ab, fpp_t const frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
|
||||
@@ -58,9 +58,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void writeBuffer( const surroundSampleFrame * /* _buf*/,
|
||||
const fpp_t /*_frames*/,
|
||||
const float /*_master_gain*/ ) override;
|
||||
void writeBuffer(const surroundSampleFrame* /* _buf*/, const fpp_t /*_frames*/) override;
|
||||
|
||||
private:
|
||||
void flushRemainingBuffers();
|
||||
|
||||
@@ -58,9 +58,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain ) override;
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
|
||||
@@ -56,9 +56,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
float _master_gain ) override;
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
|
||||
@@ -48,9 +48,7 @@ public:
|
||||
std::shared_ptr<const SampleBuffer> createSampleBuffer();
|
||||
|
||||
private:
|
||||
void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain ) override;
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
using BufferList = QList<QPair<sampleFrame*, fpp_t>>;
|
||||
BufferList m_buffers;
|
||||
|
||||
@@ -45,6 +45,8 @@ bool sanitize( sampleFrame * src, int frames );
|
||||
/*! \brief Add samples from src to dst */
|
||||
void add( sampleFrame* dst, const sampleFrame* src, int frames );
|
||||
|
||||
/*! \brief Multiply samples from `dst` by `coeff` */
|
||||
void multiply(sampleFrame* dst, float coeff, int frames);
|
||||
|
||||
/*! \brief Add samples from src multiplied by coeffSrc to dst */
|
||||
void addMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames );
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "AudioEngine.h"
|
||||
|
||||
#include "MixHelpers.h"
|
||||
#include "denormals.h"
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
@@ -433,6 +434,8 @@ void AudioEngine::renderStageMix()
|
||||
Mixer *mixer = Engine::mixer();
|
||||
mixer->masterMix(m_outputBufferWrite);
|
||||
|
||||
MixHelpers::multiply(m_outputBufferWrite, m_masterGain, m_framesPerPeriod);
|
||||
|
||||
emit nextAudioBuffer(m_outputBufferRead);
|
||||
|
||||
// and trigger LFOs
|
||||
|
||||
@@ -178,6 +178,15 @@ struct AddSwappedMultipliedOp
|
||||
const float m_coeff;
|
||||
};
|
||||
|
||||
void multiply(sampleFrame* dst, float coeff, int frames)
|
||||
{
|
||||
for (int i = 0; i < frames; ++i)
|
||||
{
|
||||
dst[i][0] *= coeff;
|
||||
dst[i][1] *= coeff;
|
||||
}
|
||||
}
|
||||
|
||||
void addSwappedMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames )
|
||||
{
|
||||
run<>( dst, src, frames, AddSwappedMultipliedOp(coeffSrc) );
|
||||
|
||||
@@ -323,10 +323,7 @@ void AudioAlsa::run()
|
||||
}
|
||||
outbuf_size = frames * channels();
|
||||
|
||||
convertToS16( temp, frames,
|
||||
audioEngine()->masterGain(),
|
||||
outbuf,
|
||||
m_convertEndian );
|
||||
convertToS16(temp, frames, outbuf, m_convertEndian);
|
||||
}
|
||||
int min_len = std::min(len, outbuf_size - outbuf_pos);
|
||||
memcpy( ptr, outbuf + outbuf_pos,
|
||||
|
||||
@@ -66,10 +66,7 @@ AudioDevice::~AudioDevice()
|
||||
void AudioDevice::processNextBuffer()
|
||||
{
|
||||
const fpp_t frames = getNextBuffer( m_buffer );
|
||||
if( frames )
|
||||
{
|
||||
writeBuffer( m_buffer, frames, audioEngine()->masterGain() );
|
||||
}
|
||||
if (frames) { writeBuffer(m_buffer, frames); }
|
||||
else
|
||||
{
|
||||
m_inProcess = false;
|
||||
@@ -211,7 +208,6 @@ fpp_t AudioDevice::resample( const surroundSampleFrame * _src,
|
||||
|
||||
int AudioDevice::convertToS16( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain,
|
||||
int_sample_t * _output_buffer,
|
||||
const bool _convert_endian )
|
||||
{
|
||||
@@ -222,8 +218,8 @@ int AudioDevice::convertToS16( const surroundSampleFrame * _ab,
|
||||
{
|
||||
for( ch_cnt_t chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
temp = static_cast<int_sample_t>( AudioEngine::clip( _ab[frame][chnl] * _master_gain ) * OUTPUT_SAMPLE_MULTIPLIER );
|
||||
|
||||
temp = static_cast<int_sample_t>(AudioEngine::clip(_ab[frame][chnl]) * OUTPUT_SAMPLE_MULTIPLIER);
|
||||
|
||||
( _output_buffer + frame * channels() )[chnl] =
|
||||
( temp & 0x00ff ) << 8 |
|
||||
( temp & 0xff00 ) >> 8;
|
||||
@@ -236,11 +232,8 @@ int AudioDevice::convertToS16( const surroundSampleFrame * _ab,
|
||||
{
|
||||
for( ch_cnt_t chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
( _output_buffer + frame * channels() )[chnl] =
|
||||
static_cast<int_sample_t>(
|
||||
AudioEngine::clip( _ab[frame][chnl] *
|
||||
_master_gain ) *
|
||||
OUTPUT_SAMPLE_MULTIPLIER );
|
||||
(_output_buffer + frame * channels())[chnl]
|
||||
= static_cast<int_sample_t>(AudioEngine::clip(_ab[frame][chnl]) * OUTPUT_SAMPLE_MULTIPLIER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ bool AudioFileFlac::startEncoding()
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const frames, float master_gain)
|
||||
void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const frames)
|
||||
{
|
||||
OutputSettings::BitDepth depth = getOutputSettings().getBitDepth();
|
||||
float clipvalue = std::nextafterf( -1.0f, 0.0f );
|
||||
@@ -104,7 +104,7 @@ void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const fram
|
||||
// Clip the negative side to just above -1.0 in order to prevent it from changing sign
|
||||
// Upstream issue: https://github.com/erikd/libsndfile/issues/309
|
||||
// When this commit is reverted libsndfile-1.0.29 must be made a requirement for FLAC
|
||||
buf[frame*channels() + channel] = std::max(clipvalue, _ab[frame][channel] * master_gain);
|
||||
buf[frame*channels() + channel] = std::max(clipvalue, _ab[frame][channel]);
|
||||
}
|
||||
}
|
||||
sf_writef_float(m_sf, static_cast<float*>(buf.data()), frames);
|
||||
@@ -112,7 +112,7 @@ void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const fram
|
||||
else // integer PCM encoding
|
||||
{
|
||||
auto buf = std::vector<int_sample_t>(frames * channels());
|
||||
convertToS16(_ab, frames, master_gain, buf.data(), !isLittleEndian());
|
||||
convertToS16(_ab, frames, buf.data(), !isLittleEndian());
|
||||
sf_writef_short(m_sf, static_cast<short*>(buf.data()), frames);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,21 +53,18 @@ AudioFileMP3::~AudioFileMP3()
|
||||
tearDownEncoder();
|
||||
}
|
||||
|
||||
void AudioFileMP3::writeBuffer( const surroundSampleFrame * _buf,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain )
|
||||
void AudioFileMP3::writeBuffer(const surroundSampleFrame* _buf, const fpp_t _frames)
|
||||
{
|
||||
if (_frames < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO Why isn't the gain applied by the driver but inside the device?
|
||||
std::vector<float> interleavedDataBuffer(_frames * 2);
|
||||
for (fpp_t i = 0; i < _frames; ++i)
|
||||
{
|
||||
interleavedDataBuffer[2*i] = _buf[i][0] * _master_gain;
|
||||
interleavedDataBuffer[2*i + 1] = _buf[i][1] * _master_gain;
|
||||
interleavedDataBuffer[2*i] = _buf[i][0];
|
||||
interleavedDataBuffer[2*i + 1] = _buf[i][1];
|
||||
}
|
||||
|
||||
size_t minimumBufferSize = 1.25 * _frames + 7200;
|
||||
|
||||
@@ -185,12 +185,7 @@ bool AudioFileOgg::startEncoding()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioFileOgg::writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain )
|
||||
void AudioFileOgg::writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames)
|
||||
{
|
||||
int eos = 0;
|
||||
|
||||
@@ -201,7 +196,7 @@ void AudioFileOgg::writeBuffer( const surroundSampleFrame * _ab,
|
||||
{
|
||||
for( ch_cnt_t chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
buffer[chnl][frame] = _ab[frame][chnl] * _master_gain;
|
||||
buffer[chnl][frame] = _ab[frame][chnl];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +253,7 @@ void AudioFileOgg::finishEncoding()
|
||||
if( m_ok )
|
||||
{
|
||||
// just for flushing buffers...
|
||||
writeBuffer( nullptr, 0, 0.0f );
|
||||
writeBuffer(nullptr, 0);
|
||||
|
||||
// clean up
|
||||
ogg_stream_clear( &m_os );
|
||||
|
||||
@@ -93,12 +93,7 @@ bool AudioFileWave::startEncoding()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioFileWave::writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain )
|
||||
void AudioFileWave::writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames)
|
||||
{
|
||||
OutputSettings::BitDepth bitDepth = getOutputSettings().getBitDepth();
|
||||
|
||||
@@ -109,8 +104,7 @@ void AudioFileWave::writeBuffer( const surroundSampleFrame * _ab,
|
||||
{
|
||||
for( ch_cnt_t chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
buf[frame*channels()+chnl] = _ab[frame][chnl] *
|
||||
_master_gain;
|
||||
buf[frame * channels() + chnl] = _ab[frame][chnl];
|
||||
}
|
||||
}
|
||||
sf_writef_float( m_sf, buf, _frames );
|
||||
@@ -119,8 +113,7 @@ void AudioFileWave::writeBuffer( const surroundSampleFrame * _ab,
|
||||
else
|
||||
{
|
||||
auto buf = new int_sample_t[_frames * channels()];
|
||||
convertToS16( _ab, _frames, _master_gain, buf,
|
||||
!isLittleEndian() );
|
||||
convertToS16(_ab, _frames, buf, !isLittleEndian());
|
||||
|
||||
sf_writef_short( m_sf, buf, _frames );
|
||||
delete[] buf;
|
||||
|
||||
@@ -344,13 +344,12 @@ int AudioJack::processCallback(jack_nframes_t nframes)
|
||||
while (done < nframes && !m_stopped)
|
||||
{
|
||||
jack_nframes_t todo = std::min<jack_nframes_t>(nframes - done, m_framesToDoInCurBuf - m_framesDoneInCurBuf);
|
||||
const float gain = audioEngine()->masterGain();
|
||||
for (int c = 0; c < channels(); ++c)
|
||||
{
|
||||
jack_default_audio_sample_t* o = m_tempOutBufs[c];
|
||||
for (jack_nframes_t frame = 0; frame < todo; ++frame)
|
||||
{
|
||||
o[done + frame] = m_outBuf[m_framesDoneInCurBuf + frame][c] * gain;
|
||||
o[done + frame] = m_outBuf[m_framesDoneInCurBuf + frame][c];
|
||||
}
|
||||
}
|
||||
done += todo;
|
||||
|
||||
@@ -303,7 +303,7 @@ void AudioOss::run()
|
||||
break;
|
||||
}
|
||||
|
||||
int bytes = convertToS16( temp, frames, audioEngine()->masterGain(), outbuf, m_convertEndian );
|
||||
int bytes = convertToS16(temp, frames, outbuf, m_convertEndian);
|
||||
if( write( m_audioFD, outbuf, bytes ) != bytes )
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -298,15 +298,11 @@ int AudioPortAudio::process_callback(
|
||||
const int min_len = std::min(static_cast<int>(_framesPerBuffer),
|
||||
m_outBufSize - m_outBufPos);
|
||||
|
||||
float master_gain = audioEngine()->masterGain();
|
||||
|
||||
for( fpp_t frame = 0; frame < min_len; ++frame )
|
||||
{
|
||||
for( ch_cnt_t chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
( _outputBuffer + frame * channels() )[chnl] =
|
||||
AudioEngine::clip( m_outBuf[frame][chnl] *
|
||||
master_gain );
|
||||
(_outputBuffer + frame * channels())[chnl] = AudioEngine::clip(m_outBuf[frame][chnl]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -278,10 +278,7 @@ void AudioPulseAudio::streamWriteCallback( pa_stream *s, size_t length )
|
||||
m_quit = true;
|
||||
break;
|
||||
}
|
||||
int bytes = convertToS16( temp, frames,
|
||||
audioEngine()->masterGain(),
|
||||
pcmbuf,
|
||||
m_convertEndian );
|
||||
int bytes = convertToS16(temp, frames, pcmbuf, m_convertEndian);
|
||||
if( bytes > 0 )
|
||||
{
|
||||
pa_stream_write( m_s, pcmbuf, bytes, nullptr, 0,
|
||||
|
||||
@@ -85,11 +85,7 @@ std::shared_ptr<const SampleBuffer> AudioSampleRecorder::createSampleBuffer()
|
||||
return std::make_shared<const SampleBuffer>(std::move(bigBuffer), sampleRate());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioSampleRecorder::writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames, const float )
|
||||
void AudioSampleRecorder::writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames)
|
||||
{
|
||||
auto buf = new sampleFrame[_frames];
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
|
||||
@@ -261,13 +261,6 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len )
|
||||
m_currentBufferFramesCount
|
||||
- m_currentBufferFramePos);
|
||||
|
||||
const float gain = audioEngine()->masterGain();
|
||||
for (uint f = 0; f < min_frames_count; f++)
|
||||
{
|
||||
(m_outBuf + m_currentBufferFramePos)[f][0] *= gain;
|
||||
(m_outBuf + m_currentBufferFramePos)[f][1] *= gain;
|
||||
}
|
||||
|
||||
memcpy( _buf, m_outBuf + m_currentBufferFramePos, min_frames_count*sizeof(sampleFrame) );
|
||||
_buf += min_frames_count*sizeof(sampleFrame);
|
||||
_len -= min_frames_count*sizeof(sampleFrame);
|
||||
@@ -291,10 +284,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len )
|
||||
m_convertedBufSize = frames * channels()
|
||||
* sizeof( int_sample_t );
|
||||
|
||||
convertToS16( m_outBuf, frames,
|
||||
audioEngine()->masterGain(),
|
||||
(int_sample_t *)m_convertedBuf,
|
||||
m_outConvertEndian );
|
||||
convertToS16(m_outBuf, frames, reinterpret_cast<int_sample_t*>(m_convertedBuf), m_outConvertEndian);
|
||||
}
|
||||
const int min_len = std::min(_len, m_convertedBufSize
|
||||
- m_convertedBufPos);
|
||||
|
||||
@@ -167,8 +167,7 @@ void AudioSndio::run()
|
||||
break;
|
||||
}
|
||||
|
||||
uint bytes = convertToS16( temp, frames,
|
||||
audioEngine()->masterGain(), outbuf, m_convertEndian );
|
||||
uint bytes = convertToS16(temp, frames, outbuf, m_convertEndian);
|
||||
if( sio_write( m_hdl, outbuf, bytes ) != bytes )
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -286,8 +286,6 @@ void AudioSoundIo::writeCallback(int frameCountMin, int frameCountMax)
|
||||
int bytesPerSample = m_outstream->bytes_per_sample;
|
||||
int err;
|
||||
|
||||
const float gain = audioEngine()->masterGain();
|
||||
|
||||
int framesLeft = frameCountMax;
|
||||
|
||||
while (framesLeft > 0)
|
||||
@@ -328,7 +326,7 @@ void AudioSoundIo::writeCallback(int frameCountMin, int frameCountMax)
|
||||
|
||||
for (int channel = 0; channel < layout->channel_count; channel += 1)
|
||||
{
|
||||
float sample = gain * m_outBuf[m_outBufFrameIndex][channel];
|
||||
float sample = m_outBuf[m_outBufFrameIndex][channel];
|
||||
memcpy(areas[channel].ptr, &sample, bytesPerSample);
|
||||
areas[channel].ptr += areas[channel].step;
|
||||
}
|
||||
|
||||
@@ -603,10 +603,6 @@ void MixerView::updateFaders()
|
||||
{
|
||||
Mixer * m = getMixer();
|
||||
|
||||
// apply master gain
|
||||
m->mixerChannel(0)->m_peakLeft *= Engine::audioEngine()->masterGain();
|
||||
m->mixerChannel(0)->m_peakRight *= Engine::audioEngine()->masterGain();
|
||||
|
||||
for (int i = 0; i < m_mixerChannelViews.size(); ++i)
|
||||
{
|
||||
const float opl = m_mixerChannelViews[i]->m_fader->getPeak_L();
|
||||
|
||||
@@ -143,14 +143,14 @@ void Oscilloscope::paintEvent( QPaintEvent * )
|
||||
{
|
||||
AudioEngine const * audioEngine = Engine::audioEngine();
|
||||
|
||||
float master_output = audioEngine->masterGain();
|
||||
float masterOutput = audioEngine->masterGain();
|
||||
|
||||
const fpp_t frames = audioEngine->framesPerPeriod();
|
||||
AudioEngine::StereoSample peakValues = audioEngine->getPeakValues(m_buffer, frames);
|
||||
const float max_level = qMax<float>( peakValues.left, peakValues.right );
|
||||
|
||||
// Set the color of the line according to the maximum level
|
||||
float const maxLevelWithAppliedMasterGain = max_level * master_output;
|
||||
float const maxLevelWithAppliedMasterGain = max_level * masterOutput;
|
||||
p.setPen(QPen(determineLineColor(maxLevelWithAppliedMasterGain), 0.7));
|
||||
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
@@ -158,7 +158,7 @@ void Oscilloscope::paintEvent( QPaintEvent * )
|
||||
// now draw all that stuff
|
||||
int w = width() - 4;
|
||||
const qreal xd = static_cast<qreal>(w) / frames;
|
||||
const qreal half_h = -( height() - 6 ) / 3.0 * static_cast<qreal>(master_output) - 1;
|
||||
const qreal half_h = -(height() - 6) / 3.0 * static_cast<qreal>(masterOutput) - 1;
|
||||
int x_base = 2;
|
||||
const qreal y_base = height() / 2 - 0.5;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user