nuaumgrex.c
8.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*======================================================================*/
/* NuSYS */
/* nuaumgr.c */
/* */
/* Copyright (C) 1997, NINTENDO Co,Ltd. */
/* */
/* --/--/-- Created by K.Ohki(SLANP) */
/* 98/11/26 Modified by K.Ohki(SLANP) */
/*======================================================================*/
/* $Id: nuaumgrex.c,v 1.1.1.1 2002/10/30 02:07:09 blythe Exp $ */
/*======================================================================*/
#include <nusys.h>
#include <nualsgi.h>
static s16* auBuffer_ptr[2]; /* オーディオバッファ */
static void nuAuMgr(void* arg);
/*----------------------------------------------------------------------*/
/* nuAuMgrInitEx -オーディオマネージャの初期化 */
/* */
/* AI_FIFO_EVENTを使うオーディオマネージャの初期化 */
/* IN: ヒープバッファの先頭ポインタ */
/* RET: 使用ヒープサイズ */
/*----------------------------------------------------------------------*/
s32 nuAuMgrInitEx(void* heap_ptr, u32 size, ALSynConfig* synConfig)
{
s32 frameRate;
nuAuTaskStop = NU_AU_TASK_RUN; /* タスク実行可 */
frameRate = nuScGetFrameRate(); /* フレームレートの取得 */
/* 1フレームに必要なサンプル数の計算。小数点以下切り上げ */
nuAuFrameSampleSize = (nusched.retraceCount * synConfig->outputRate + frameRate - 1)/frameRate;
nuAuFrameSampleSize += nuAuExtraSampleSize;
nuAuFrameSampleSize = ((nuAuFrameSampleSize + (NU_AU_AUDIO_SAMPLES -1)) / NU_AU_AUDIO_SAMPLES) * NU_AU_AUDIO_SAMPLES;
/* オーディオヒープの初期化 */
nuAuHeapInit(&nuAuHeap, heap_ptr, size);
/* コマンドリストバッファの確保 */
nuAuCmdListBuf = nuAuHeapAlloc(nuAuAcmdLen * sizeof(Acmd));
/* オーディオバッファの確保 */
auBuffer_ptr[0] = nuAuHeapAlloc(nuAuFrameSampleSize * sizeof(s32));
auBuffer_ptr[1] = nuAuHeapAlloc(nuAuFrameSampleSize * sizeof(s32));
/* オーディオマネージャのスタック領域の確保 */
nuAuMgrStack = nuAuHeapAlloc(NU_AU_STACK_SIZE);
/* シンセサイズドライバの初期化 */
synConfig->dmaproc = nuAuDmaNew;
synConfig->heap = &nuAuHeap;
synConfig->outputRate = osAiSetFrequency(synConfig->outputRate);
alInit(&nuAuGlobal, synConfig);
/* タスク構造体の初期化 */
nuAuTask.msg = 0;/* reply with this message */
nuAuTask.list.t.type = M_AUDTASK;
nuAuTask.list.t.ucode_boot = (u64*)rspbootTextStart;
nuAuTask.list.t.ucode_boot_size =
((int) rspbootTextEnd - (int) rspbootTextStart);
#ifdef N_AUDIO
nuAuTask.list.t.ucode = (u64*) n_aspMainTextStart;
nuAuTask.list.t.ucode_data = (u64 *) n_aspMainDataStart;
#else
nuAuTask.list.t.ucode = (u64*) aspMainTextStart;
nuAuTask.list.t.ucode_data = (u64 *) aspMainDataStart;
#endif /* N_AUDIO */
nuAuTask.list.t.ucode_data_size = SP_UCODE_DATA_SIZE;
nuAuTask.list.t.dram_stack = (u64 *) NULL;
nuAuTask.list.t.dram_stack_size = 0;
nuAuTask.list.t.output_buff = (u64 *) NULL;
nuAuTask.list.t.output_buff_size = 0;
nuAuTask.list.t.yield_data_ptr = NULL;
nuAuTask.list.t.yield_data_size = 0;
nuAuSeqPlayer[0].mode = 0;
nuAuSeqPlayer[1].mode = 0;
nuAuSeqPlayer[0].data_ptr = NULL;
nuAuSeqPlayer[1].data_ptr = NULL;
/* オーディオマネージャの起動 */
osCreateThread(&nuAuMgrThread, NU_AU_MGR_THREAD_ID, nuAuMgr, (void*)NULL,
(nuAuMgrStack + NU_AU_STACK_SIZE/sizeof(u64)),
NU_AU_MGR_THREAD_PRI);
osStartThread(&nuAuMgrThread);
/* 使用しているヒープサイズを返す */
return nuAuHeapGetUsed();
}
/*----------------------------------------------------------------------*/
/* nuAuMgr - オーディオマネージャ */
/* IN: 無し */
/* RET: 無し */
/*----------------------------------------------------------------------*/
static void nuAuMgr(void* arg)
{
OSMesgQueue nuAuRtnMesgQ;
OSMesg nuAuRtnMesgBuf;
OSMesg nuAuMsgBuf[NU_AU_MESG_MAX];
NUScMsg* mesg_type;
NUScMsg aiEventMsg;
Acmd* cmdListAfter_ptr;
s32 cmdList_len;
u32 bufCnt;
u32 bufPtr;
s32 readCnt;
osCreateMesgQueue(&nuAuMesgQ, nuAuMsgBuf, NU_AU_MESG_MAX);
/* オーディオタスクスレッドからのメッセージ待ちキュー */
osCreateMesgQueue(&nuAuRtnMesgQ, &nuAuRtnMesgBuf, 1);
/* AIイベントメッセージの設定 */
aiEventMsg = NU_AU_AI_FIFO_MSG;
osSetEventMesg(OS_EVENT_AI, &nuAuMesgQ, (OSMesg*)&aiEventMsg);
/* スケジューラにRETRACEクライアント登録 */
nuScAddClient(&nuAuClient, &nuAuMesgQ, NU_SC_RETRACE_MSG | NU_SC_PRENMI_MSG);
cmdList_len = 0;
bufCnt = 0;
readCnt = 0;
bufPtr = 0;
while(1){
(void)osRecvMesg(&nuAuMesgQ, (OSMesg*)&mesg_type, OS_MESG_BLOCK);
#ifdef NU_DEBUG
if((nuAuDebFlag & NU_AU_DEBUG_FIFOOFF)
&& (*mesg_type == NU_AU_AI_FIFO_MSG)){
continue;
}
if((nuAuDebFlag & NU_AU_DEBUG_RETRACEOFF)
&&(*mesg_type == NU_SC_RETRACE_MSG)){
continue;
}
#endif /* NU_DEBUG */
switch(*mesg_type){
/* AIのFIFO(DMAの設定をするレジスタ)が1->0になったとき */
/* AIイベントが発生する。その時,未転送の合成波形データが */
/* ある場合FIFOにDMAの設定をおこなう */
/* この機構により,ノイズが発生することはなくなる */
/* しかし、最初はFIFOは空なのでAIイベントは発生しない。 */
/* そこでAIイベントが発生するまでリトレースメッセージで */
/* RSPコマンド作成,マクロコードの起動,FIFOの設定をおこなう */
/* AIイベントが発生すれば,後はリトレースメッセージは不要 */
/* なので、メッセージ登録をなくす */
/* もしなんらかの理由でAIイベント時にバッファを設定 */
/* 出来なかったら、もう一度リトレースメッセージが来るように */
/* 設定しなおす。 */
case NU_SC_RETRACE_MSG:
if((bufCnt > 1) && !nuAuPreNMI){
nuScResetClientMesgType(&nuAuClient, nuAuClient.msgType ^ NU_SC_RETRACE_MSG);
}
case NU_AU_AI_FIFO_MSG:
#ifdef NU_DEBUG
case NU_AU_AI_DEBUG_MSG:
#endif /* NU_DEBUG */
/* 未転送のデータがバッファにある場合,DMAのFIFOレジスタを */
/* チェックし,OKであれば転送設定する */
if(bufCnt > 0){
u32 status;
status = osAiGetStatus();
/* バッファの切り替え。これによりAIにデータが送られて音が鳴る*/
if(!(status & AI_STATUS_FIFO_FULL)){
#ifdef NU_DEBUG
if(!(nuAuDebFlag & NU_AU_DEBUG_DISABLEAI)){
#endif /* NU_DEBUG */
osAiSetNextBuffer(auBuffer_ptr[readCnt], nuAuFrameSampleSize<<2);
#ifdef NU_DEBUG
}
#endif /* NU_DEBUG */
readCnt ^= 1;
bufCnt--;
}
} else if(!(nuAuClient.msgType & NU_SC_RETRACE_MSG)){
/* FIFOが空になりAIイベントが発生しなくなるので */
/* リトレースメッセージを送るように再登録する */
nuScResetClientMesgType(&nuAuClient, nuAuClient.msgType | NU_SC_RETRACE_MSG);
}
/* タスク起動。コマンドリストが無い場合はタスクを起動しない */
if((cmdList_len > 0) && (bufCnt < 2) && (nuAuTaskStop)){
#ifdef NU_DEBUG
if(!(nuAuDebFlag & NU_AU_DEBUG_DISABLETASK)){
#endif /* NU_DEBUG */
nuAuTask.list.t.data_ptr = (u64 *)nuAuCmdListBuf;
nuAuTask.list.t.data_size =
(cmdListAfter_ptr - nuAuCmdListBuf) * sizeof(Acmd);
nuAuTask.msgQ = &nuAuRtnMesgQ;
osSendMesg(&nusched.audioRequestMQ,
(OSMesg*)&nuAuTask, OS_MESG_BLOCK);
osRecvMesg(&nuAuRtnMesgQ, NULL, OS_MESG_BLOCK);
#ifdef NU_DEBUG
}
#endif /* NU_DEBUG */
bufPtr ^=1;
bufCnt++;
cmdList_len = 0;
}
if(cmdList_len == 0){
/* オーディオコマンドリストの作成 */
cmdListAfter_ptr = alAudioFrame(nuAuCmdListBuf, &cmdList_len,
(s16*)osVirtualToPhysical(auBuffer_ptr[bufPtr]),
nuAuFrameSampleSize);
/* DMAバッファのクリア。2フレーム未使用のバッファは */
/* クリアする。 */
nuAuCleanDMABuffers();
/* シーケンスのコントロール */
if(nuAuMgrFunc){
(*nuAuMgrFunc)();
}
#ifdef NU_DEBUG
/* オーディオコマンドリストのサイズの最大値の更新 */
if(cmdList_len > nuAuDebAcmdLenMax){
nuAuDebAcmdLenMax = cmdList_len;
}
if(cmdList_len >= nuAuAcmdLen){
if(nuAuDebFlag & NU_AU_DEBUG_NORMAL){
osSyncPrintf("nuAuMgr: cmdlist_len %d is too big.\n",
cmdList_len);
}
nuAuDebStatus |= NU_AU_DEBUG_ACMDBUFOVER;
}
#endif /* NU_DEBUG */
}
/* PRE NMIメッセージが来たら,その後この関数が呼ばれつづける */
if((nuAuPreNMI) && (*mesg_type & NU_SC_RETRACE_MSG)){
if((u32)nuAuPreNMIFunc){
(*nuAuPreNMIFunc)(NU_SC_RETRACE_MSG, nuAuPreNMI);
}
nuAuPreNMI++;
}
break;
case NU_SC_PRENMI_MSG:
/* PRE NMIメッセージがきたら関数を呼ぶ */
if(nuAuPreNMIFunc){
/* リトレースメッセージを送るように再登録する */
nuScResetClientMesgType(&nuAuClient, nuAuClient.msgType | NU_SC_RETRACE_MSG);
(*nuAuPreNMIFunc)(NU_SC_PRENMI_MSG, nuAuPreNMI);
}
nuAuPreNMI++;
break;
default:
#ifdef NU_DEBUG
if(nuAuDebFlag & NU_AU_DEBUG_NORMAL){
osSyncPrintf("nuAuMgr: Unknown message %d received \n", *mesg_type);
}
#endif /* NU_DEBUG */
break;
}
}
}