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