1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #define FORBIDDEN_SYMBOL_EXCEPTION_printf
24 
25 #include <malloc.h>
26 
27 #include "osystem.h"
28 
29 #define SFX_THREAD_STACKSIZE (1024 * 128)
30 #define SFX_THREAD_PRIO 80
31 #define SFX_THREAD_FRAG_SIZE (1024 * 8)
32 #define SFX_BUFFERS 3
33 
34 static lwpq_t sfx_queue;
35 static lwp_t sfx_thread;
36 static u8 *sfx_stack;
37 static bool sfx_thread_running = false;
38 static bool sfx_thread_quit = false;
39 
40 static u32 sb_hw;
41 static u8 *sound_buffer[SFX_BUFFERS];
42 
audio_switch_buffers()43 static void audio_switch_buffers() {
44 	sb_hw = (sb_hw + 1) % SFX_BUFFERS;
45 	AUDIO_InitDMA((u32) sound_buffer[sb_hw], SFX_THREAD_FRAG_SIZE);
46 	LWP_ThreadSignal(sfx_queue);
47 }
48 
sfx_thread_func(void * arg)49 static void * sfx_thread_func(void *arg) {
50 	Audio::MixerImpl *mixer = (Audio::MixerImpl *) arg;
51 	u8 sb_sw;
52 
53 	while (true) {
54 		LWP_ThreadSleep(sfx_queue);
55 
56 		if (sfx_thread_quit)
57 			break;
58 
59 		// the hardware uses two buffers: a front and a back buffer
60 		// we use 3 buffers here: two are beeing pushed to the DSP,
61 		// and the free one is where our mixer writes to
62 		// thus the latency of our stream is:
63 		// 8192 [frag size] / 48000 / 2 [16bit] / 2 [stereo] * 2 [hw buffers]
64 		// -> 85.3ms
65 		sb_sw = (sb_hw + 1) % SFX_BUFFERS;
66 		mixer->mixCallback(sound_buffer[sb_sw], SFX_THREAD_FRAG_SIZE);
67 		DCFlushRange(sound_buffer[sb_sw], SFX_THREAD_FRAG_SIZE);
68 	}
69 
70 	return NULL;
71 }
72 
initSfx()73 void OSystem_Wii::initSfx() {
74 	_mixer = new Audio::MixerImpl(48000);
75 
76 	sfx_thread_running = false;
77 	sfx_thread_quit = false;
78 
79 	sfx_stack = (u8 *) memalign(32, SFX_THREAD_STACKSIZE);
80 
81 	if (sfx_stack) {
82 		memset(sfx_stack, 0, SFX_THREAD_STACKSIZE);
83 
84 		LWP_InitQueue(&sfx_queue);
85 
86 		s32 res = LWP_CreateThread(&sfx_thread, sfx_thread_func, _mixer, sfx_stack,
87 									SFX_THREAD_STACKSIZE, SFX_THREAD_PRIO);
88 
89 		if (res) {
90 			printf("ERROR creating sfx thread: %d\n", res);
91 			LWP_CloseQueue(sfx_queue);
92 			return;
93 		}
94 
95 		sfx_thread_running = true;
96 	}
97 
98 	for (u32 i = 0; i < SFX_BUFFERS; ++i) {
99 		sound_buffer[i] = (u8 *) memalign(32, SFX_THREAD_FRAG_SIZE);
100 		memset(sound_buffer[i], 0, SFX_THREAD_FRAG_SIZE);
101 		DCFlushRange(sound_buffer[i], SFX_THREAD_FRAG_SIZE);
102 	}
103 
104 	_mixer->setReady(true);
105 
106 	sb_hw = 0;
107 
108 	AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
109 	AUDIO_RegisterDMACallback(audio_switch_buffers);
110 	AUDIO_InitDMA((u32) sound_buffer[sb_hw], SFX_THREAD_FRAG_SIZE);
111 	AUDIO_StartDMA();
112 }
113 
deinitSfx()114 void OSystem_Wii::deinitSfx() {
115 	if (_mixer)
116 		_mixer->setReady(false);
117 
118 	AUDIO_StopDMA();
119 	AUDIO_RegisterDMACallback(NULL);
120 
121 	if (sfx_thread_running) {
122 		sfx_thread_quit = true;
123 		LWP_ThreadBroadcast(sfx_queue);
124 
125 		LWP_JoinThread(sfx_thread, NULL);
126 		LWP_CloseQueue(sfx_queue);
127 
128 		free(sfx_stack);
129 		sfx_thread_running = false;
130 
131 		for (u32 i = 0; i < SFX_BUFFERS; ++i)
132 			free(sound_buffer[i]);
133 	}
134 }
135