summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/audio/psp/SDL_pspaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/audio/psp/SDL_pspaudio.c')
-rw-r--r--contrib/SDL-3.2.8/src/audio/psp/SDL_pspaudio.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/audio/psp/SDL_pspaudio.c b/contrib/SDL-3.2.8/src/audio/psp/SDL_pspaudio.c
new file mode 100644
index 0000000..18546e8
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/audio/psp/SDL_pspaudio.c
@@ -0,0 +1,183 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifdef SDL_AUDIO_DRIVER_PSP
24
25#include <stdio.h>
26#include <string.h>
27#include <stdlib.h>
28
29#include "../SDL_audiodev_c.h"
30#include "../SDL_sysaudio.h"
31#include "SDL_pspaudio.h"
32
33#include <pspaudio.h>
34#include <pspthreadman.h>
35
36static bool isBasicAudioConfig(const SDL_AudioSpec *spec)
37{
38 return spec->freq == 44100;
39}
40
41static bool PSPAUDIO_OpenDevice(SDL_AudioDevice *device)
42{
43 device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
44 if (!device->hidden) {
45 return false;
46 }
47
48 // device only natively supports S16LSB
49 device->spec.format = SDL_AUDIO_S16LE;
50
51 /* PSP has some limitations with the Audio. It fully supports 44.1KHz (Mono & Stereo),
52 however with frequencies different than 44.1KHz, it just supports Stereo,
53 so a resampler must be done for these scenarios */
54 if (isBasicAudioConfig(&device->spec)) {
55 // The sample count must be a multiple of 64.
56 device->sample_frames = PSP_AUDIO_SAMPLE_ALIGN(device->sample_frames);
57 // The number of channels (1 or 2).
58 device->spec.channels = device->spec.channels == 1 ? 1 : 2;
59 const int format = (device->spec.channels == 1) ? PSP_AUDIO_FORMAT_MONO : PSP_AUDIO_FORMAT_STEREO;
60 device->hidden->channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, device->sample_frames, format);
61 } else {
62 // 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11050, 8000
63 switch (device->spec.freq) {
64 case 8000:
65 case 11025:
66 case 12000:
67 case 16000:
68 case 22050:
69 case 24000:
70 case 32000:
71 case 44100:
72 case 48000:
73 break; // acceptable, keep it
74 default:
75 device->spec.freq = 48000;
76 break;
77 }
78 // The number of samples to output in one output call (min 17, max 4111).
79 device->sample_frames = device->sample_frames < 17 ? 17 : (device->sample_frames > 4111 ? 4111 : device->sample_frames);
80 device->spec.channels = 2; // we're forcing the hardware to stereo.
81 device->hidden->channel = sceAudioSRCChReserve(device->sample_frames, device->spec.freq, 2);
82 }
83
84 if (device->hidden->channel < 0) {
85 return SDL_SetError("Couldn't reserve hardware channel");
86 }
87
88 // Update the fragment size as size in bytes.
89 SDL_UpdatedAudioDeviceFormat(device);
90
91 /* Allocate the mixing buffer. Its size and starting address must
92 be a multiple of 64 bytes. Our sample count is already a multiple of
93 64, so spec->size should be a multiple of 64 as well. */
94 const int mixlen = device->buffer_size * NUM_BUFFERS;
95 device->hidden->rawbuf = (Uint8 *)SDL_aligned_alloc(64, mixlen);
96 if (!device->hidden->rawbuf) {
97 return SDL_SetError("Couldn't allocate mixing buffer");
98 }
99
100 SDL_memset(device->hidden->rawbuf, device->silence_value, mixlen);
101 for (int i = 0; i < NUM_BUFFERS; i++) {
102 device->hidden->mixbufs[i] = &device->hidden->rawbuf[i * device->buffer_size];
103 }
104
105 return true;
106}
107
108static bool PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
109{
110 int rc;
111 if (!isBasicAudioConfig(&device->spec)) {
112 SDL_assert(device->spec.channels == 2);
113 rc = sceAudioSRCOutputBlocking(PSP_AUDIO_VOLUME_MAX, (void *) buffer);
114 } else {
115 rc = sceAudioOutputPannedBlocking(device->hidden->channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, (void *) buffer);
116 }
117 return (rc == 0);
118}
119
120static bool PSPAUDIO_WaitDevice(SDL_AudioDevice *device)
121{
122 return true; // Because we block when sending audio, there's no need for this function to do anything.
123}
124
125static Uint8 *PSPAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
126{
127 Uint8 *buffer = device->hidden->mixbufs[device->hidden->next_buffer];
128 device->hidden->next_buffer = (device->hidden->next_buffer + 1) % NUM_BUFFERS;
129 return buffer;
130}
131
132static void PSPAUDIO_CloseDevice(SDL_AudioDevice *device)
133{
134 if (device->hidden) {
135 if (device->hidden->channel >= 0) {
136 if (!isBasicAudioConfig(&device->spec)) {
137 sceAudioSRCChRelease();
138 } else {
139 sceAudioChRelease(device->hidden->channel);
140 }
141 device->hidden->channel = -1;
142 }
143
144 if (device->hidden->rawbuf) {
145 SDL_aligned_free(device->hidden->rawbuf);
146 device->hidden->rawbuf = NULL;
147 }
148 SDL_free(device->hidden);
149 device->hidden = NULL;
150 }
151}
152
153static void PSPAUDIO_ThreadInit(SDL_AudioDevice *device)
154{
155 /* Increase the priority of this audio thread by 1 to put it
156 ahead of other SDL threads. */
157 const SceUID thid = sceKernelGetThreadId();
158 SceKernelThreadInfo status;
159 status.size = sizeof(SceKernelThreadInfo);
160 if (sceKernelReferThreadStatus(thid, &status) == 0) {
161 sceKernelChangeThreadPriority(thid, status.currentPriority - 1);
162 }
163}
164
165static bool PSPAUDIO_Init(SDL_AudioDriverImpl *impl)
166{
167 impl->OpenDevice = PSPAUDIO_OpenDevice;
168 impl->PlayDevice = PSPAUDIO_PlayDevice;
169 impl->WaitDevice = PSPAUDIO_WaitDevice;
170 impl->GetDeviceBuf = PSPAUDIO_GetDeviceBuf;
171 impl->CloseDevice = PSPAUDIO_CloseDevice;
172 impl->ThreadInit = PSPAUDIO_ThreadInit;
173 impl->OnlyHasDefaultPlaybackDevice = true;
174 //impl->HasRecordingSupport = true;
175 //impl->OnlyHasDefaultRecordingDevice = true;
176 return true;
177}
178
179AudioBootStrap PSPAUDIO_bootstrap = {
180 "psp", "PSP audio driver", PSPAUDIO_Init, false, false
181};
182
183#endif // SDL_AUDIO_DRIVER_PSP