aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-10-21 10:54:03 +0200
committerBad Diode <bd@badd10de.dev>2022-10-21 10:54:03 +0200
commit357d401d00e560e8834f79e271ccad047f85a4da (patch)
treeaae5e28c9d10333bc173d4281c02376b324357f3
parent98b84781ebe0ceafe434dbeb90dc790c00ce6cb0 (diff)
downloaduxn64-357d401d00e560e8834f79e271ccad047f85a4da.tar.gz
uxn64-357d401d00e560e8834f79e271ccad047f85a4da.zip
Move audio playing to separate thread
-rw-r--r--src/linker.ld4
-rw-r--r--src/main.c62
2 files changed, 40 insertions, 26 deletions
diff --git a/src/linker.ld b/src/linker.ld
index 91bd28a..20f3986 100644
--- a/src/linker.ld
+++ b/src/linker.ld
@@ -41,6 +41,10 @@ SECTIONS {
41 41
42 . += STACK_SIZE; 42 . += STACK_SIZE;
43 . = ALIGN(8); 43 . = ALIGN(8);
44 _audio_thread_stack = .;
45
46 . += STACK_SIZE;
47 . = ALIGN(8);
44 _idle_thread_stack = .; 48 _idle_thread_stack = .;
45 } >ram 49 } >ram
46 50
diff --git a/src/main.c b/src/main.c
index b3187ac..b84ace6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,8 +8,10 @@
8 8
9static OSThread idle_thread; 9static OSThread idle_thread;
10static OSThread main_thread; 10static OSThread main_thread;
11static OSThread audio_thread;
11extern u8 _idle_thread_stack[]; 12extern u8 _idle_thread_stack[];
12extern u8 _main_thread_stack[]; 13extern u8 _main_thread_stack[];
14extern u8 _audio_thread_stack[];
13 15
14// 16//
15// Message buffers, queues and devices. 17// Message buffers, queues and devices.
@@ -41,15 +43,11 @@ OSPiHandle *rom_handle;
41 43
42#define N_AUDIO_BUF 3 44#define N_AUDIO_BUF 3
43#define AUDIO_RATE 44100 45#define AUDIO_RATE 44100
44#define MAX_AUDIO_LENGTH KB(4) 46#define MAX_AUDIO_LENGTH KB(1)
45#define AUDIO_BUF_SIZE (MAX_AUDIO_LENGTH * sizeof(s32)) 47#define AUDIO_BUF_SIZE (MAX_AUDIO_LENGTH * sizeof(s32))
46static s16 audio_samples[N_AUDIO_BUF] = {0, 0, 0};
47static s16 audio_buffers[N_AUDIO_BUF][AUDIO_BUF_SIZE] __attribute__((aligned(64))); 48static s16 audio_buffers[N_AUDIO_BUF][AUDIO_BUF_SIZE] __attribute__((aligned(64)));
48static s32 active_audio = 0; 49static s32 active_audio = 0;
49static s32 frame_size = 0; 50static s32 pause_audio = 0;
50static s32 min_frame_size = 0;
51static s32 samples_left = 0;
52static int pause_audio = 0;
53 51
54#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) 52#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X))
55 53
@@ -407,33 +405,25 @@ init_uxn(Uxn *u) {
407 405
408void 406void
409init_audio(void) { 407init_audio(void) {
410 s32 audio_rate = osAiSetFrequency(AUDIO_RATE); 408 osAiSetFrequency(AUDIO_RATE);
411 osWritebackDCache(audio_buffers, sizeof(audio_buffers)); 409 osWritebackDCache(audio_buffers, sizeof(audio_buffers));
412} 410}
413 411
414void 412void
415handle_audio(void) { 413handle_audio(void) {
416 if (pause_audio) {
417 return;
418 }
419
420 u32 status = osAiGetStatus();
421 if (status & AI_STATUS_FIFO_FULL > 0) {
422 return;
423 }
424
425 int running = 0; 414 int running = 0;
426 s16 *samples = &audio_buffers[active_audio]; 415 s16 *samples = (s16*)&audio_buffers[active_audio];
427 for (size_t i = 0; i < AUDIO_BUF_SIZE; i++) { 416 for (size_t i = 0; i < AUDIO_BUF_SIZE; i++) {
428 samples[i] = 0; 417 samples[i] = 0;
429 } 418 }
430 for(int channel = 0; channel < POLYPHONY; channel++) { 419 if (!pause_audio) {
431 running += audio_render(channel, samples, samples + AUDIO_BUF_SIZE / 2); 420 for(int channel = 0; channel < POLYPHONY; channel++) {
432 } 421 running += audio_render(channel, samples, samples + AUDIO_BUF_SIZE / 2);
433 if(!running) { 422 }
434 pause_audio = 1; 423 if(!running) {
424 pause_audio = 1;
425 }
435 } 426 }
436
437 osAiSetNextBuffer(audio_buffers[active_audio], AUDIO_BUF_SIZE); 427 osAiSetNextBuffer(audio_buffers[active_audio], AUDIO_BUF_SIZE);
438 active_audio++; 428 active_audio++;
439 if (active_audio == N_AUDIO_BUF) { 429 if (active_audio == N_AUDIO_BUF) {
@@ -445,20 +435,36 @@ static void
445main_proc(void *arg) { 435main_proc(void *arg) {
446 (void)arg; 436 (void)arg;
447 init_ppu(); 437 init_ppu();
448 init_audio();
449 init_ctrl(); 438 init_ctrl();
450 init_uxn(&u); 439 init_uxn(&u);
451 440
452 // Main loop. 441 // Main loop.
453 while (true) { 442 while (true) {
454 poll_input(); 443 poll_input();
455 handle_audio();
456 uxn_eval(&u, GETVECTOR(devscreen)); 444 uxn_eval(&u, GETVECTOR(devscreen));
457 blit_framebuffer(); 445 blit_framebuffer();
458 swap_buffers(); 446 swap_buffers();
459 } 447 }
460} 448}
461 449
450static OSMesg audio_msg_buf;
451static OSMesgQueue audio_msg_queue;
452
453static void
454audio_proc(void *arg) {
455 (void)arg;
456 osCreateMesgQueue(&audio_msg_queue, &audio_msg_buf, 1);
457 osSetEventMesg(OS_EVENT_AI, &audio_msg_queue, &audio_msg_buf);
458 init_audio();
459 while (true) {
460 handle_audio();
461 u32 status = osAiGetStatus();
462 if ((status & AI_STATUS_FIFO_FULL) > 0) {
463 osRecvMesg(&audio_msg_queue, NULL, OS_MESG_BLOCK);
464 }
465 }
466}
467
462void 468void
463audio_finished_handler(int instance) { 469audio_finished_handler(int instance) {
464 (void)instance; 470 (void)instance;
@@ -475,9 +481,13 @@ idle_proc(void *arg) {
475 osCreatePiManager((OSPri)OS_PRIORITY_PIMGR, &pi_msg_queue, pi_msg, NUM_PI_MSGS); 481 osCreatePiManager((OSPri)OS_PRIORITY_PIMGR, &pi_msg_queue, pi_msg, NUM_PI_MSGS);
476 482
477 // Create main thread. 483 // Create main thread.
478 osCreateThread(&main_thread, 3, main_proc, NULL, _main_thread_stack, 10); 484 osCreateThread(&main_thread, 2, main_proc, NULL, _main_thread_stack, 10);
479 osStartThread(&main_thread); 485 osStartThread(&main_thread);
480 486
487 // Create audio thread.
488 osCreateThread(&audio_thread, 3, audio_proc, NULL, _audio_thread_stack, 10);
489 osStartThread(&audio_thread);
490
481 // Become the idle thread. 491 // Become the idle thread.
482 osSetThreadPri(0, 0); 492 osSetThreadPri(0, 0);
483 for (;;); 493 for (;;);