4
4
#include < memory>
5
5
#include < mutex>
6
6
#include < shared_mutex>
7
+ #include < magic_enum/magic_enum.hpp>
7
8
8
9
#include " common/assert.h"
9
10
#include " common/config.h"
@@ -22,111 +23,28 @@ std::array<PortOut, SCE_AUDIO_OUT_NUM_PORTS> ports_out{};
22
23
23
24
static std::unique_ptr<AudioOutBackend> audio;
24
25
25
- static std::string_view GetAudioOutPort (OrbisAudioOutPort port) {
26
- switch (port) {
27
- case OrbisAudioOutPort::Main:
28
- return " MAIN" ;
29
- case OrbisAudioOutPort::Bgm:
30
- return " BGM" ;
31
- case OrbisAudioOutPort::Voice:
32
- return " VOICE" ;
33
- case OrbisAudioOutPort::Personal:
34
- return " PERSONAL" ;
35
- case OrbisAudioOutPort::Padspk:
36
- return " PADSPK" ;
37
- case OrbisAudioOutPort::Aux:
38
- return " AUX" ;
39
- default :
40
- return " INVALID" ;
41
- }
42
- }
43
-
44
- static std::string_view GetAudioOutParamFormat (OrbisAudioOutParamFormat param) {
45
- switch (param) {
46
- case OrbisAudioOutParamFormat::S16Mono:
47
- return " S16_MONO" ;
48
- case OrbisAudioOutParamFormat::S16Stereo:
49
- return " S16_STEREO" ;
50
- case OrbisAudioOutParamFormat::S16_8CH:
51
- return " S16_8CH" ;
52
- case OrbisAudioOutParamFormat::FloatMono:
53
- return " FLOAT_MONO" ;
54
- case OrbisAudioOutParamFormat::FloatStereo:
55
- return " FLOAT_STEREO" ;
56
- case OrbisAudioOutParamFormat::Float_8CH:
57
- return " FLOAT_8CH" ;
58
- case OrbisAudioOutParamFormat::S16_8CH_Std:
59
- return " S16_8CH_STD" ;
60
- case OrbisAudioOutParamFormat::Float_8CH_Std:
61
- return " FLOAT_8CH_STD" ;
62
- default :
63
- return " INVALID" ;
64
- }
65
- }
66
-
67
- static std::string_view GetAudioOutParamAttr (OrbisAudioOutParamAttr attr) {
68
- switch (attr) {
69
- case OrbisAudioOutParamAttr::None:
70
- return " NONE" ;
71
- case OrbisAudioOutParamAttr::Restricted:
72
- return " RESTRICTED" ;
73
- case OrbisAudioOutParamAttr::MixToMain:
74
- return " MIX_TO_MAIN" ;
75
- default :
76
- return " INVALID" ;
77
- }
78
- }
79
-
80
- static bool IsFormatFloat (const OrbisAudioOutParamFormat format) {
81
- switch (format) {
82
- case OrbisAudioOutParamFormat::S16Mono:
83
- case OrbisAudioOutParamFormat::S16Stereo:
84
- case OrbisAudioOutParamFormat::S16_8CH:
85
- case OrbisAudioOutParamFormat::S16_8CH_Std:
86
- return false ;
87
- case OrbisAudioOutParamFormat::FloatMono:
88
- case OrbisAudioOutParamFormat::FloatStereo:
89
- case OrbisAudioOutParamFormat::Float_8CH:
90
- case OrbisAudioOutParamFormat::Float_8CH_Std:
91
- return true ;
92
- default :
93
- UNREACHABLE_MSG (" Unknown format" );
94
- }
95
- }
96
-
97
- static u8 GetFormatNumChannels (const OrbisAudioOutParamFormat format) {
98
- switch (format) {
99
- case OrbisAudioOutParamFormat::S16Mono:
100
- case OrbisAudioOutParamFormat::FloatMono:
101
- return 1 ;
102
- case OrbisAudioOutParamFormat::S16Stereo:
103
- case OrbisAudioOutParamFormat::FloatStereo:
104
- return 2 ;
105
- case OrbisAudioOutParamFormat::S16_8CH:
106
- case OrbisAudioOutParamFormat::Float_8CH:
107
- case OrbisAudioOutParamFormat::S16_8CH_Std:
108
- case OrbisAudioOutParamFormat::Float_8CH_Std:
109
- return 8 ;
110
- default :
111
- UNREACHABLE_MSG (" Unknown format" );
112
- }
113
- }
114
-
115
- static u8 GetFormatSampleSize (const OrbisAudioOutParamFormat format) {
116
- switch (format) {
117
- case OrbisAudioOutParamFormat::S16Mono:
118
- case OrbisAudioOutParamFormat::S16Stereo:
119
- case OrbisAudioOutParamFormat::S16_8CH:
120
- case OrbisAudioOutParamFormat::S16_8CH_Std:
121
- return 2 ;
122
- case OrbisAudioOutParamFormat::FloatMono:
123
- case OrbisAudioOutParamFormat::FloatStereo:
124
- case OrbisAudioOutParamFormat::Float_8CH:
125
- case OrbisAudioOutParamFormat::Float_8CH_Std:
126
- return 4 ;
127
- default :
128
- UNREACHABLE_MSG (" Unknown format" );
129
- }
26
+ static AudioFormatInfo GetFormatInfo (const OrbisAudioOutParamFormat format) {
27
+ static constexpr std::array<AudioFormatInfo, 8 > format_infos = {{
28
+ // S16Mono
29
+ {false , 2 , 1 , {0 }},
30
+ // S16Stereo
31
+ {false , 2 , 2 , {0 , 1 }},
32
+ // S16_8CH
33
+ {false , 2 , 8 , {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 }},
34
+ // FloatMono
35
+ {true , 4 , 1 , {0 }},
36
+ // FloatStereo
37
+ {true , 4 , 2 , {0 , 1 }},
38
+ // Float_8CH
39
+ {true , 4 , 8 , {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 }},
40
+ // S16_8CH_Std
41
+ {false , 2 , 8 , {0 , 1 , 2 , 3 , 6 , 7 , 4 , 5 }},
42
+ // Float_8CH_Std
43
+ {true , 4 , 8 , {0 , 1 , 2 , 3 , 6 , 7 , 4 , 5 }},
44
+ }};
45
+ const auto index = static_cast <u32 >(format);
46
+ ASSERT_MSG (index < format_infos.size (), " Unknown audio format {}" , index);
47
+ return format_infos[index];
130
48
}
131
49
132
50
int PS4_SYSV_ABI sceAudioOutDeviceIdOpen () {
@@ -268,7 +186,7 @@ int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* sta
268
186
case OrbisAudioOutPort::Bgm:
269
187
case OrbisAudioOutPort::Voice:
270
188
state->output = 1 ;
271
- state->channel = port.channels_num > 2 ? 2 : port.channels_num ;
189
+ state->channel = port.format_info . num_channels > 2 ? 2 : port.format_info . num_channels ;
272
190
break ;
273
191
case OrbisAudioOutPort::Personal:
274
192
case OrbisAudioOutPort::Padspk:
@@ -357,7 +275,7 @@ static void AudioOutputThread(PortOut* port, const std::stop_token& stop) {
357
275
}
358
276
359
277
Common::AccurateTimer timer (
360
- std::chrono::nanoseconds (1000000000ULL * port->buffer_frames / port->freq ));
278
+ std::chrono::nanoseconds (1000000000ULL * port->buffer_frames / port->sample_rate ));
361
279
while (true ) {
362
280
timer.Start ();
363
281
{
@@ -381,9 +299,9 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
381
299
LOG_INFO (Lib_AudioOut,
382
300
" id = {} port_type = {} index = {} length = {} sample_rate = {} "
383
301
" param_type = {} attr = {}" ,
384
- user_id, GetAudioOutPort (port_type), index, length, sample_rate,
385
- GetAudioOutParamFormat (param_type.data_format ),
386
- GetAudioOutParamAttr (param_type.attributes ));
302
+ user_id, magic_enum::enum_name (port_type), index, length, sample_rate,
303
+ magic_enum::enum_name (param_type.data_format . Value () ),
304
+ magic_enum::enum_name (param_type.attributes . Value () ));
387
305
if ((port_type < OrbisAudioOutPort::Main || port_type > OrbisAudioOutPort::Padspk) &&
388
306
(port_type != OrbisAudioOutPort::Aux)) {
389
307
LOG_ERROR (Lib_AudioOut, " Invalid port type" );
@@ -423,19 +341,14 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
423
341
}
424
342
425
343
port->type = port_type;
426
- port->format = format;
427
- port->is_float = IsFormatFloat (format);
428
- port->freq = sample_rate;
429
- port->sample_size = GetFormatSampleSize (format);
430
- port->channels_num = GetFormatNumChannels (format);
431
- port->frame_size = port->sample_size * port->channels_num ;
344
+ port->format_info = GetFormatInfo (format);
345
+ port->sample_rate = sample_rate;
432
346
port->buffer_frames = length;
433
- port->buffer_size = port->frame_size * port->buffer_frames ;
434
347
port->volume .fill (SCE_AUDIO_OUT_VOLUME_0DB);
435
348
436
349
port->impl = audio->Open (*port);
437
350
438
- port->output_buffer = std::malloc (port->buffer_size );
351
+ port->output_buffer = std::malloc (port->BufferSize () );
439
352
port->output_ready = false ;
440
353
port->output_thread .Run (
441
354
[port](const std::stop_token& stop) { AudioOutputThread (&*port, stop); });
@@ -462,7 +375,7 @@ s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr) {
462
375
std::unique_lock lock{port.output_mutex };
463
376
port.output_cv .wait (lock, [&] { return !port.output_ready ; });
464
377
if (ptr != nullptr ) {
465
- std::memcpy (port.output_buffer , ptr, port.buffer_size );
378
+ std::memcpy (port.output_buffer , ptr, port.BufferSize () );
466
379
port.output_ready = true ;
467
380
}
468
381
}
@@ -581,30 +494,9 @@ s32 PS4_SYSV_ABI sceAudioOutSetVolume(s32 handle, s32 flag, s32* vol) {
581
494
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
582
495
}
583
496
584
- for (int i = 0 ; i < port.channels_num ; i++, flag >>= 1u ) {
585
- auto bit = flag & 0x1u ;
586
- if (bit == 1 ) {
587
- int src_index = i;
588
- if (port.format == OrbisAudioOutParamFormat::Float_8CH_Std ||
589
- port.format == OrbisAudioOutParamFormat::S16_8CH_Std) {
590
- switch (i) {
591
- case 4 :
592
- src_index = 6 ;
593
- break ;
594
- case 5 :
595
- src_index = 7 ;
596
- break ;
597
- case 6 :
598
- src_index = 4 ;
599
- break ;
600
- case 7 :
601
- src_index = 5 ;
602
- break ;
603
- default :
604
- break ;
605
- }
606
- }
607
- port.volume [i] = vol[src_index];
497
+ for (int i = 0 ; i < port.format_info .num_channels ; i++, flag >>= 1u ) {
498
+ if (flag & 0x1u ) {
499
+ port.volume [i] = vol[i];
608
500
}
609
501
}
610
502
0 commit comments