PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
adpcm.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2005, ps2dev - http://www.ps2dev.org
7# Licenced under GNU Library General Public License version 2
8*/
9
15#include <stdio.h>
16#include <thbase.h>
17#include <thsemap.h>
18#include <loadcore.h>
19#include <sysmem.h>
20#include <intrman.h>
21#include <libsd.h>
22#include <sysclib.h>
23
24#include <audsrv.h>
25#include "audsrv_internal.h"
26#include "common.h"
27#include "rpc_server.h"
28#include "spu.h"
29#include "debug_printf.h"
30
31typedef struct adpcm_list_t
32{
33 struct adpcm_list_t *next;
34
35 int id;
36 int pitch;
37 int loop;
38 int channels;
39 int size;
40 int spu2_addr;
42
43static adpcm_list_t *adpcm_list_head = 0;
44static adpcm_list_t *adpcm_list_tail = 0;
45
46static u32 sbuffer[16] __attribute__((aligned(16)));
47
50{
51 void *buffer;
52 int OldState;
53
54 CpuSuspendIntr(&OldState);
55 buffer = AllocSysMemory(ALLOC_FIRST, sizeof(adpcm_list_t), NULL);
56 CpuResumeIntr(OldState);
57
58 return buffer;
59}
60
62static void free_all_samples()
63{
64 adpcm_list_t *p, *q;
65 int OldState;
66
67 CpuSuspendIntr(&OldState);
68 for (p = adpcm_list_head; p != NULL; p = q)
69 {
70 q = p->next;
71 FreeSysMemory(p);
72 }
73
74 adpcm_list_head = NULL;
75 adpcm_list_tail = NULL;
76 CpuResumeIntr(OldState);
77}
78
84int free_sample(u32 id)
85{
86 adpcm_list_t *adpcm = adpcm_list_head;
87 adpcm_list_t *parent = NULL;
88
89 while (adpcm != NULL)
90 {
91 if (adpcm->id == id)
92 {
93 break;
94 }
95
96 parent = adpcm;
97 adpcm = adpcm->next;
98 }
99
100 if (adpcm == NULL)
101 {
102 return AUDSRV_ERR_NOERROR;
103 }
104
105 if (parent != NULL)
106 parent->next = adpcm->next;
107
108 if (adpcm_list_head == adpcm)
109 adpcm_list_head = adpcm->next;
110
111 if (adpcm_list_tail == adpcm)
112 adpcm_list_tail = parent;
113
114 int OldState;
115 CpuSuspendIntr(&OldState);
116 FreeSysMemory(adpcm);
117 CpuResumeIntr(OldState);
118
119 return AUDSRV_ERR_NOERROR;
120}
121
127{
128 adpcm_list_t *cur = adpcm_list_head;
129
130 while (cur != NULL)
131 {
132 if (cur->id == id)
133 {
134 return cur;
135 }
136
137 cur = cur->next;
138 }
139
140 return NULL;
141}
142
147static void audsrv_read_adpcm_header(adpcm_list_t *adpcm, const u32 *buffer)
148{
149 adpcm->pitch = buffer[2];
150 adpcm->loop = (buffer[1] >> 16) & 0xFF;
151 adpcm->channels = (buffer[1] >> 8) & 0xFF;
152}
153
160void *audsrv_load_adpcm(u32 *buffer, int size, int id)
161{
162 adpcm_list_t *adpcm;
163
164 adpcm = adpcm_loaded(id);
165 if (adpcm == NULL)
166 {
167 int spu2_addr = 0x5010; /* Need to change this so it considers to PCM streaming space usage :) */
168 if (adpcm_list_tail != NULL)
169 {
170 spu2_addr = adpcm_list_tail->spu2_addr + adpcm_list_tail->size;
171 }
172 if (spu2_addr + size - 16 > 2097152)
173 {
174 sbuffer[0] = -AUDSRV_ERR_OUT_OF_MEMORY;
175 return sbuffer;
176 }
177
178 adpcm = alloc_new_sample();
179 adpcm->id = id;
180 adpcm->spu2_addr = spu2_addr;
181 adpcm->size = size - 16; /* header is 16 bytes */
182 adpcm->next = NULL;
183
184 audsrv_read_adpcm_header(adpcm, buffer);
185
186 if (adpcm_list_head == NULL)
187 {
188 /* first entry ever! yay! */
189 adpcm_list_head = adpcm;
190 adpcm_list_tail = adpcm_list_head;
191 }
192 else
193 {
194 /* add at the end of the list */
195 adpcm_list_tail->next = adpcm;
196 adpcm_list_tail = adpcm;
197 }
198
199 /* DMA from IOP to SPU2 */
200 sceSdVoiceTrans(AUDSRV_VOICE_DMA_CH, SD_TRANS_WRITE | SD_TRANS_MODE_DMA, ((u8*)buffer)+16, (u32*)adpcm->spu2_addr, adpcm->size);
201 sceSdVoiceTransStatus(AUDSRV_VOICE_DMA_CH, 1);
202 }
203
204 sbuffer[0] = 0;
205 sbuffer[1] = adpcm->pitch;
206 sbuffer[2] = adpcm->loop;
207 sbuffer[3] = adpcm->channels;
208 return sbuffer;
209}
210
211int audsrv_is_adpcm_playing(int ch, u32 id)
212{
213 u32 endx;
214 adpcm_list_t *a;
215
216 if (ch > 24)
217 return 0;
218
219 endx = sceSdGetSwitch(SD_CORE_1 | SD_SWITCH_ENDX);
220 if ((endx & (1 << ch)) != 0)
221 return 0;
222
223 a = adpcm_loaded(id);
224 if (a == NULL)
225 {
226 /* bad joke */
227 return AUDSRV_ERR_ARGS;
228 }
229
230 return a->spu2_addr == sceSdGetAddr(SD_CORE_1 | (ch << 1) | SD_VOICE_START);
231}
232
233static int audsrv_adpcm_alloc_channel(void)
234{
235 int i, channel;
236 u32 endx;
237
238 endx = sceSdGetSwitch(SD_CORE_1 | SD_SWITCH_ENDX);
239 if (endx == 0)
240 {
241 /* all channels are occupied */
242 return -AUDSRV_ERR_NO_MORE_CHANNELS;
243 }
244
245 /* find first channel available */
246 i = 1;
247 channel = -1;
248 while ((channel < 0) && (i < 24))
249 {
250 if (endx & (1 << i))
251 {
252 channel = i;
253 }
254
255 i++;
256 }
257
258 if (channel == -1)
259 {
260 /* cannot find a single channel free */
261 return -AUDSRV_ERR_NO_MORE_CHANNELS;
262 }
263
264 return channel;
265}
266
277int audsrv_ch_play_adpcm(int ch, u32 id)
278{
279 int channel;
280 u32 endx;
281 adpcm_list_t *a;
282
283 a = adpcm_loaded(id);
284 if (a == NULL)
285 {
286 /* bad joke */
287 return AUDSRV_ERR_ARGS;
288 }
289
290 /* sample was loaded */
291 if (ch >= 0 && ch < 24)
292 {
293 endx = sceSdGetSwitch(SD_CORE_1 | SD_SWITCH_ENDX);
294 if (!(endx & (1 << ch)))
295 {
296 /* Channel in use. */
297 return -AUDSRV_ERR_NO_MORE_CHANNELS;
298 }
299
300 channel = ch;
301 }
302 else
303 {
304 channel = audsrv_adpcm_alloc_channel();
305 if (channel < 0)
306 return channel;
307 }
308
309 sceSdSetParam(SD_CORE_1 | (channel << 1) | SD_VPARAM_PITCH, a->pitch);
310 sceSdSetAddr(SD_CORE_1 | (channel << 1) | SD_VOICE_START, a->spu2_addr);
311 sceSdSetSwitch(SD_CORE_1 | SD_SWITCH_KON, (1 << channel));
312 return channel;
313}
314
320{
321 int voice;
322
323 printf("audsrv_adpcm_init()\n");
324
325 for (voice = 0; voice < 24; voice++)
326 {
327 sceSdSetSwitch(SD_CORE_1 | SD_SWITCH_KOFF, (1 << voice));
328 sceSdSetParam(SD_CORE_1 | (voice << 1) | SD_VPARAM_VOLL, 0x3fff);
329 sceSdSetParam(SD_CORE_1 | (voice << 1) | SD_VPARAM_VOLR, 0x3fff);
330 }
331
332 if (adpcm_list_head != NULL)
333 {
334 /* called second time, after samples were already uploaded */
336 }
337
338 return AUDSRV_ERR_NOERROR;
339}
340
347int audsrv_adpcm_set_volume(int ch, int voll, int volr)
348{
349 if (voll < 0 || voll > MAX_VOLUME || volr < 0 || volr > MAX_VOLUME)
350 {
351 /* bad joke */
352 return AUDSRV_ERR_ARGS;
353 }
354
355 sceSdSetParam(SD_CORE_1 | (ch << 1) | SD_VPARAM_VOLL, voll);
356 sceSdSetParam(SD_CORE_1 | (ch << 1) | SD_VPARAM_VOLR, volr);
357
358 return AUDSRV_ERR_NOERROR;
359}
360
int audsrv_is_adpcm_playing(int ch, audsrv_adpcm_t *adpcm)
Definition audsrv_rpc.c:487
#define AUDSRV_ERR_NOERROR
Definition audsrv.h:28
#define MAX_VOLUME
Definition audsrv.h:25
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
static void audsrv_read_adpcm_header(adpcm_list_t *adpcm, const u32 *buffer)
Definition adpcm.c:147
void * audsrv_load_adpcm(u32 *buffer, int size, int id)
Definition adpcm.c:160
static adpcm_list_t * alloc_new_sample(void)
Definition adpcm.c:49
int audsrv_ch_play_adpcm(int ch, u32 id)
Definition adpcm.c:277
static adpcm_list_t * adpcm_loaded(int id)
Definition adpcm.c:126
int audsrv_adpcm_init()
Definition adpcm.c:319
static void free_all_samples()
Definition adpcm.c:62
int free_sample(u32 id)
Definition adpcm.c:84