1 /*---------------------------------------------------------------------------*
2   Project:  THP Player
3   File:     THPAudioDecode.c
4 
5   Copyright (C)2002-2006 Nintendo  All Rights Reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: THPAudioDecode.c,v $
14   Revision 1.1  02/03/2006 10:01:27  aka
15   Imported from Dolphin tree.
16 
17 
18     3     03/11/25 11:24 Dante
19     Japanese to English translation of comments and text strings
20 
21     2     03/09/16 15:42:00 Suzuki
22     changed DECODE_BUFFER_NUM to DECODE_AUDIO_BUFFER_NUM.
23 
24     1     02/05/14 11:28a Suzuki
25     Initial check-in.
26 
27   $NoKeywords: $
28 
29  *---------------------------------------------------------------------------*/
30 
31 #include <revolution.h>
32 
33 #include "THPPlayerStrmAX.h"
34 #include "THPAudioDecode.h"
35 #include "THPRead.h"
36 
37 /*---------------------------------------------------------------------------*
38    External Function
39  *---------------------------------------------------------------------------*/
40 
41 extern void PrepareReady(BOOL flag);
42 
43 /*---------------------------------------------------------------------------*
44    Static Function
45  *---------------------------------------------------------------------------*/
46 
47 static void *AudioDecoder(void *ptr);
48 static void *AudioDecoderForOnMemory(void *ptr);
49 static void AudioDecode(THPReadBuffer *readBuffer);
50 
51 /*---------------------------------------------------------------------------*
52    Global Variable
53  *---------------------------------------------------------------------------*/
54 
55 extern THPPlayer ActivePlayer;
56 
57 /*---------------------------------------------------------------------------*
58    Static Variable
59  *---------------------------------------------------------------------------*/
60 
61 static s32            AudioDecodeThreadCreated = 0;
62 static OSThread       AudioDecodeThread;
63 static u8             AudioDecodeThreadStack[4*1024];
64 static OSMessageQueue FreeAudioBufferQueue;
65 static OSMessageQueue DecodedAudioBufferQueue;
66 static OSMessage      FreeAudioBufferMessage[DECODE_AUDIO_BUFFER_NUM];
67 static OSMessage      DecodedAudioBufferMessage[DECODE_AUDIO_BUFFER_NUM];
68 
69 /*---------------------------------------------------------------------------*
70     Name:           CreateAudioDecodeThread
71 
72     Description:    Creation of audio decode thread
73 
74     Arguments:      priority   thread priority
75                     ptr        Pointer to memory where the start data of movie
76                                is with OnMemory playback.
77 
78     Return Values:  If creation of thread succeeds, returns TRUE. If creation fails, returns FALSE.
79  *---------------------------------------------------------------------------*/
80 
CreateAudioDecodeThread(OSPriority priority,u8 * ptr)81 BOOL CreateAudioDecodeThread(OSPriority priority, u8 *ptr)
82 {
83     if (ptr)
84     {
85         if (OSCreateThread(&AudioDecodeThread,
86                            AudioDecoderForOnMemory,
87                            ptr,
88                            AudioDecodeThreadStack + sizeof(AudioDecodeThreadStack),
89                            sizeof(AudioDecodeThreadStack),
90                            priority,
91                            OS_THREAD_ATTR_DETACH) == FALSE)
92         {
93 #ifdef _DEBUG
94             OSReport("Can't create audio decode thread\n");
95 #endif
96             return FALSE;
97         }
98     }
99     else
100     {
101         if (OSCreateThread(&AudioDecodeThread,
102                            AudioDecoder,
103                            NULL,
104                            AudioDecodeThreadStack + sizeof(AudioDecodeThreadStack),
105                            sizeof(AudioDecodeThreadStack),
106                            priority,
107                            OS_THREAD_ATTR_DETACH) == FALSE)
108         {
109 #ifdef _DEBUG
110             OSReport("Can't create audio decode thread\n");
111 #endif
112             return FALSE;
113         }
114     }
115 
116     OSInitMessageQueue(&FreeAudioBufferQueue,
117                        FreeAudioBufferMessage,
118                        DECODE_AUDIO_BUFFER_NUM);
119 
120     OSInitMessageQueue(&DecodedAudioBufferQueue,
121                        DecodedAudioBufferMessage,
122                        DECODE_AUDIO_BUFFER_NUM);
123 
124     AudioDecodeThreadCreated = 1;
125 
126     return TRUE;
127 }
128 
129 /*---------------------------------------------------------------------------*
130     Name:           AudioDecodeThreadStart
131 
132     Description:    Start of audio decode thread.
133 
134     Arguments:      None
135 
136     Return Values:  None
137  *---------------------------------------------------------------------------*/
138 
AudioDecodeThreadStart(void)139 void AudioDecodeThreadStart(void)
140 {
141     if (AudioDecodeThreadCreated)
142     {
143         OSResumeThread(&AudioDecodeThread);
144     }
145 
146     return;
147 }
148 
149 /*---------------------------------------------------------------------------*
150     Name:           AudioDecodeThreadCancel
151 
152     Description:    Cancel audio decode thread
153 
154     Arguments:      None
155 
156     Returns:        None
157  *---------------------------------------------------------------------------*/
158 
AudioDecodeThreadCancel(void)159 void AudioDecodeThreadCancel(void)
160 {
161     if (AudioDecodeThreadCreated)
162     {
163         OSCancelThread(&AudioDecodeThread);
164 
165         AudioDecodeThreadCreated = 0;
166     }
167 
168     return;
169 }
170 
171 /*---------------------------------------------------------------------------*
172     Name:           AudioDecoder
173 
174     Description:    Audio decoder for streaming playback
175 
176     Arguments:      None
177 
178     Returns:        None
179  *---------------------------------------------------------------------------*/
180 
AudioDecoder(void * ptr)181 static void *AudioDecoder(void *ptr)
182 {
183     #pragma unused(ptr)
184     THPReadBuffer *readBuffer;
185     s32           frameNumber, count;
186 
187     count = 0;
188 
189     while(1)
190     {
191         readBuffer = PopReadedBuffer();
192 
193         AudioDecode(readBuffer);
194 
195         if (count < 2)
196         {
197             if (!(ActivePlayer.playFlag & THP_PLAY_LOOP))
198             {
199                 frameNumber = (s32)(readBuffer->frameNumber + ActivePlayer.initReadFrame);
200 
201                 if (frameNumber == ActivePlayer.header.numFrames - 1)
202                 {
203                     PrepareReady(TRUE);
204                 }
205             }
206         }
207 
208         if (count == 2)
209         {
210             PrepareReady(TRUE);
211         }
212 
213         PushReadedBuffer2(readBuffer);
214 
215         count++;
216     }
217 
218     return NULL;
219 }
220 
221 /*---------------------------------------------------------------------------*
222     Name:           AudioDecoderForOnMemory
223 
224     Description:    Audio decoder for OnMemory playback.
225 
226     Arguments:      None
227 
228     Returns:        None
229  *---------------------------------------------------------------------------*/
230 
AudioDecoderForOnMemory(void * ptr)231 static void *AudioDecoderForOnMemory(void *ptr)
232 {
233     THPReadBuffer readBuffer;
234     s32           tmp, size, readFrame, frameNumber;
235 
236     size           = ActivePlayer.initReadSize;
237     readBuffer.ptr = (u8 *)ptr;
238     readFrame      = 0;
239 
240     while(1)
241     {
242         readBuffer.frameNumber = readFrame;
243 
244         AudioDecode(&readBuffer);
245 
246         frameNumber = (s32)((readFrame + ActivePlayer.initReadFrame)
247                     % ActivePlayer.header.numFrames);
248 
249         // Check end of THP movie data
250         if (frameNumber == ActivePlayer.header.numFrames - 1)
251         {
252             // If loop playback, at beginning of movie data
253             if (ActivePlayer.playFlag & THP_PLAY_LOOP)
254             {
255                 size           = *(s32 *)(readBuffer.ptr);
256                 readBuffer.ptr = ActivePlayer.movieData;
257             }
258             // Stop decode if one-shot playback
259             else
260             {
261                 if (readFrame < 2)
262                 {
263                     PrepareReady(TRUE);
264                 }
265                 OSSuspendThread(&AudioDecodeThread);
266             }
267         }
268         // Move next frame pointer if not end
269         else
270         {
271             tmp             = *(s32 *)(readBuffer.ptr);
272             readBuffer.ptr += size;
273             size            = tmp;
274         }
275 
276         if (readFrame == 2)
277         {
278             PrepareReady(TRUE);
279         }
280 
281         readFrame++;
282     }
283 
284     return NULL;
285 }
286 
287 /*---------------------------------------------------------------------------*
288     Name:           AudioDecode
289 
290     Description:    Decoding of THP audio data.
291 
292     Arguments:      readBuffer Pointer to buffer where THP frame stored.
293 
294     Returns:        None
295  *---------------------------------------------------------------------------*/
296 
AudioDecode(THPReadBuffer * readBuffer)297 static void AudioDecode(THPReadBuffer *readBuffer)
298 {
299     THPAudioBuffer *audioBuffer;
300     u32            i, sample;
301     u32            *compSizePtr;
302     u8             *ptr;
303 
304     compSizePtr = (u32 *)(readBuffer->ptr + 8);
305     ptr         = readBuffer->ptr + ActivePlayer.compInfo.numComponents * 4 + 8;
306 
307     audioBuffer  = PopFreeAudioBuffer();
308 
309     for (i = 0 ; i < ActivePlayer.compInfo.numComponents ; i++)
310     {
311         switch (ActivePlayer.compInfo.frameComp[i])
312         {
313             case THP_AUDIO_COMP:
314                 sample = THPAudioDecode(audioBuffer->buffer,
315                                         ptr + (*compSizePtr) * ActivePlayer.curAudioTrack,
316                                         THP_AUDIO_INTERLEAVE);
317                 audioBuffer->validSample = sample;
318                 audioBuffer->curPtr      = audioBuffer->buffer;
319                 PushDecodedAudioBuffer(audioBuffer);
320                 return;
321             default:
322                 ptr += *compSizePtr;
323                 compSizePtr++;
324         }
325     }
326 
327     return;
328 }
329 
330 /*---------------------------------------------------------------------------*
331     Name:           PopFreeAudioBuffer
332 
333     Description:    Acquire audio buffers not used.
334 
335     Arguments:      None
336 
337     Returns:        Pointer for audio buffers not used.
338  *---------------------------------------------------------------------------*/
339 
PopFreeAudioBuffer()340 void *PopFreeAudioBuffer()
341 {
342     OSMessage msg;
343 
344     OSReceiveMessage(&FreeAudioBufferQueue, &msg, OS_MESSAGE_BLOCK);
345 
346     return msg;
347 }
348 
349 /*---------------------------------------------------------------------------*
350     Name:           PushFreeAudioBuffer
351 
352     Description:    Free THP audio data finished playing back.
353 
354     Arguments:      buffer  Pointer for THP audio data finished playing back.
355 
356     Returns:        None
357  *---------------------------------------------------------------------------*/
358 
PushFreeAudioBuffer(void * buffer)359 void PushFreeAudioBuffer(void *buffer)
360 {
361     OSSendMessage(&FreeAudioBufferQueue, buffer, OS_MESSAGE_NOBLOCK);
362 
363     return;
364 }
365 
366 /*---------------------------------------------------------------------------*
367     Name:           PopDecodedAudioBuffer
368 
369     Description:    Acquire decoded THP audio data.
370 
371     Arguments:      Block until can get decoded THP audio data
372                     if flag OS_MESSAGE_BLOCK.  Do not block if
373                     OS_MESSAGE_NOBLOCK.
374 
375     Returns:        If successful, return audio buffer pointer.
376                     If unsuccessful, NULL is returned.
377  *---------------------------------------------------------------------------*/
378 
PopDecodedAudioBuffer(s32 flag)379 void *PopDecodedAudioBuffer(s32 flag)
380 {
381     OSMessage msg;
382 
383     if (OSReceiveMessage(&DecodedAudioBufferQueue, &msg, flag) == TRUE)
384     {
385         return msg;
386     }
387     else
388     {
389         return NULL;
390     }
391 }
392 
393 /*---------------------------------------------------------------------------*
394     Name:           PushDecodedAudioBuffer
395 
396     Description:    Push THP audio that has finished decoding into queue
397 
398     Arguments:      buffer  Pointer for decoded THP audio data.
399 
400     Returns:        None
401  *---------------------------------------------------------------------------*/
402 
PushDecodedAudioBuffer(void * buffer)403 void PushDecodedAudioBuffer(void *buffer)
404 {
405     OSSendMessage(&DecodedAudioBufferQueue, buffer, OS_MESSAGE_BLOCK);
406 
407     return;
408 }
409 
410 
411 
412