1 // Copyright (c) 2012- PPSSPP Project. 2 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, version 2.0 or later versions. 6 7 // This program is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 // GNU General Public License 2.0 for more details. 11 12 // A copy of the GPL 2.0 should have been included with the program. 13 // If not, see http://www.gnu.org/licenses/ 14 15 // Official git repository and contact information can be found at 16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. 17 18 #include "Common/Serialize/Serializer.h" 19 #include "Common/Serialize/SerializeFuncs.h" 20 #include "Common/Data/Collections/FixedSizeQueue.h" 21 #include "Core/MIPS/MIPS.h" 22 #include "Core/Host.h" 23 #include "Core/CoreTiming.h" 24 #include "Core/HLE/HLE.h" 25 #include "Core/HLE/FunctionWrappers.h" 26 #include "Core/HLE/sceKernelThread.h" 27 #include "Core/HLE/sceAudio.h" 28 #include "Core/HLE/sceUsbMic.h" 29 #include "Core/HLE/__sceAudio.h" 30 #include "Core/Reporting.h" 31 32 const u32 PSP_AUDIO_SAMPLE_MAX = 65536 - 64; 33 const int PSP_AUDIO_ERROR_SRC_FORMAT_4 = 0x80000003; 34 const int AUDIO_ROUTING_SPEAKER_OFF = 0; 35 const int AUDIO_ROUTING_SPEAKER_ON = 1; 36 int defaultRoutingMode = AUDIO_ROUTING_SPEAKER_ON; 37 int defaultRoutingVolMode = AUDIO_ROUTING_SPEAKER_ON; 38 39 extern FixedSizeQueue<s16, 32768 * 8> chanSampleQueues[PSP_AUDIO_CHANNEL_MAX + 1]; 40 41 // The extra channel is for SRC/Output2/Vaudio. 42 AudioChannel chans[PSP_AUDIO_CHANNEL_MAX + 1]; 43 44 void AudioChannel::DoState(PointerWrap &p) 45 { 46 auto s = p.Section("AudioChannel", 1, 2); 47 if (!s) 48 return; 49 50 Do(p, reserved); 51 Do(p, sampleAddress); 52 Do(p, sampleCount); 53 Do(p, leftVolume); 54 Do(p, rightVolume); 55 Do(p, format); 56 Do(p, waitingThreads); 57 if (s >= 2) { 58 Do(p, defaultRoutingMode); 59 Do(p, defaultRoutingVolMode); 60 } 61 chanSampleQueues[index].DoState(p); 62 } 63 64 void AudioChannel::reset() 65 { 66 __AudioWakeThreads(*this, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED); 67 clear(); 68 } 69 70 void AudioChannel::clear() 71 { 72 reserved = false; 73 leftVolume = 0; 74 rightVolume = 0; 75 format = 0; 76 sampleAddress = 0; 77 sampleCount = 0; 78 chanSampleQueues[index].clear(); 79 waitingThreads.clear(); 80 } 81 82 // Enqueues the buffer pointed to on the channel. If channel buffer queue is full (2 items?) will block until it isn't. 83 // For solid audio output we'll need a queue length of 2 buffers at least. 84 85 // Not sure about the range of volume, I often see 0x800 so that might be either 86 // max or 50%? 87 static u32 sceAudioOutputBlocking(u32 chan, int vol, u32 samplePtr) { 88 if (vol > 0xFFFF) { 89 ERROR_LOG(SCEAUDIO, "sceAudioOutputBlocking() - invalid volume"); 90 return SCE_ERROR_AUDIO_INVALID_VOLUME; 91 } else if (chan >= PSP_AUDIO_CHANNEL_MAX) { 92 ERROR_LOG(SCEAUDIO, "sceAudioOutputBlocking() - bad channel"); 93 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 94 } else if (!chans[chan].reserved) { 95 ERROR_LOG(SCEAUDIO, "sceAudioOutputBlocking() - channel not reserved"); 96 return SCE_ERROR_AUDIO_CHANNEL_NOT_INIT; 97 } else { 98 DEBUG_LOG(SCEAUDIO, "sceAudioOutputBlocking(%08x, %08x, %08x)", chan, vol, samplePtr); 99 if (vol >= 0) { 100 chans[chan].leftVolume = vol; 101 chans[chan].rightVolume = vol; 102 } 103 chans[chan].sampleAddress = samplePtr; 104 return __AudioEnqueue(chans[chan], chan, true); 105 } 106 } 107 108 static u32 sceAudioOutputPannedBlocking(u32 chan, int leftvol, int rightvol, u32 samplePtr) { 109 int result = 0; 110 // For some reason, this is the only one that checks for negative. 111 if (leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rightvol < 0) { 112 ERROR_LOG(SCEAUDIO, "sceAudioOutputPannedBlocking() - invalid volume"); 113 result = SCE_ERROR_AUDIO_INVALID_VOLUME; 114 } else if (chan >= PSP_AUDIO_CHANNEL_MAX) { 115 ERROR_LOG(SCEAUDIO, "sceAudioOutputPannedBlocking() - bad channel"); 116 result = SCE_ERROR_AUDIO_INVALID_CHANNEL; 117 } else if (!chans[chan].reserved) { 118 ERROR_LOG(SCEAUDIO, "sceAudioOutputPannedBlocking() - channel not reserved"); 119 result = SCE_ERROR_AUDIO_CHANNEL_NOT_INIT; 120 } else { 121 if (leftvol >= 0) { 122 chans[chan].leftVolume = leftvol; 123 } 124 if (rightvol >= 0) { 125 chans[chan].rightVolume = rightvol; 126 } 127 chans[chan].sampleAddress = samplePtr; 128 result = __AudioEnqueue(chans[chan], chan, true); 129 } 130 131 DEBUG_LOG(SCEAUDIO, "%08x = sceAudioOutputPannedBlocking(%08x, %08x, %08x, %08x)", result, chan, leftvol, rightvol, samplePtr); 132 return result; 133 134 } 135 136 static u32 sceAudioOutput(u32 chan, int vol, u32 samplePtr) { 137 if (vol > 0xFFFF) { 138 ERROR_LOG(SCEAUDIO, "sceAudioOutput() - invalid volume"); 139 return SCE_ERROR_AUDIO_INVALID_VOLUME; 140 } else if (chan >= PSP_AUDIO_CHANNEL_MAX) { 141 ERROR_LOG(SCEAUDIO, "sceAudioOutput() - bad channel"); 142 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 143 } else if (!chans[chan].reserved) { 144 ERROR_LOG(SCEAUDIO, "sceAudioOutput(%08x, %08x, %08x) - channel not reserved", chan, vol, samplePtr); 145 return SCE_ERROR_AUDIO_CHANNEL_NOT_INIT; 146 } else { 147 DEBUG_LOG(SCEAUDIO, "sceAudioOutputPanned(%08x, %08x, %08x)", chan, vol, samplePtr); 148 if (vol >= 0) { 149 chans[chan].leftVolume = vol; 150 chans[chan].rightVolume = vol; 151 } 152 chans[chan].sampleAddress = samplePtr; 153 return __AudioEnqueue(chans[chan], chan, false); 154 } 155 } 156 157 static u32 sceAudioOutputPanned(u32 chan, int leftvol, int rightvol, u32 samplePtr) { 158 if (leftvol > 0xFFFF || rightvol > 0xFFFF) { 159 ERROR_LOG(SCEAUDIO, "sceAudioOutputPanned() - invalid volume"); 160 return SCE_ERROR_AUDIO_INVALID_VOLUME; 161 } else if (chan >= PSP_AUDIO_CHANNEL_MAX) { 162 ERROR_LOG(SCEAUDIO, "sceAudioOutputPanned() - bad channel"); 163 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 164 } else if (!chans[chan].reserved) { 165 ERROR_LOG(SCEAUDIO, "sceAudioOutputPanned(%08x, %08x, %08x, %08x) - channel not reserved", chan, leftvol, rightvol, samplePtr); 166 return SCE_ERROR_AUDIO_CHANNEL_NOT_INIT; 167 } else { 168 DEBUG_LOG(SCEAUDIO, "sceAudioOutputPanned(%08x, %08x, %08x, %08x)", chan, leftvol, rightvol, samplePtr); 169 if (leftvol >= 0) { 170 chans[chan].leftVolume = leftvol; 171 } 172 if (rightvol >= 0) { 173 chans[chan].rightVolume = rightvol; 174 } 175 chans[chan].sampleAddress = samplePtr; 176 return __AudioEnqueue(chans[chan], chan, false); 177 } 178 } 179 180 static int sceAudioGetChannelRestLen(u32 chan) { 181 if (chan >= PSP_AUDIO_CHANNEL_MAX) { 182 ERROR_LOG(SCEAUDIO, "sceAudioGetChannelRestLen(%08x) - bad channel", chan); 183 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 184 } 185 int remainingSamples = (int)chanSampleQueues[chan].size() / 2; 186 VERBOSE_LOG(SCEAUDIO, "%d=sceAudioGetChannelRestLen(%08x)", remainingSamples, chan); 187 return remainingSamples; 188 } 189 190 static int sceAudioGetChannelRestLength(u32 chan) { 191 if (chan >= PSP_AUDIO_CHANNEL_MAX) { 192 ERROR_LOG(SCEAUDIO, "sceAudioGetChannelRestLength(%08x) - bad channel", chan); 193 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 194 } 195 int remainingSamples = (int)chanSampleQueues[chan].size() / 2; 196 VERBOSE_LOG(SCEAUDIO, "%d=sceAudioGetChannelRestLength(%08x)", remainingSamples, chan); 197 return remainingSamples; 198 } 199 200 static u32 GetFreeChannel() { 201 for (u32 i = PSP_AUDIO_CHANNEL_MAX - 1; i > 0; --i) { 202 if (!chans[i].reserved) 203 return i; 204 } 205 return -1; 206 } 207 208 static u32 sceAudioChReserve(int chan, u32 sampleCount, u32 format) { 209 if (chan < 0) { 210 chan = GetFreeChannel(); 211 if (chan < 0) { 212 ERROR_LOG(SCEAUDIO, "sceAudioChReserve - no channels remaining"); 213 return SCE_ERROR_AUDIO_NO_CHANNELS_AVAILABLE; 214 } 215 } 216 if ((u32)chan >= PSP_AUDIO_CHANNEL_MAX) { 217 ERROR_LOG(SCEAUDIO, "sceAudioChReserve(%08x, %08x, %08x) - bad channel", chan, sampleCount, format); 218 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 219 } 220 if ((sampleCount & 63) != 0 || sampleCount == 0 || sampleCount > PSP_AUDIO_SAMPLE_MAX) { 221 ERROR_LOG(SCEAUDIO, "sceAudioChReserve(%08x, %08x, %08x) - invalid sample count", chan, sampleCount, format); 222 return SCE_ERROR_AUDIO_OUTPUT_SAMPLE_DATA_SIZE_NOT_ALIGNED; 223 } 224 if (format != PSP_AUDIO_FORMAT_MONO && format != PSP_AUDIO_FORMAT_STEREO) { 225 ERROR_LOG(SCEAUDIO, "sceAudioChReserve(%08x, %08x, %08x) - invalid format", chan, sampleCount, format); 226 return SCE_ERROR_AUDIO_INVALID_FORMAT; 227 } 228 if (chans[chan].reserved) { 229 ERROR_LOG(SCEAUDIO, "sceAudioChReserve - reserve channel failed"); 230 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 231 } 232 233 DEBUG_LOG(SCEAUDIO, "sceAudioChReserve(%08x, %08x, %08x)", chan, sampleCount, format); 234 chans[chan].sampleCount = sampleCount; 235 chans[chan].format = format; 236 chans[chan].reserved = true; 237 chans[chan].leftVolume = 0; 238 chans[chan].rightVolume = 0; 239 return chan; 240 } 241 242 static u32 sceAudioChRelease(u32 chan) { 243 if (chan >= PSP_AUDIO_CHANNEL_MAX) { 244 ERROR_LOG(SCEAUDIO, "sceAudioChRelease(%i) - bad channel", chan); 245 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 246 } 247 248 if (!chans[chan].reserved) { 249 ERROR_LOG(SCEAUDIO, "sceAudioChRelease(%i) - channel not reserved", chan); 250 return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; 251 } 252 // TODO: Does this error if busy? 253 chans[chan].reset(); 254 chans[chan].reserved = false; 255 return hleLogSuccessI(SCEAUDIO, 0); 256 } 257 258 static u32 sceAudioSetChannelDataLen(u32 chan, u32 len) { 259 int result = 0; 260 if (chan >= PSP_AUDIO_CHANNEL_MAX) { 261 ERROR_LOG(SCEAUDIO, "sceAudioSetChannelDataLen(%08x, %08x) - bad channel", chan, len); 262 result = SCE_ERROR_AUDIO_INVALID_CHANNEL; 263 } else if (!chans[chan].reserved) { 264 ERROR_LOG(SCEAUDIO, "sceAudioSetChannelDataLen(%08x, %08x) - channel not reserved", chan, len); 265 result = SCE_ERROR_AUDIO_CHANNEL_NOT_INIT; 266 } else if ((len & 63) != 0 || len == 0 || len > PSP_AUDIO_SAMPLE_MAX) { 267 ERROR_LOG(SCEAUDIO, "sceAudioSetChannelDataLen(%08x, %08x) - invalid sample count", chan, len); 268 result = SCE_ERROR_AUDIO_OUTPUT_SAMPLE_DATA_SIZE_NOT_ALIGNED; 269 } else { 270 chans[chan].sampleCount = len; 271 } 272 DEBUG_LOG(SCEAUDIO, "%08x = sceAudioSetChannelDataLen(%08x, %08x)", result , chan, len); 273 return result; 274 } 275 276 static u32 sceAudioChangeChannelConfig(u32 chan, u32 format) { 277 if (chan >= PSP_AUDIO_CHANNEL_MAX) { 278 ERROR_LOG(SCEAUDIO, "sceAudioChangeChannelConfig(%08x, %08x) - invalid channel number", chan, format); 279 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 280 } else if (!chans[chan].reserved) { 281 ERROR_LOG(SCEAUDIO, "sceAudioChangeChannelConfig(%08x, %08x) - channel not reserved", chan, format); 282 return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; 283 } else { 284 DEBUG_LOG(SCEAUDIO, "sceAudioChangeChannelConfig(%08x, %08x)", chan, format); 285 chans[chan].format = format; 286 return 0; 287 } 288 } 289 290 static u32 sceAudioChangeChannelVolume(u32 chan, u32 leftvol, u32 rightvol) { 291 if (leftvol > 0xFFFF || rightvol > 0xFFFF) { 292 ERROR_LOG(SCEAUDIO, "sceAudioChangeChannelVolume(%08x, %08x, %08x) - invalid volume", chan, leftvol, rightvol); 293 return SCE_ERROR_AUDIO_INVALID_VOLUME; 294 } else if (chan >= PSP_AUDIO_CHANNEL_MAX) { 295 ERROR_LOG(SCEAUDIO, "sceAudioChangeChannelVolume(%08x, %08x, %08x) - invalid channel number", chan, leftvol, rightvol); 296 return SCE_ERROR_AUDIO_INVALID_CHANNEL; 297 } else if (!chans[chan].reserved) { 298 ERROR_LOG(SCEAUDIO, "sceAudioChangeChannelVolume(%08x, %08x, %08x) - channel not reserved", chan, leftvol, rightvol); 299 return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; 300 } else { 301 DEBUG_LOG(SCEAUDIO, "sceAudioChangeChannelVolume(%08x, %08x, %08x)", chan, leftvol, rightvol); 302 chans[chan].leftVolume = leftvol; 303 chans[chan].rightVolume = rightvol; 304 return 0; 305 } 306 } 307 308 static u32 sceAudioInit() { 309 DEBUG_LOG(SCEAUDIO, "sceAudioInit()"); 310 // Don't need to do anything 311 return 0; 312 } 313 314 static u32 sceAudioEnd() { 315 DEBUG_LOG(SCEAUDIO, "sceAudioEnd()"); 316 // Don't need to do anything 317 return 0; 318 } 319 320 static u32 sceAudioOutput2Reserve(u32 sampleCount) { 321 auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2]; 322 // This seems to ignore the MSB, for some reason. 323 sampleCount &= 0x7FFFFFFF; 324 if (sampleCount < 17 || sampleCount > 4111) { 325 return hleLogError(SCEAUDIO, SCE_KERNEL_ERROR_INVALID_SIZE, "invalid sample count"); 326 } else if (chan.reserved) { 327 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_ALREADY_RESERVED, "channel already reserved"); 328 } 329 330 chan.sampleCount = sampleCount; 331 chan.format = PSP_AUDIO_FORMAT_STEREO; 332 chan.reserved = true; 333 __AudioSetSRCFrequency(0); 334 return hleLogSuccessI(SCEAUDIO, 0); 335 } 336 337 static u32 sceAudioOutput2OutputBlocking(u32 vol, u32 dataPtr) { 338 // Note: 0xFFFFF, not 0xFFFF! 339 if (vol > 0xFFFFF) { 340 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_INVALID_VOLUME, "invalid volume"); 341 } 342 343 auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2]; 344 if (!chan.reserved) { 345 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved"); 346 } 347 348 chan.leftVolume = vol; 349 chan.rightVolume = vol; 350 chan.sampleAddress = dataPtr; 351 352 hleEatCycles(10000); 353 int result = __AudioEnqueue(chan, PSP_AUDIO_CHANNEL_OUTPUT2, true); 354 if (result < 0) 355 return hleLogError(SCEAUDIO, result); 356 return hleLogSuccessI(SCEAUDIO, result); 357 } 358 359 static u32 sceAudioOutput2ChangeLength(u32 sampleCount) { 360 auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2]; 361 if (!chan.reserved) { 362 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved"); 363 } 364 chan.sampleCount = sampleCount; 365 return hleLogSuccessI(SCEAUDIO, 0); 366 } 367 368 static u32 sceAudioOutput2GetRestSample() { 369 auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2]; 370 if (!chan.reserved) { 371 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved"); 372 } 373 u32 size = (u32)chanSampleQueues[PSP_AUDIO_CHANNEL_OUTPUT2].size() / 2; 374 if (size > chan.sampleCount) { 375 // If ChangeLength reduces the size, it still gets output but this return is clamped. 376 size = chan.sampleCount; 377 } 378 return hleLogSuccessI(SCEAUDIO, size); 379 } 380 381 static u32 sceAudioOutput2Release() { 382 auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2]; 383 if (!chan.reserved) 384 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved"); 385 if (!chanSampleQueues[PSP_AUDIO_CHANNEL_OUTPUT2].empty()) 386 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_ALREADY_RESERVED, "output busy"); 387 388 chan.reset(); 389 chan.reserved = false; 390 return hleLogSuccessI(SCEAUDIO, 0); 391 } 392 393 static u32 sceAudioSetFrequency(u32 freq) { 394 // TODO: Not available from user code. 395 if (freq == 44100 || freq == 48000) { 396 INFO_LOG(SCEAUDIO, "sceAudioSetFrequency(%08x)", freq); 397 __AudioSetOutputFrequency(freq); 398 return 0; 399 } else { 400 ERROR_LOG(SCEAUDIO, "sceAudioSetFrequency(%08x) - invalid frequency (must be 44.1 or 48 khz)", freq); 401 return SCE_ERROR_AUDIO_INVALID_FREQUENCY; 402 } 403 } 404 405 static u32 sceAudioSetVolumeOffset() { 406 ERROR_LOG(SCEAUDIO, "UNIMPL sceAudioSetVolumeOffset()"); 407 return 0; 408 } 409 410 static bool SRCFrequencyAllowed(int freq) { 411 if (freq == 44100 || freq == 22050 || freq == 11025) 412 return true; 413 if (freq == 48000 || freq == 32000 || freq == 24000 || freq == 16000 || freq == 12000 || freq == 8000) 414 return true; 415 return false; 416 } 417 418 static u32 sceAudioSRCChReserve(u32 sampleCount, u32 freq, u32 format) { 419 auto &chan = chans[PSP_AUDIO_CHANNEL_SRC]; 420 // This seems to ignore the MSB, for some reason. 421 sampleCount &= 0x7FFFFFFF; 422 if (format == 4) { 423 return hleReportError(SCEAUDIO, PSP_AUDIO_ERROR_SRC_FORMAT_4, "unexpected format"); 424 } else if (format != 2) { 425 return hleLogError(SCEAUDIO, SCE_KERNEL_ERROR_INVALID_SIZE, "unexpected format"); 426 } else if (sampleCount < 17 || sampleCount > 4111) { 427 return hleLogError(SCEAUDIO, SCE_KERNEL_ERROR_INVALID_SIZE, "invalid sample count"); 428 } else if (freq != 0 && !SRCFrequencyAllowed(freq)) { 429 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_INVALID_FREQUENCY, "invalid frequency"); 430 } else if (chan.reserved) { 431 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_ALREADY_RESERVED, "channel already reserved"); 432 } 433 434 chan.reserved = true; 435 chan.sampleCount = sampleCount; 436 chan.format = format == 2 ? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO; 437 // Zero means default to 44.1kHz. 438 __AudioSetSRCFrequency(freq); 439 return hleLogSuccessI(SCEAUDIO, 0); 440 } 441 442 static u32 sceAudioSRCChRelease() { 443 auto &chan = chans[PSP_AUDIO_CHANNEL_SRC]; 444 if (!chan.reserved) 445 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved"); 446 if (!chanSampleQueues[PSP_AUDIO_CHANNEL_SRC].empty()) 447 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_ALREADY_RESERVED, "output busy"); 448 449 chan.reset(); 450 chan.reserved = false; 451 return hleLogSuccessI(SCEAUDIO, 0); 452 } 453 454 static u32 sceAudioSRCOutputBlocking(u32 vol, u32 buf) { 455 if (vol > 0xFFFFF) { 456 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_INVALID_VOLUME, "invalid volume"); 457 } 458 459 auto &chan = chans[PSP_AUDIO_CHANNEL_SRC]; 460 if (!chan.reserved) { 461 return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved"); 462 } 463 464 chan.leftVolume = vol; 465 chan.rightVolume = vol; 466 chan.sampleAddress = buf; 467 468 hleEatCycles(10000); 469 int result = __AudioEnqueue(chan, PSP_AUDIO_CHANNEL_SRC, true); 470 if (result < 0) 471 return hleLogError(SCEAUDIO, result); 472 return hleLogSuccessI(SCEAUDIO, result); 473 } 474 475 static int sceAudioInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { 476 if (!Memory::IsValidAddress(bufAddr)) { 477 ERROR_LOG(HLE, "sceAudioInputBlocking(%d, %d, %08x): invalid addresses", maxSamples, sampleRate, bufAddr); 478 return -1; 479 } 480 481 INFO_LOG(HLE, "sceAudioInputBlocking: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); 482 return __MicInput(maxSamples, sampleRate, bufAddr, AUDIOINPUT); 483 } 484 485 static int sceAudioInput(u32 maxSamples, u32 sampleRate, u32 bufAddr) { 486 if (!Memory::IsValidAddress(bufAddr)) { 487 ERROR_LOG(HLE, "sceAudioInput(%d, %d, %08x): invalid addresses", maxSamples, sampleRate, bufAddr); 488 return -1; 489 } 490 491 ERROR_LOG(HLE, "UNTEST sceAudioInput: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); 492 return __MicInput(maxSamples, sampleRate, bufAddr, AUDIOINPUT, false); 493 } 494 495 static int sceAudioGetInputLength() { 496 int ret = Microphone::getReadMicDataLength() / 2; 497 ERROR_LOG(HLE, "UNTEST sceAudioGetInputLength(ret: %d)", ret); 498 return ret; 499 } 500 501 static u32 sceAudioRoutingSetMode(u32 mode) { 502 ERROR_LOG_REPORT(SCEAUDIO, "sceAudioRoutingSetMode(%08x)", mode); 503 int previousMode = defaultRoutingMode; 504 defaultRoutingMode = mode; 505 return previousMode; 506 } 507 508 static u32 sceAudioRoutingGetMode() { 509 ERROR_LOG_REPORT(SCEAUDIO, "sceAudioRoutingGetMode()"); 510 return defaultRoutingMode; 511 } 512 513 static u32 sceAudioRoutingSetVolumeMode(u32 mode) { 514 ERROR_LOG_REPORT(SCEAUDIO, "sceAudioRoutingSetVolumeMode(%08x)", mode); 515 int previousMode = defaultRoutingVolMode; 516 defaultRoutingVolMode = mode; 517 return previousMode; 518 } 519 520 static u32 sceAudioRoutingGetVolumeMode() { 521 ERROR_LOG_REPORT(SCEAUDIO, "sceAudioRoutingGetVolumeMode()"); 522 return defaultRoutingVolMode; 523 } 524 525 const HLEFunction sceAudio[] = 526 { 527 // Newer simplified single channel audio output. Presumably for games that use Atrac3 528 // directly from Sas instead of playing it on a separate audio channel. 529 {0X01562BA3, &WrapU_U<sceAudioOutput2Reserve>, "sceAudioOutput2Reserve", 'x', "i" }, 530 {0X2D53F36E, &WrapU_UU<sceAudioOutput2OutputBlocking>, "sceAudioOutput2OutputBlocking", 'x', "xx" }, 531 {0X63F2889C, &WrapU_U<sceAudioOutput2ChangeLength>, "sceAudioOutput2ChangeLength", 'x', "i" }, 532 {0X647CEF33, &WrapU_V<sceAudioOutput2GetRestSample>, "sceAudioOutput2GetRestSample", 'i', "" }, 533 {0X43196845, &WrapU_V<sceAudioOutput2Release>, "sceAudioOutput2Release", 'x', "" }, 534 535 // "Traditional" audio channel interface 536 {0X80F1F7E0, &WrapU_V<sceAudioInit>, "sceAudioInit", 'x', "" }, 537 {0X210567F7, &WrapU_V<sceAudioEnd>, "sceAudioEnd", 'x', "" }, 538 {0XA2BEAA6C, &WrapU_U<sceAudioSetFrequency>, "sceAudioSetFrequency", 'x', "i" }, 539 {0X927AC32B, &WrapU_V<sceAudioSetVolumeOffset>, "sceAudioSetVolumeOffset", 'x', "" }, 540 {0X8C1009B2, &WrapU_UIU<sceAudioOutput>, "sceAudioOutput", 'x', "ixx" }, 541 {0X136CAF51, &WrapU_UIU<sceAudioOutputBlocking>, "sceAudioOutputBlocking", 'x', "ixx" }, 542 {0XE2D56B2D, &WrapU_UIIU<sceAudioOutputPanned>, "sceAudioOutputPanned", 'x', "ixxx"}, 543 {0X13F592BC, &WrapU_UIIU<sceAudioOutputPannedBlocking>, "sceAudioOutputPannedBlocking", 'x', "ixxx"}, 544 {0X5EC81C55, &WrapU_IUU<sceAudioChReserve>, "sceAudioChReserve", 'x', "iii" }, 545 {0X6FC46853, &WrapU_U<sceAudioChRelease>, "sceAudioChRelease", 'x', "i" }, 546 {0XE9D97901, &WrapI_U<sceAudioGetChannelRestLen>, "sceAudioGetChannelRestLen", 'i', "i" }, 547 {0XB011922F, &WrapI_U<sceAudioGetChannelRestLength>, "sceAudioGetChannelRestLength", 'i', "i" }, 548 {0XCB2E439E, &WrapU_UU<sceAudioSetChannelDataLen>, "sceAudioSetChannelDataLen", 'x', "ii" }, 549 {0X95FD0C2D, &WrapU_UU<sceAudioChangeChannelConfig>, "sceAudioChangeChannelConfig", 'x', "ii" }, 550 {0XB7E1D8E7, &WrapU_UUU<sceAudioChangeChannelVolume>, "sceAudioChangeChannelVolume", 'x', "ixx" }, 551 552 // Like Output2, but with ability to do sample rate conversion. 553 {0X38553111, &WrapU_UUU<sceAudioSRCChReserve>, "sceAudioSRCChReserve", 'x', "iii" }, 554 {0X5C37C0AE, &WrapU_V<sceAudioSRCChRelease>, "sceAudioSRCChRelease", 'x', "" }, 555 {0XE0727056, &WrapU_UU<sceAudioSRCOutputBlocking>, "sceAudioSRCOutputBlocking", 'x', "xx" }, 556 557 // Never seen these used 558 {0X41EFADE7, nullptr, "sceAudioOneshotOutput", '?', "" }, 559 {0XB61595C0, nullptr, "sceAudioLoopbackTest", '?', "" }, 560 561 // Microphone interface 562 {0X7DE61688, nullptr, "sceAudioInputInit", '?', "" }, 563 {0XE926D3FB, nullptr, "sceAudioInputInitEx", '?', "" }, 564 {0X6D4BEC68, &WrapI_UUU<sceAudioInput>, "sceAudioInput", 'i', "xxx" }, 565 {0X086E5895, &WrapI_UUU<sceAudioInputBlocking>, "sceAudioInputBlocking", 'i', "xxx" }, 566 {0XA708C6A6, &WrapI_V<sceAudioGetInputLength>, "sceAudioGetInputLength", 'i', "" }, 567 {0XA633048E, nullptr, "sceAudioPollInputEnd", '?', "" }, 568 {0X87B2E651, nullptr, "sceAudioWaitInputEnd", '?', "" }, 569 570 {0X36FD8AA9, &WrapU_U<sceAudioRoutingSetMode>, "sceAudioRoutingSetMode", 'x', "x" }, 571 {0X39240E7D, &WrapU_V<sceAudioRoutingGetMode>, "sceAudioRoutingGetMode", 'x', "" }, 572 {0XBB548475, &WrapU_U<sceAudioRoutingSetVolumeMode>, "sceAudioRoutingSetVolumeMode", 'x', "x" }, 573 {0X28235C56, &WrapU_V<sceAudioRoutingGetVolumeMode>, "sceAudioRoutingGetVolumeMode", 'x', "" }, 574 575 }; 576 577 void Register_sceAudio() 578 { 579 RegisterModule("sceAudio", ARRAY_SIZE(sceAudio), sceAudio); 580 } 581