@ -12,6 +12,7 @@
# include "audio_core/voice_context.h"
# include "audio_core/voice_context.h"
# include "common/logging/log.h"
# include "common/logging/log.h"
# include "common/settings.h"
# include "common/settings.h"
# include "core/core_timing.h"
# include "core/memory.h"
# include "core/memory.h"
namespace {
namespace {
@ -68,7 +69,9 @@ namespace {
} // namespace
} // namespace
namespace AudioCore {
namespace AudioCore {
AudioRenderer : : AudioRenderer ( Core : : Timing : : CoreTiming & core_timing , Core : : Memory : : Memory & memory_ ,
constexpr s32 NUM_BUFFERS = 2 ;
AudioRenderer : : AudioRenderer ( Core : : Timing : : CoreTiming & core_timing_ , Core : : Memory : : Memory & memory_ ,
AudioCommon : : AudioRendererParameter params ,
AudioCommon : : AudioRendererParameter params ,
Stream : : ReleaseCallback & & release_callback ,
Stream : : ReleaseCallback & & release_callback ,
std : : size_t instance_number )
std : : size_t instance_number )
@ -77,7 +80,8 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory
sink_context ( params . sink_count ) , splitter_context ( ) ,
sink_context ( params . sink_count ) , splitter_context ( ) ,
voices ( params . voice_count ) , memory { memory_ } ,
voices ( params . voice_count ) , memory { memory_ } ,
command_generator ( worker_params , voice_context , mix_context , splitter_context , effect_context ,
command_generator ( worker_params , voice_context , mix_context , splitter_context , effect_context ,
memory ) {
memory ) ,
core_timing { core_timing_ } {
behavior_info . SetUserRevision ( params . revision ) ;
behavior_info . SetUserRevision ( params . revision ) ;
splitter_context . Initialize ( behavior_info , params . splitter_count ,
splitter_context . Initialize ( behavior_info , params . splitter_count ,
params . num_splitter_send_channels ) ;
params . num_splitter_send_channels ) ;
@ -86,16 +90,27 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory
stream = audio_out - > OpenStream (
stream = audio_out - > OpenStream (
core_timing , params . sample_rate , AudioCommon : : STREAM_NUM_CHANNELS ,
core_timing , params . sample_rate , AudioCommon : : STREAM_NUM_CHANNELS ,
fmt : : format ( " AudioRenderer-Instance{} " , instance_number ) , std : : move ( release_callback ) ) ;
fmt : : format ( " AudioRenderer-Instance{} " , instance_number ) , std : : move ( release_callback ) ) ;
audio_out- > StartStream ( stream ) ;
process_event = Core : : Timing : : CreateEvent (
fmt : : format ( " AudioRenderer-Instance{}-Process " , instance_number ) ,
QueueMixedBuffer ( 0 ) ;
[ this ] ( std : : uintptr_t , std : : chrono : : nanoseconds ) { ReleaseAndQueueBuffers ( ) ; } ) ;
QueueMixedBuffer ( 1 ) ;
for ( s32 i = 0 ; i < NUM_BUFFERS ; + + i ) {
QueueMixedBuffer ( 2 ) ;
QueueMixedBuffer ( i ) ;
QueueMixedBuffer ( 3 ) ;
}
}
}
AudioRenderer : : ~ AudioRenderer ( ) = default ;
AudioRenderer : : ~ AudioRenderer ( ) = default ;
ResultCode AudioRenderer : : Start ( ) {
audio_out - > StartStream ( stream ) ;
ReleaseAndQueueBuffers ( ) ;
return ResultSuccess ;
}
ResultCode AudioRenderer : : Stop ( ) {
audio_out - > StopStream ( stream ) ;
return ResultSuccess ;
}
u32 AudioRenderer : : GetSampleRate ( ) const {
u32 AudioRenderer : : GetSampleRate ( ) const {
return worker_params . sample_rate ;
return worker_params . sample_rate ;
}
}
@ -114,7 +129,8 @@ Stream::State AudioRenderer::GetStreamState() const {
ResultCode AudioRenderer : : UpdateAudioRenderer ( const std : : vector < u8 > & input_params ,
ResultCode AudioRenderer : : UpdateAudioRenderer ( const std : : vector < u8 > & input_params ,
std : : vector < u8 > & output_params ) {
std : : vector < u8 > & output_params ) {
{
std : : scoped_lock lock { mutex } ;
InfoUpdater info_updater { input_params , output_params , behavior_info } ;
InfoUpdater info_updater { input_params , output_params , behavior_info } ;
if ( ! info_updater . UpdateBehaviorInfo ( behavior_info ) ) {
if ( ! info_updater . UpdateBehaviorInfo ( behavior_info ) ) {
@ -150,8 +166,8 @@ ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_param
}
}
}
}
const auto mix_result = info_updater . UpdateMixes ( mix_context , worker_params . mix_buffer_count ,
const auto mix_result = info_updater . UpdateMixes (
splitter_context , effect_context ) ;
mix_context , worker_params . mix_buffer_count , splitter_context , effect_context ) ;
if ( mix_result . IsError ( ) ) {
if ( mix_result . IsError ( ) ) {
LOG_ERROR ( Audio , " Failed to update mix parameters " ) ;
LOG_ERROR ( Audio , " Failed to update mix parameters " ) ;
@ -194,9 +210,7 @@ ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_param
LOG_ERROR ( Audio , " Audio buffers were not consumed! " ) ;
LOG_ERROR ( Audio , " Audio buffers were not consumed! " ) ;
return AudioCommon : : Audren : : ERR_INVALID_PARAMETERS ;
return AudioCommon : : Audren : : ERR_INVALID_PARAMETERS ;
}
}
}
ReleaseAndQueueBuffers ( ) ;
return ResultSuccess ;
return ResultSuccess ;
}
}
@ -315,10 +329,24 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
}
}
void AudioRenderer : : ReleaseAndQueueBuffers ( ) {
void AudioRenderer : : ReleaseAndQueueBuffers ( ) {
if ( ! stream - > IsPlaying ( ) ) {
return ;
}
{
std : : scoped_lock lock { mutex } ;
const auto released_buffers { audio_out - > GetTagsAndReleaseBuffers ( stream ) } ;
const auto released_buffers { audio_out - > GetTagsAndReleaseBuffers ( stream ) } ;
for ( const auto & tag : released_buffers ) {
for ( const auto & tag : released_buffers ) {
QueueMixedBuffer ( tag ) ;
QueueMixedBuffer ( tag ) ;
}
}
}
}
const f32 sample_rate = static_cast < f32 > ( GetSampleRate ( ) ) ;
const f32 sample_count = static_cast < f32 > ( GetSampleCount ( ) ) ;
const f32 consume_rate = sample_rate / ( sample_count * ( sample_count / 240 ) ) ;
const s32 ms = ( 1000 / static_cast < s32 > ( consume_rate ) ) - 1 ;
const std : : chrono : : milliseconds next_event_time ( std : : max ( ms / NUM_BUFFERS , 1 ) ) ;
core_timing . ScheduleEvent ( next_event_time , process_event , { } ) ;
}
} // namespace AudioCore
} // namespace AudioCore