Index: libopenmpt/libopenmpt_impl.cpp =================================================================== --- libopenmpt/libopenmpt_impl.cpp (revision 9521) +++ libopenmpt/libopenmpt_impl.cpp (working copy) @@ -450,6 +450,7 @@ m_current_subsong = 0; m_currentPositionSeconds = 0.0; m_Gain = 1.0f; + m_AutoGain = 1.0f; m_ctl_play_at_end = song_end_action::fadeout_song; m_ctl_load_skip_samples = false; m_ctl_load_skip_patterns = false; @@ -493,6 +494,7 @@ for ( const auto & ctl : ctls ) { ctl_set( ctl.first, ctl.second, false ); } + update_autogain(); } bool module_impl::is_loaded() const { return m_loaded; @@ -503,7 +505,7 @@ std::size_t count_read = 0; while ( count > 0 ) { std::int16_t * const buffers[4] = { left + count_read, right + count_read, rear_left + count_read, rear_right + count_read }; - AudioReadTargetGainBuffer target(*m_Dither, 0, buffers, m_Gain); + AudioReadTargetGainBuffer target(*m_Dither, 0, buffers, m_Gain * m_AutoGain); std::size_t count_chunk = m_sndFile->Read( static_cast( std::min( count, std::numeric_limits::max() / 2 / 4 / 4 ) ), // safety margin / samplesize / channels target @@ -526,7 +528,7 @@ std::size_t count_read = 0; while ( count > 0 ) { float * const buffers[4] = { left + count_read, right + count_read, rear_left + count_read, rear_right + count_read }; - AudioReadTargetGainBuffer target(*m_Dither, 0, buffers, m_Gain); + AudioReadTargetGainBuffer target(*m_Dither, 0, buffers, m_Gain * m_AutoGain); std::size_t count_chunk = m_sndFile->Read( static_cast( std::min( count, std::numeric_limits::max() / 2 / 4 / 4 ) ), // safety margin / samplesize / channels target @@ -548,7 +550,7 @@ m_sndFile->m_bIsRendering = ( m_ctl_play_at_end != song_end_action::fadeout_song ); std::size_t count_read = 0; while ( count > 0 ) { - AudioReadTargetGainBuffer target(*m_Dither, interleaved + count_read * channels, 0, m_Gain); + AudioReadTargetGainBuffer target(*m_Dither, interleaved + count_read * channels, 0, m_Gain * m_AutoGain); std::size_t count_chunk = m_sndFile->Read( static_cast( std::min( count, std::numeric_limits::max() / 2 / 4 / 4 ) ), // safety margin / samplesize / channels target @@ -570,7 +572,7 @@ m_sndFile->m_bIsRendering = ( m_ctl_play_at_end != song_end_action::fadeout_song ); std::size_t count_read = 0; while ( count > 0 ) { - AudioReadTargetGainBuffer target(*m_Dither, interleaved + count_read * channels, 0, m_Gain); + AudioReadTargetGainBuffer target(*m_Dither, interleaved + count_read * channels, 0, m_Gain * m_AutoGain); std::size_t count_chunk = m_sndFile->Read( static_cast( std::min( count, std::numeric_limits::max() / 2 / 4 / 4 ) ), // safety margin / samplesize / channels target @@ -1658,4 +1660,42 @@ } } +void module_impl::update_autogain() { + std::int32_t current_subsong = get_selected_subsong(); + select_subsong( all_subsongs); + + std::uint64_t samples = Util::Round( get_duration_seconds() * 1000.0 ); + float buffer[512]; + auto old_dither = m_Dither->GetMode(); + m_Dither->SetMode( DitherNone ); + auto orig_settings = m_sndFile->m_Resampler.m_Settings, new_settings = m_sndFile->m_Resampler.m_Settings; + new_settings.emulateAmiga = false; + new_settings.SrcMode = SRCMODE_NEAREST; + m_sndFile->SetResamplerSettings( new_settings ); + + apply_mixer_settings( 1000, 1 ); + float peak = 0.0f; + while ( samples > 0 ) { + AudioReadTargetBuffer target(*m_Dither, buffer, nullptr ); + std::size_t count_chunk = m_sndFile->Read( + static_cast( std::min( mpt::size(buffer), samples ) ), + target + ); + if(count_chunk == 0) { + break; + } + auto minmax = std::minmax_element( std::begin( buffer ), std::begin( buffer ) + count_chunk ); + peak = std::max( { peak, mpt::abs(*minmax.first), mpt::abs(*minmax.second) } ); + samples -= count_chunk; + } + + m_Dither->SetMode( old_dither ); + m_sndFile->SetResamplerSettings( orig_settings ); + select_subsong( current_subsong ); + + if ( peak > 0.0f ) { + m_AutoGain = 1.0f / peak; + } +} + } // namespace openmpt Index: libopenmpt/libopenmpt_impl.hpp =================================================================== --- libopenmpt/libopenmpt_impl.hpp (revision 9521) +++ libopenmpt/libopenmpt_impl.hpp (working copy) @@ -98,7 +98,7 @@ bool m_loaded; std::unique_ptr m_Dither; subsongs_type m_subsongs; - float m_Gain; + float m_Gain, m_AutoGain; song_end_action m_ctl_play_at_end; bool m_ctl_load_skip_samples; bool m_ctl_load_skip_patterns; @@ -126,6 +126,7 @@ std::pair< std::string, std::string > format_and_highlight_pattern_row_channel_command( std::int32_t p, std::int32_t r, std::int32_t c, int command ) const; std::pair< std::string, std::string > format_and_highlight_pattern_row_channel( std::int32_t p, std::int32_t r, std::int32_t c, std::size_t width, bool pad ) const; static double could_open_probability( const OpenMPT::FileReader & file, double effort, std::unique_ptr log ); + void update_autogain(); public: static std::vector get_supported_extensions(); static bool is_extension_supported( const char * extension );