26#define MIN(a,b) ((a) <= (b)) ? (a) : (b)
37static int initialized = 0;
38static int rpc_server_thread_id;
40static int completion_sema;
42static audsrv_callback_t on_cdda_stop = NULL;
43static void *on_cdda_stop_arg = NULL;
45static audsrv_callback_t on_fillbuf = NULL;
46static void *on_fillbuf_arg = NULL;
48static const unsigned short vol_values[26] =
51 0x0000, 0x0096, 0x0190, 0x0230, 0x0320,
52 0x042E, 0x0532, 0x05FA, 0x06C2, 0x088E,
53 0x09F6, 0x0BC2, 0x0DC0, 0x0FF0, 0x118A,
54 0x1482, 0x1752, 0x1B4E, 0x1F40, 0x2378,
55 0x28D2, 0x2EFE, 0x34F8, 0x3A5C, 0x3FFF
80 WaitSema(completion_sema);
83 SifCallRpc(&cd0, func, 0, sbuff, 1*4, sbuff, 4, NULL, NULL);
86 SignalSema(completion_sema);
103 WaitSema(completion_sema);
107 SifCallRpc(&cd0, func, 0, sbuff, 2*4, sbuff, 4, NULL, NULL);
110 SignalSema(completion_sema);
128 WaitSema(completion_sema);
133 SifCallRpc(&cd0, func, 0, sbuff, 3*4, sbuff, 4, NULL, NULL);
136 SignalSema(completion_sema);
145 WaitSema(completion_sema);
147 SifCallRpc(&cd0, AUDSRV_QUIT, 0, sbuff, 1*4, sbuff, 4, NULL, NULL);
150 SifRemoveRpc(&cb_srv, &cb_queue);
151 SifRemoveRpcQueue(&cb_queue);
152 TerminateThread(rpc_server_thread_id);
153 DeleteThread(rpc_server_thread_id);
155 DeleteSema(completion_sema);
163 WaitSema(completion_sema);
165 sbuff[0] = fmt->
freq;
166 sbuff[1] = fmt->
bits;
168 SifCallRpc(&cd0, AUDSRV_SET_FORMAT, 0, sbuff, 3*4, sbuff, 4, NULL, NULL);
171 SignalSema(completion_sema);
194 return call_rpc_1(AUDSRV_SET_VOLUME, vol_values[volume/4]);
204 return call_rpc_2(AUDSRV_PLAY_SECTORS, start, end);
231 return call_rpc_1(AUDSRV_GET_TRACKOFFSET, track);
260 maxcopy =
sizeof(sbuff) -
sizeof(
int);
266 WaitSema(completion_sema);
268 copy = MIN(bytes, maxcopy);
270 memcpy(&sbuff[1], chunk, copy);
271 packet_size = copy +
sizeof(int);
272 SifCallRpc(&cd0, AUDSRV_PLAY_AUDIO, 0, sbuff, packet_size, sbuff, 1*4, NULL, NULL);
275 SignalSema(completion_sema);
284 chunk = chunk + copy;
285 bytes = bytes - copy;
286 sent = sent + copied;
299static void *audsrv_ee_rpc_handler(
int fnum,
void *buffer,
int len)
304 case AUDSRV_FILLBUF_CALLBACK:
305 if (on_fillbuf != NULL)
306 on_fillbuf(on_fillbuf_arg);
308 case AUDSRV_CDDA_CALLBACK:
309 if (on_cdda_stop != NULL)
310 on_cdda_stop(on_cdda_stop_arg);
317static void rpc_server_thread(
void *arg)
319 static unsigned char cb_rpc_buffer[64]
__attribute__((__aligned__(64)));
323 SifSetRpcQueue(&cb_queue, GetThreadId());
324 SifRegisterRpc(&cb_srv, AUDSRV_IRX, &audsrv_ee_rpc_handler, cb_rpc_buffer, NULL, NULL, &cb_queue);
325 SifRpcLoop(&cb_queue);
340 memset(&cd0,
'\0',
sizeof(cd0));
344 if (SifBindRpc(&cd0, AUDSRV_IRX, 0) < 0)
358 compSema.init_count = 1;
359 compSema.max_count = 1;
361 completion_sema = CreateSema(&compSema);
362 if (completion_sema < 0)
364 set_error(AUDSRV_ERR_FAILED_TO_CREATE_SEMA);
370 rpcThread.option = 0;
371 rpcThread.func = &rpc_server_thread;
372 rpcThread.stack = rpc_server_stack;
373 rpcThread.stack_size =
sizeof(rpc_server_stack);
374 rpcThread.gp_reg = &_gp;
375 rpcThread.initial_priority = 0x60;
376 rpc_server_thread_id = CreateThread(&rpcThread);
377 StartThread(rpc_server_thread_id, NULL);
379 SifCallRpc(&cd0,
AUDSRV_INIT, 0, sbuff, 64, sbuff, 64, NULL, NULL);
419 int volumel = volume;
420 int volumer = volume;
423 volumer = volumer * (100 + pan) / 100;
425 volumel = volumel * (100 - pan) / 100;
427 return call_rpc_3(AUDSRV_ADPCM_SET_VOLUME, ch, vol_values[volumel/4], vol_values[volumer/4]);
436 iop_addr = SifAllocIopHeap(size);
439 return -AUDSRV_ERR_OUT_OF_MEMORY;
443 sifdma.dest = iop_addr;
448 while((
id = SifSetDma(&sifdma, 1)) == 0);
449 while(SifDmaStat(
id) >= 0);
451 WaitSema(completion_sema);
453 sbuff[0] = (int)iop_addr;
455 sbuff[2] = (int)adpcm;
457 SifCallRpc(&cd0, AUDSRV_LOAD_ADPCM, 0, sbuff, 12, sbuff, 16, NULL, NULL);
466 adpcm->buffer = buffer;
468 adpcm->pitch = sbuff[1];
469 adpcm->loop = sbuff[2];
470 adpcm->channels = sbuff[3];
474 SignalSema(completion_sema);
476 SifFreeIopHeap(iop_addr);
484 return call_rpc_2(AUDSRV_PLAY_ADPCM, ch, (u32)adpcm);
489 return call_rpc_2(AUDSRV_IS_ADPCM_PLAYING, ch, (u32)adpcm);
495 return call_rpc_1(AUDSRV_FREE_ADPCM, (u32)adpcm);
505 case AUDSRV_ERR_NOT_INITIALIZED:
506 return "Not initialized";
508 case AUDSRV_ERR_OUT_OF_MEMORY:
509 return "Out of IOP memory";
511 case AUDSRV_ERR_RPC_FAILED:
512 return "RPC operation failed";
514 case AUDSRV_ERR_FORMAT_NOT_SUPPORTED:
515 return "Format not supported";
517 case AUDSRV_ERR_NO_DISC:
518 return "No disc in drive";
521 return "Unknown error";
527 on_cdda_stop_arg = arg;
538 err =
call_rpc_1(AUDSRV_SET_THRESHOLD, amount);
545 on_fillbuf_arg = arg;
int audsrv_play_sectors(int start, int end)
int audsrv_get_numtracks()
static int call_rpc_2(int func, int arg1, int arg2)
int audsrv_is_adpcm_playing(int ch, audsrv_adpcm_t *adpcm)
static int call_rpc_1(int func, int arg)
int audsrv_adpcm_set_volume_and_pan(int ch, int volume, int pan)
static int call_rpc_3(int func, int arg1, int arg2, int arg3)
int audsrv_play_audio(const char *chunk, int bytes)
int audsrv_on_cdda_stop(audsrv_callback_t cb, void *arg)
int audsrv_ch_play_adpcm(int ch, audsrv_adpcm_t *adpcm)
int audsrv_play_cd(int track)
int audsrv_get_trackpos()
int audsrv_load_adpcm(audsrv_adpcm_t *adpcm, void *buffer, int size)
const char * audsrv_get_error_string()
int audsrv_set_volume(int volume)
int audsrv_free_adpcm(audsrv_adpcm_t *adpcm)
int audsrv_on_fillbuf(int amount, audsrv_callback_t cb, void *arg)
int audsrv_wait_audio(int bytes)
static void set_error(int err)
int audsrv_get_track_offset(int track)
int audsrv_set_format(struct audsrv_fmt_t *fmt)
int audsrv_get_cd_status()
#define AUDSRV_INIT_ADPCM
#define AUDSRV_ERR_NOERROR