Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply master gain outside audio devices #7135

Merged
merged 6 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions include/AudioDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,7 @@ class AudioDevice
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 );
Expand All @@ -109,7 +105,6 @@ class AudioDevice
// 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 );

Expand Down
4 changes: 1 addition & 3 deletions include/AudioFileFlac.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ class AudioFileFlac : public AudioFileDevice
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();
Expand Down
4 changes: 1 addition & 3 deletions include/AudioFileMP3.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ class AudioFileMP3 : public AudioFileDevice
}

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();
Expand Down
4 changes: 1 addition & 3 deletions include/AudioFileOgg.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ class AudioFileOgg : public AudioFileDevice


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();
Expand Down
4 changes: 1 addition & 3 deletions include/AudioFileWave.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ class AudioFileWave : public AudioFileDevice


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();
Expand Down
4 changes: 1 addition & 3 deletions include/AudioSampleRecorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ class AudioSampleRecorder : public AudioDevice
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;
Expand Down
2 changes: 2 additions & 0 deletions include/MixHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
3 changes: 3 additions & 0 deletions src/core/AudioEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "AudioEngine.h"

#include "MixHelpers.h"
#include "denormals.h"

#include "lmmsconfig.h"
Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions src/core/MixHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) );
Expand Down
5 changes: 1 addition & 4 deletions src/core/audio/AudioAlsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
17 changes: 5 additions & 12 deletions src/core/audio/AudioDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 )
{
Expand All @@ -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;
Expand All @@ -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);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/core/audio/AudioFileFlac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand All @@ -104,15 +104,15 @@ 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);
}
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);
}

Expand Down
9 changes: 3 additions & 6 deletions src/core/audio/AudioFileMP3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 3 additions & 8 deletions src/core/audio/AudioFileOgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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];
}
}

Expand Down Expand Up @@ -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 );
Expand Down
13 changes: 3 additions & 10 deletions src/core/audio/AudioFileWave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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 );
Expand All @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions src/core/audio/AudioJack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/core/audio/AudioOss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 1 addition & 5 deletions src/core/audio/AudioPortAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
}
}

Expand Down
5 changes: 1 addition & 4 deletions src/core/audio/AudioPulseAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 1 addition & 5 deletions src/core/audio/AudioSampleRecorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down
12 changes: 1 addition & 11 deletions src/core/audio/AudioSdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions src/core/audio/AudioSndio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading