summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/audio/vita
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/audio/vita')
-rw-r--r--contrib/SDL-3.2.8/src/audio/vita/SDL_vitaaudio.c238
-rw-r--r--contrib/SDL-3.2.8/src/audio/vita/SDL_vitaaudio.h41
2 files changed, 279 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/audio/vita/SDL_vitaaudio.c b/contrib/SDL-3.2.8/src/audio/vita/SDL_vitaaudio.c
new file mode 100644
index 0000000..e194f21
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/audio/vita/SDL_vitaaudio.c
@@ -0,0 +1,238 @@
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_VITA
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_vitaaudio.h"
32
33#include <psp2/kernel/threadmgr.h>
34#include <psp2/audioout.h>
35#include <psp2/audioin.h>
36
37#define SCE_AUDIO_SAMPLE_ALIGN(s) (((s) + 63) & ~63)
38#define SCE_AUDIO_MAX_VOLUME 0x8000
39
40static bool VITAAUD_OpenRecordingDevice(SDL_AudioDevice *device)
41{
42 device->spec.freq = 16000;
43 device->spec.channels = 1;
44 device->sample_frames = 512;
45
46 SDL_UpdatedAudioDeviceFormat(device);
47
48 device->hidden->port = sceAudioInOpenPort(SCE_AUDIO_IN_PORT_TYPE_VOICE, 512, 16000, SCE_AUDIO_IN_PARAM_FORMAT_S16_MONO);
49
50 if (device->hidden->port < 0) {
51 return SDL_SetError("Couldn't open audio in port: %x", device->hidden->port);
52 }
53
54 return true;
55}
56
57static bool VITAAUD_OpenDevice(SDL_AudioDevice *device)
58{
59 int format, mixlen, i, port = SCE_AUDIO_OUT_PORT_TYPE_MAIN;
60 int vols[2] = { SCE_AUDIO_MAX_VOLUME, SCE_AUDIO_MAX_VOLUME };
61 SDL_AudioFormat test_format;
62 const SDL_AudioFormat *closefmts;
63
64 device->hidden = (struct SDL_PrivateAudioData *)
65 SDL_calloc(1, sizeof(*device->hidden));
66 if (!device->hidden) {
67 return false;
68 }
69
70 closefmts = SDL_ClosestAudioFormats(device->spec.format);
71 while ((test_format = *(closefmts++)) != 0) {
72 if (test_format == SDL_AUDIO_S16LE) {
73 device->spec.format = test_format;
74 break;
75 }
76 }
77
78 if (!test_format) {
79 return SDL_SetError("Unsupported audio format");
80 }
81
82 if (device->recording) {
83 return VITAAUD_OpenRecordingDevice(device);
84 }
85
86 // The sample count must be a multiple of 64.
87 device->sample_frames = SCE_AUDIO_SAMPLE_ALIGN(device->sample_frames);
88
89 // Update the fragment size as size in bytes.
90 SDL_UpdatedAudioDeviceFormat(device);
91
92 /* Allocate the mixing buffer. Its size and starting address must
93 be a multiple of 64 bytes. Our sample count is already a multiple of
94 64, so spec->size should be a multiple of 64 as well. */
95 mixlen = device->buffer_size * NUM_BUFFERS;
96 device->hidden->rawbuf = (Uint8 *)SDL_aligned_alloc(64, mixlen);
97 if (!device->hidden->rawbuf) {
98 return SDL_SetError("Couldn't allocate mixing buffer");
99 }
100
101 // Setup the hardware channel.
102 if (device->spec.channels == 1) {
103 format = SCE_AUDIO_OUT_MODE_MONO;
104 } else {
105 format = SCE_AUDIO_OUT_MODE_STEREO;
106 }
107
108 // the main port requires 48000Hz audio, so this drops to the background music port if necessary
109 if (device->spec.freq < 48000) {
110 port = SCE_AUDIO_OUT_PORT_TYPE_BGM;
111 }
112
113 device->hidden->port = sceAudioOutOpenPort(port, device->sample_frames, device->spec.freq, format);
114 if (device->hidden->port < 0) {
115 SDL_aligned_free(device->hidden->rawbuf);
116 device->hidden->rawbuf = NULL;
117 return SDL_SetError("Couldn't open audio out port: %x", device->hidden->port);
118 }
119
120 sceAudioOutSetVolume(device->hidden->port, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, vols);
121
122 SDL_memset(device->hidden->rawbuf, 0, mixlen);
123 for (i = 0; i < NUM_BUFFERS; i++) {
124 device->hidden->mixbufs[i] = &device->hidden->rawbuf[i * device->buffer_size];
125 }
126
127 device->hidden->next_buffer = 0;
128 return true;
129}
130
131static bool VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
132{
133 return (sceAudioOutOutput(device->hidden->port, buffer) == 0);
134}
135
136// This function waits until it is possible to write a full sound buffer
137static bool VITAAUD_WaitDevice(SDL_AudioDevice *device)
138{
139 // !!! FIXME: we might just need to sleep roughly as long as playback buffers take to process, based on sample rate, etc.
140 while (!SDL_GetAtomicInt(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) {
141 SDL_Delay(1);
142 }
143 return true;
144}
145
146static Uint8 *VITAAUD_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
147{
148 Uint8 *result = device->hidden->mixbufs[device->hidden->next_buffer];
149 device->hidden->next_buffer = (device->hidden->next_buffer + 1) % NUM_BUFFERS;
150 return result;
151}
152
153static void VITAAUD_CloseDevice(SDL_AudioDevice *device)
154{
155 if (device->hidden) {
156 if (device->hidden->port >= 0) {
157 if (device->recording) {
158 sceAudioInReleasePort(device->hidden->port);
159 } else {
160 sceAudioOutReleasePort(device->hidden->port);
161 }
162 device->hidden->port = -1;
163 }
164
165 if (!device->recording && device->hidden->rawbuf) {
166 SDL_aligned_free(device->hidden->rawbuf); // this uses SDL_aligned_alloc(), not SDL_malloc()
167 device->hidden->rawbuf = NULL;
168 }
169 SDL_free(device->hidden);
170 device->hidden = NULL;
171 }
172}
173
174static bool VITAAUD_WaitRecordingDevice(SDL_AudioDevice *device)
175{
176 // there's only a blocking call to obtain more data, so we'll just sleep as
177 // long as a buffer would run.
178 const Uint64 endticks = SDL_GetTicks() + ((device->sample_frames * 1000) / device->spec.freq);
179 while (!SDL_GetAtomicInt(&device->shutdown) && (SDL_GetTicks() < endticks)) {
180 SDL_Delay(1);
181 }
182 return true;
183}
184
185static int VITAAUD_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
186{
187 int ret;
188 SDL_assert(buflen == device->buffer_size);
189 ret = sceAudioInInput(device->hidden->port, buffer);
190 if (ret < 0) {
191 SDL_SetError("Failed to record from device: %x", ret);
192 return -1;
193 }
194 return device->buffer_size;
195}
196
197static void VITAAUD_FlushRecording(SDL_AudioDevice *device)
198{
199 // just grab the latest and dump it.
200 sceAudioInInput(device->hidden->port, device->work_buffer);
201}
202
203static void VITAAUD_ThreadInit(SDL_AudioDevice *device)
204{
205 // Increase the priority of this audio thread by 1 to put it ahead of other SDL threads.
206 SceUID thid;
207 SceKernelThreadInfo info;
208 thid = sceKernelGetThreadId();
209 info.size = sizeof(SceKernelThreadInfo);
210 if (sceKernelGetThreadInfo(thid, &info) == 0) {
211 sceKernelChangeThreadPriority(thid, info.currentPriority - 1);
212 }
213}
214
215static bool VITAAUD_Init(SDL_AudioDriverImpl *impl)
216{
217 impl->OpenDevice = VITAAUD_OpenDevice;
218 impl->PlayDevice = VITAAUD_PlayDevice;
219 impl->WaitDevice = VITAAUD_WaitDevice;
220 impl->GetDeviceBuf = VITAAUD_GetDeviceBuf;
221 impl->CloseDevice = VITAAUD_CloseDevice;
222 impl->ThreadInit = VITAAUD_ThreadInit;
223 impl->WaitRecordingDevice = VITAAUD_WaitRecordingDevice;
224 impl->FlushRecording = VITAAUD_FlushRecording;
225 impl->RecordDevice = VITAAUD_RecordDevice;
226
227 impl->HasRecordingSupport = true;
228 impl->OnlyHasDefaultPlaybackDevice = true;
229 impl->OnlyHasDefaultRecordingDevice = true;
230
231 return true;
232}
233
234AudioBootStrap VITAAUD_bootstrap = {
235 "vita", "VITA audio driver", VITAAUD_Init, false, false
236};
237
238#endif // SDL_AUDIO_DRIVER_VITA
diff --git a/contrib/SDL-3.2.8/src/audio/vita/SDL_vitaaudio.h b/contrib/SDL-3.2.8/src/audio/vita/SDL_vitaaudio.h
new file mode 100644
index 0000000..1e97499
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/audio/vita/SDL_vitaaudio.h
@@ -0,0 +1,41 @@
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
22#ifndef SDL_vitaaudio_h
23#define SDL_vitaaudio_h
24
25#include "../SDL_sysaudio.h"
26
27#define NUM_BUFFERS 2
28
29struct SDL_PrivateAudioData
30{
31 // The hardware input/output port.
32 int port;
33 // The raw allocated mixing buffer.
34 Uint8 *rawbuf;
35 // Individual mixing buffers.
36 Uint8 *mixbufs[NUM_BUFFERS];
37 // Index of the next available mixing buffer.
38 int next_buffer;
39};
40
41#endif // SDL_vitaaudio_h