diff options
author | Bad Diode <bd@badd10de.dev> | 2022-10-21 10:54:03 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-10-21 10:54:03 +0200 |
commit | 357d401d00e560e8834f79e271ccad047f85a4da (patch) | |
tree | aae5e28c9d10333bc173d4281c02376b324357f3 | |
parent | 98b84781ebe0ceafe434dbeb90dc790c00ce6cb0 (diff) | |
download | uxn64-357d401d00e560e8834f79e271ccad047f85a4da.tar.gz uxn64-357d401d00e560e8834f79e271ccad047f85a4da.zip |
Move audio playing to separate thread
-rw-r--r-- | src/linker.ld | 4 | ||||
-rw-r--r-- | src/main.c | 62 |
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 | ||
@@ -8,8 +8,10 @@ | |||
8 | 8 | ||
9 | static OSThread idle_thread; | 9 | static OSThread idle_thread; |
10 | static OSThread main_thread; | 10 | static OSThread main_thread; |
11 | static OSThread audio_thread; | ||
11 | extern u8 _idle_thread_stack[]; | 12 | extern u8 _idle_thread_stack[]; |
12 | extern u8 _main_thread_stack[]; | 13 | extern u8 _main_thread_stack[]; |
14 | extern 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)) |
46 | static s16 audio_samples[N_AUDIO_BUF] = {0, 0, 0}; | ||
47 | static s16 audio_buffers[N_AUDIO_BUF][AUDIO_BUF_SIZE] __attribute__((aligned(64))); | 48 | static s16 audio_buffers[N_AUDIO_BUF][AUDIO_BUF_SIZE] __attribute__((aligned(64))); |
48 | static s32 active_audio = 0; | 49 | static s32 active_audio = 0; |
49 | static s32 frame_size = 0; | 50 | static s32 pause_audio = 0; |
50 | static s32 min_frame_size = 0; | ||
51 | static s32 samples_left = 0; | ||
52 | static 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 | ||
408 | void | 406 | void |
409 | init_audio(void) { | 407 | init_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 | ||
414 | void | 412 | void |
415 | handle_audio(void) { | 413 | handle_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 | |||
445 | main_proc(void *arg) { | 435 | main_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 | ||
450 | static OSMesg audio_msg_buf; | ||
451 | static OSMesgQueue audio_msg_queue; | ||
452 | |||
453 | static void | ||
454 | audio_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 | |||
462 | void | 468 | void |
463 | audio_finished_handler(int instance) { | 469 | audio_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 (;;); |