@ -37,7 +37,9 @@ bool IsValidMultiStreamStreamCounts(s32 total_stream_count, s32 stereo_stream_co
} // namespace
OpusDecoder : : OpusDecoder ( Core : : System & system_ ) : system { system_ } {
init_thread = std : : jthread ( [ this ] ( std : : stop_token stop_token ) { Init ( stop_token ) ; } ) ;
init_thread = std : : jthread ( [ this ] ( std : : stop_token stop_token ) {
Init ( stop_token ) ;
} ) ;
}
OpusDecoder : : ~ OpusDecoder ( ) {
@ -64,206 +66,203 @@ u32 OpusDecoder::Receive(Direction dir, std::stop_token stop_token) {
return mailbox . Receive ( dir , stop_token ) ;
}
void OpusDecoder : : Init ( std : : stop_token stop_token ) {
void OpusDecoder : : Init ( std : : stop_token rc_ stop_token) {
Common : : SetCurrentThreadName ( " DSP_OpusDecoder_Init " ) ;
if ( Receive ( Direction : : DSP , stop_token ) ! = Message : : Start ) {
LOG_ERROR ( Service_Audio ,
" DSP OpusDecoder failed to receive Start message. Opus initialization failed. " ) ;
if ( Receive ( Direction : : DSP , rc_stop_token ) ! = Message : : Start ) {
LOG_ERROR ( Service_Audio , " DSP OpusDecoder failed to receive Start message. Opus initialization failed. " ) ;
return ;
}
main_thread = std : : jthread ( [ this ] ( std : : stop_token st ) { Main ( st ) ; } ) ;
running = true ;
Send ( Direction : : Host , Message : : StartOK ) ;
}
void OpusDecoder : : Main ( std : : stop_token stop_token ) {
Common : : SetCurrentThreadName ( " DSP_OpusDecoder_Main " ) ;
while ( ! stop_token . stop_requested ( ) ) {
auto msg = Receive ( Direction : : DSP , stop_token ) ;
switch ( msg ) {
case Shutdown :
Send ( Direction : : Host , Message : : ShutdownOK ) ;
return ;
case GetWorkBufferSize : {
auto channel_count = static_cast < s32 > ( shared_memory - > host_send_data [ 0 ] ) ;
ASSERT ( IsValidChannelCount ( channel_count ) ) ;
shared_memory - > dsp_return_data [ 0 ] = OpusDecodeObject : : GetWorkBufferSize ( channel_count ) ;
Send ( Direction : : Host , Message : : GetWorkBufferSizeOK ) ;
} break ;
case InitializeDecodeObject : {
auto buffer = shared_memory - > host_send_data [ 0 ] ;
auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
auto sample_rate = static_cast < s32 > ( shared_memory - > host_send_data [ 2 ] ) ;
auto channel_count = static_cast < s32 > ( shared_memory - > host_send_data [ 3 ] ) ;
ASSERT ( sample_rate > = 0 ) ;
ASSERT ( IsValidChannelCount ( channel_count ) ) ;
ASSERT ( buffer_size > = OpusDecodeObject : : GetWorkBufferSize ( channel_count ) ) ;
auto & decoder_object = OpusDecodeObject : : Initialize ( buffer , buffer ) ;
shared_memory - > dsp_return_data [ 0 ] =
decoder_object . InitializeDecoder ( sample_rate , channel_count ) ;
Send ( Direction : : Host , Message : : InitializeDecodeObjectOK ) ;
} break ;
case ShutdownDecodeObject : {
auto buffer = shared_memory - > host_send_data [ 0 ] ;
[[maybe_unused]] auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
auto & decoder_object = OpusDecodeObject : : Initialize ( buffer , buffer ) ;
shared_memory - > dsp_return_data [ 0 ] = decoder_object . Shutdown ( ) ;
Send ( Direction : : Host , Message : : ShutdownDecodeObjectOK ) ;
} break ;
case DecodeInterleaved : {
auto start_time = system . CoreTiming ( ) . GetGlobalTimeUs ( ) ;
auto buffer = shared_memory - > host_send_data [ 0 ] ;
auto input_data = shared_memory - > host_send_data [ 1 ] ;
auto input_data_size = shared_memory - > host_send_data [ 2 ] ;
auto output_data = shared_memory - > host_send_data [ 3 ] ;
auto output_data_size = shared_memory - > host_send_data [ 4 ] ;
auto final_range = static_cast < u32 > ( shared_memory - > host_send_data [ 5 ] ) ;
auto reset_requested = shared_memory - > host_send_data [ 6 ] ;
u32 decoded_samples { 0 } ;
auto & decoder_object = OpusDecodeObject : : Initialize ( buffer , buffer ) ;
s32 error_code { OPUS_OK } ;
if ( reset_requested ) {
error_code = decoder_object . ResetDecoder ( ) ;
}
// Main OpusDecoder thread, responsible for processing the incoming Opus packets.
main_thread = std : : jthread ( [ this ] ( std : : stop_token stop_token ) {
Common : : SetCurrentThreadName ( " DSP_OpusDecoder_Main " ) ;
while ( ! stop_token . stop_requested ( ) ) {
auto msg = Receive ( Direction : : DSP , stop_token ) ;
switch ( msg ) {
case Shutdown :
Send ( Direction : : Host , Message : : ShutdownOK ) ;
return ;
case GetWorkBufferSize : {
auto channel_count = static_cast < s32 > ( shared_memory - > host_send_data [ 0 ] ) ;
ASSERT ( IsValidChannelCount ( channel_count ) ) ;
shared_memory - > dsp_return_data [ 0 ] = OpusDecodeObject : : GetWorkBufferSize ( channel_count ) ;
Send ( Direction : : Host , Message : : GetWorkBufferSizeOK ) ;
} break ;
case InitializeDecodeObject : {
auto buffer = shared_memory - > host_send_data [ 0 ] ;
auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
auto sample_rate = static_cast < s32 > ( shared_memory - > host_send_data [ 2 ] ) ;
auto channel_count = static_cast < s32 > ( shared_memory - > host_send_data [ 3 ] ) ;
ASSERT ( sample_rate > = 0 ) ;
ASSERT ( IsValidChannelCount ( channel_count ) ) ;
ASSERT ( buffer_size > = OpusDecodeObject : : GetWorkBufferSize ( channel_count ) ) ;
auto & decoder_object = OpusDecodeObject : : Initialize ( buffer , buffer ) ;
shared_memory - > dsp_return_data [ 0 ] =
decoder_object . InitializeDecoder ( sample_rate , channel_count ) ;
Send ( Direction : : Host , Message : : InitializeDecodeObjectOK ) ;
} break ;
case ShutdownDecodeObject : {
auto buffer = shared_memory - > host_send_data [ 0 ] ;
[[maybe_unused]] auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
auto & decoder_object = OpusDecodeObject : : Initialize ( buffer , buffer ) ;
shared_memory - > dsp_return_data [ 0 ] = decoder_object . Shutdown ( ) ;
Send ( Direction : : Host , Message : : ShutdownDecodeObjectOK ) ;
} break ;
case DecodeInterleaved : {
auto start_time = system . CoreTiming ( ) . GetGlobalTimeUs ( ) ;
auto buffer = shared_memory - > host_send_data [ 0 ] ;
auto input_data = shared_memory - > host_send_data [ 1 ] ;
auto input_data_size = shared_memory - > host_send_data [ 2 ] ;
auto output_data = shared_memory - > host_send_data [ 3 ] ;
auto output_data_size = shared_memory - > host_send_data [ 4 ] ;
auto final_range = static_cast < u32 > ( shared_memory - > host_send_data [ 5 ] ) ;
auto reset_requested = shared_memory - > host_send_data [ 6 ] ;
u32 decoded_samples { 0 } ;
auto & decoder_object = OpusDecodeObject : : Initialize ( buffer , buffer ) ;
s32 error_code { OPUS_OK } ;
if ( reset_requested ) {
error_code = decoder_object . ResetDecoder ( ) ;
}
if ( error_code = = OPUS_OK ) {
error_code = decoder_object . Decode ( decoded_samples , output_data , output_data_size ,
input_data , input_data_size ) ;
}
if ( error_code = = OPUS_OK ) {
error_code = decoder_object . Decode ( decoded_samples , output_data , output_data_size ,
input_data , input_data_size ) ;
}
if ( error_code = = OPUS_OK ) {
if ( final_range & & decoder_object . GetFinalRange ( ) ! = final_range ) {
error_code = OPUS_INVALID_PACKET ;
if ( error_code = = OPUS_OK ) {
if ( final_range & & decoder_object . GetFinalRange ( ) ! = final_range ) {
error_code = OPUS_INVALID_PACKET ;
}
}
}
auto end_time = system . CoreTiming ( ) . GetGlobalTimeUs ( ) ;
shared_memory - > dsp_return_data [ 0 ] = error_code ;
shared_memory - > dsp_return_data [ 1 ] = decoded_samples ;
shared_memory - > dsp_return_data [ 2 ] = ( end_time - start_time ) . count ( ) ;
Send ( Direction : : Host , Message : : DecodeInterleavedOK ) ;
} break ;
case MapMemory : {
[[maybe_unused]] auto buffer = shared_memory - > host_send_data [ 0 ] ;
[[maybe_unused]] auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
Send ( Direction : : Host , Message : : MapMemoryOK ) ;
} break ;
case UnmapMemory : {
[[maybe_unused]] auto buffer = shared_memory - > host_send_data [ 0 ] ;
[[maybe_unused]] auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
Send ( Direction : : Host , Message : : UnmapMemoryOK ) ;
} break ;
case GetWorkBufferSizeForMultiStream : {
auto total_stream_count = static_cast < s32 > ( shared_memory - > host_send_data [ 0 ] ) ;
auto stereo_stream_count = static_cast < s32 > ( shared_memory - > host_send_data [ 1 ] ) ;
ASSERT ( IsValidMultiStreamStreamCounts ( total_stream_count , stereo_stream_count ) ) ;
shared_memory - > dsp_return_data [ 0 ] = OpusMultiStreamDecodeObject : : GetWorkBufferSize (
total_stream_count , stereo_stream_count ) ;
Send ( Direction : : Host , Message : : GetWorkBufferSizeForMultiStreamOK ) ;
} break ;
case InitializeMultiStreamDecodeObject : {
auto buffer = shared_memory - > host_send_data [ 0 ] ;
auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
auto sample_rate = static_cast < s32 > ( shared_memory - > host_send_data [ 2 ] ) ;
auto channel_count = static_cast < s32 > ( shared_memory - > host_send_data [ 3 ] ) ;
auto total_stream_count = static_cast < s32 > ( shared_memory - > host_send_data [ 4 ] ) ;
auto stereo_stream_count = static_cast < s32 > ( shared_memory - > host_send_data [ 5 ] ) ;
// Nintendo seem to have a bug here, they try to use &host_send_data[6] for the channel
// mappings, but [6] is never set, and there is not enough room in the argument data for
// more than 40 channels, when 255 are possible.
// It also means the mapping values are undefined, though likely always 0,
// and the mappings given by the game are ignored. The mappings are copied to this
// dedicated buffer host side, so let's do as intended.
auto mappings = shared_memory - > channel_mapping . data ( ) ;
ASSERT ( IsValidMultiStreamStreamCounts ( total_stream_count , stereo_stream_count ) ) ;
ASSERT ( sample_rate > = 0 ) ;
ASSERT ( buffer_size > = OpusMultiStreamDecodeObject : : GetWorkBufferSize (
total_stream_count , stereo_stream_count ) ) ;
auto & decoder_object = OpusMultiStreamDecodeObject : : Initialize ( buffer , buffer ) ;
shared_memory - > dsp_return_data [ 0 ] = decoder_object . InitializeDecoder (
sample_rate , total_stream_count , channel_count , stereo_stream_count , mappings ) ;
Send ( Direction : : Host , Message : : InitializeMultiStreamDecodeObjectOK ) ;
} break ;
case ShutdownMultiStreamDecodeObject : {
auto buffer = shared_memory - > host_send_data [ 0 ] ;
[[maybe_unused]] auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
auto & decoder_object = OpusMultiStreamDecodeObject : : Initialize ( buffer , buffer ) ;
shared_memory - > dsp_return_data [ 0 ] = decoder_object . Shutdown ( ) ;
Send ( Direction : : Host , Message : : ShutdownMultiStreamDecodeObjectOK ) ;
} break ;
case DecodeInterleavedForMultiStream : {
auto start_time = system . CoreTiming ( ) . GetGlobalTimeUs ( ) ;
auto buffer = shared_memory - > host_send_data [ 0 ] ;
auto input_data = shared_memory - > host_send_data [ 1 ] ;
auto input_data_size = shared_memory - > host_send_data [ 2 ] ;
auto output_data = shared_memory - > host_send_data [ 3 ] ;
auto output_data_size = shared_memory - > host_send_data [ 4 ] ;
auto final_range = static_cast < u32 > ( shared_memory - > host_send_data [ 5 ] ) ;
auto reset_requested = shared_memory - > host_send_data [ 6 ] ;
u32 decoded_samples { 0 } ;
auto & decoder_object = OpusMultiStreamDecodeObject : : Initialize ( buffer , buffer ) ;
s32 error_code { OPUS_OK } ;
if ( reset_requested ) {
error_code = decoder_object . ResetDecoder ( ) ;
}
auto end_time = system . CoreTiming ( ) . GetGlobalTimeUs ( ) ;
shared_memory - > dsp_return_data [ 0 ] = error_code ;
shared_memory - > dsp_return_data [ 1 ] = decoded_samples ;
shared_memory - > dsp_return_data [ 2 ] = ( end_time - start_time ) . count ( ) ;
Send ( Direction : : Host , Message : : DecodeInterleavedOK ) ;
} break ;
case MapMemory : {
[[maybe_unused]] auto buffer = shared_memory - > host_send_data [ 0 ] ;
[[maybe_unused]] auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
Send ( Direction : : Host , Message : : MapMemoryOK ) ;
} break ;
case UnmapMemory : {
[[maybe_unused]] auto buffer = shared_memory - > host_send_data [ 0 ] ;
[[maybe_unused]] auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
Send ( Direction : : Host , Message : : UnmapMemoryOK ) ;
} break ;
case GetWorkBufferSizeForMultiStream : {
auto total_stream_count = static_cast < s32 > ( shared_memory - > host_send_data [ 0 ] ) ;
auto stereo_stream_count = static_cast < s32 > ( shared_memory - > host_send_data [ 1 ] ) ;
ASSERT ( IsValidMultiStreamStreamCounts ( total_stream_count , stereo_stream_count ) ) ;
shared_memory - > dsp_return_data [ 0 ] = OpusMultiStreamDecodeObject : : GetWorkBufferSize (
total_stream_count , stereo_stream_count ) ;
Send ( Direction : : Host , Message : : GetWorkBufferSizeForMultiStreamOK ) ;
} break ;
case InitializeMultiStreamDecodeObject : {
auto buffer = shared_memory - > host_send_data [ 0 ] ;
auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
auto sample_rate = static_cast < s32 > ( shared_memory - > host_send_data [ 2 ] ) ;
auto channel_count = static_cast < s32 > ( shared_memory - > host_send_data [ 3 ] ) ;
auto total_stream_count = static_cast < s32 > ( shared_memory - > host_send_data [ 4 ] ) ;
auto stereo_stream_count = static_cast < s32 > ( shared_memory - > host_send_data [ 5 ] ) ;
// Nintendo seem to have a bug here, they try to use &host_send_data[6] for the channel
// mappings, but [6] is never set, and there is not enough room in the argument data for
// more than 40 channels, when 255 are possible.
// It also means the mapping values are undefined, though likely always 0,
// and the mappings given by the game are ignored. The mappings are copied to this
// dedicated buffer host side, so let's do as intended.
auto mappings = shared_memory - > channel_mapping . data ( ) ;
ASSERT ( IsValidMultiStreamStreamCounts ( total_stream_count , stereo_stream_count ) ) ;
ASSERT ( sample_rate > = 0 ) ;
ASSERT ( buffer_size > = OpusMultiStreamDecodeObject : : GetWorkBufferSize (
total_stream_count , stereo_stream_count ) ) ;
auto & decoder_object = OpusMultiStreamDecodeObject : : Initialize ( buffer , buffer ) ;
shared_memory - > dsp_return_data [ 0 ] = decoder_object . InitializeDecoder (
sample_rate , total_stream_count , channel_count , stereo_stream_count , mappings ) ;
Send ( Direction : : Host , Message : : InitializeMultiStreamDecodeObjectOK ) ;
} break ;
case ShutdownMultiStreamDecodeObject : {
auto buffer = shared_memory - > host_send_data [ 0 ] ;
[[maybe_unused]] auto buffer_size = shared_memory - > host_send_data [ 1 ] ;
auto & decoder_object = OpusMultiStreamDecodeObject : : Initialize ( buffer , buffer ) ;
shared_memory - > dsp_return_data [ 0 ] = decoder_object . Shutdown ( ) ;
Send ( Direction : : Host , Message : : ShutdownMultiStreamDecodeObjectOK ) ;
} break ;
case DecodeInterleavedForMultiStream : {
auto start_time = system . CoreTiming ( ) . GetGlobalTimeUs ( ) ;
auto buffer = shared_memory - > host_send_data [ 0 ] ;
auto input_data = shared_memory - > host_send_data [ 1 ] ;
auto input_data_size = shared_memory - > host_send_data [ 2 ] ;
auto output_data = shared_memory - > host_send_data [ 3 ] ;
auto output_data_size = shared_memory - > host_send_data [ 4 ] ;
auto final_range = static_cast < u32 > ( shared_memory - > host_send_data [ 5 ] ) ;
auto reset_requested = shared_memory - > host_send_data [ 6 ] ;
u32 decoded_samples { 0 } ;
auto & decoder_object = OpusMultiStreamDecodeObject : : Initialize ( buffer , buffer ) ;
s32 error_code { OPUS_OK } ;
if ( reset_requested ) {
error_code = decoder_object . ResetDecoder ( ) ;
}
if ( error_code = = OPUS_OK ) {
error_code = decoder_object . Decode ( decoded_samples , output_data , output_data_size ,
input_data , input_data_size ) ;
}
if ( error_code = = OPUS_OK ) {
error_code = decoder_object . Decode ( decoded_samples , output_data , output_data_size ,
input_data , input_data_size ) ;
}
if ( error_code = = OPUS_OK ) {
if ( final_range & & decoder_object . GetFinalRange ( ) ! = final_range ) {
error_code = OPUS_INVALID_PACKET ;
if ( error_code = = OPUS_OK ) {
if ( final_range & & decoder_object . GetFinalRange ( ) ! = final_range ) {
error_code = OPUS_INVALID_PACKET ;
}
}
}
auto end_time = system . CoreTiming ( ) . GetGlobalTimeUs ( ) ;
shared_memory - > dsp_return_data [ 0 ] = error_code ;
shared_memory - > dsp_return_data [ 1 ] = decoded_samples ;
shared_memory - > dsp_return_data [ 2 ] = ( end_time - start_time ) . count ( ) ;
auto end_time = system . CoreTiming ( ) . GetGlobalTimeUs ( ) ;
shared_memory - > dsp_return_data [ 0 ] = error_code ;
shared_memory - > dsp_return_data [ 1 ] = decoded_samples ;
shared_memory - > dsp_return_data [ 2 ] = ( end_time - start_time ) . count ( ) ;
Send ( Direction : : Host , Message : : DecodeInterleavedForMultiStreamOK ) ;
} break ;
Send ( Direction : : Host , Message : : DecodeInterleavedForMultiStreamOK ) ;
} break ;
default :
LOG_ERROR ( Service_Audio , " Invalid OpusDecoder command {} " , msg ) ;
continue ;
default :
LOG_ERROR ( Service_Audio , " Invalid OpusDecoder command {} " , msg ) ;
continue ;
}
}
}
} ) ;
running = true ;
Send ( Direction : : Host , Message : : StartOK ) ;
}
} // namespace AudioCore::ADSP::OpusDecoder