/*---------------------------------------------------------------------------* Project: THP Player File: THPAudioDecode.c Copyright (C)2002-2006 Nintendo All Rights Reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: THPAudioDecode.c,v $ Revision 1.1 02/03/2006 10:01:27 aka Imported from Dolphin tree. 3 03/11/25 11:24 Dante Japanese to English translation of comments and text strings 2 03/09/16 15:42:00 Suzuki changed DECODE_BUFFER_NUM to DECODE_AUDIO_BUFFER_NUM. 1 02/05/14 11:28a Suzuki Initial check-in. $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include "THPPlayerStrmAX.h" #include "THPAudioDecode.h" #include "THPRead.h" /*---------------------------------------------------------------------------* External Function *---------------------------------------------------------------------------*/ extern void PrepareReady(BOOL flag); /*---------------------------------------------------------------------------* Static Function *---------------------------------------------------------------------------*/ static void *AudioDecoder(void *ptr); static void *AudioDecoderForOnMemory(void *ptr); static void AudioDecode(THPReadBuffer *readBuffer); /*---------------------------------------------------------------------------* Global Variable *---------------------------------------------------------------------------*/ extern THPPlayer ActivePlayer; /*---------------------------------------------------------------------------* Static Variable *---------------------------------------------------------------------------*/ static s32 AudioDecodeThreadCreated = 0; static OSThread AudioDecodeThread; static u8 AudioDecodeThreadStack[4*1024]; static OSMessageQueue FreeAudioBufferQueue; static OSMessageQueue DecodedAudioBufferQueue; static OSMessage FreeAudioBufferMessage[DECODE_AUDIO_BUFFER_NUM]; static OSMessage DecodedAudioBufferMessage[DECODE_AUDIO_BUFFER_NUM]; /*---------------------------------------------------------------------------* Name: CreateAudioDecodeThread Description: Creation of audio decode thread Arguments: priority thread priority ptr Pointer to memory where the start data of movie is with OnMemory playback. Return Values: If creation of thread succeeds, returns TRUE. If creation fails, returns FALSE. *---------------------------------------------------------------------------*/ BOOL CreateAudioDecodeThread(OSPriority priority, u8 *ptr) { if (ptr) { if (OSCreateThread(&AudioDecodeThread, AudioDecoderForOnMemory, ptr, AudioDecodeThreadStack + sizeof(AudioDecodeThreadStack), sizeof(AudioDecodeThreadStack), priority, OS_THREAD_ATTR_DETACH) == FALSE) { #ifdef _DEBUG OSReport("Can't create audio decode thread\n"); #endif return FALSE; } } else { if (OSCreateThread(&AudioDecodeThread, AudioDecoder, NULL, AudioDecodeThreadStack + sizeof(AudioDecodeThreadStack), sizeof(AudioDecodeThreadStack), priority, OS_THREAD_ATTR_DETACH) == FALSE) { #ifdef _DEBUG OSReport("Can't create audio decode thread\n"); #endif return FALSE; } } OSInitMessageQueue(&FreeAudioBufferQueue, FreeAudioBufferMessage, DECODE_AUDIO_BUFFER_NUM); OSInitMessageQueue(&DecodedAudioBufferQueue, DecodedAudioBufferMessage, DECODE_AUDIO_BUFFER_NUM); AudioDecodeThreadCreated = 1; return TRUE; } /*---------------------------------------------------------------------------* Name: AudioDecodeThreadStart Description: Start of audio decode thread. Arguments: None Return Values: None *---------------------------------------------------------------------------*/ void AudioDecodeThreadStart(void) { if (AudioDecodeThreadCreated) { OSResumeThread(&AudioDecodeThread); } return; } /*---------------------------------------------------------------------------* Name: AudioDecodeThreadCancel Description: Cancel audio decode thread Arguments: None Returns: None *---------------------------------------------------------------------------*/ void AudioDecodeThreadCancel(void) { if (AudioDecodeThreadCreated) { OSCancelThread(&AudioDecodeThread); AudioDecodeThreadCreated = 0; } return; } /*---------------------------------------------------------------------------* Name: AudioDecoder Description: Audio decoder for streaming playback Arguments: None Returns: None *---------------------------------------------------------------------------*/ static void *AudioDecoder(void *ptr) { #pragma unused(ptr) THPReadBuffer *readBuffer; s32 frameNumber, count; count = 0; while(1) { readBuffer = PopReadedBuffer(); AudioDecode(readBuffer); if (count < 2) { if (!(ActivePlayer.playFlag & THP_PLAY_LOOP)) { frameNumber = (s32)(readBuffer->frameNumber + ActivePlayer.initReadFrame); if (frameNumber == ActivePlayer.header.numFrames - 1) { PrepareReady(TRUE); } } } if (count == 2) { PrepareReady(TRUE); } PushReadedBuffer2(readBuffer); count++; } return NULL; } /*---------------------------------------------------------------------------* Name: AudioDecoderForOnMemory Description: Audio decoder for OnMemory playback. Arguments: None Returns: None *---------------------------------------------------------------------------*/ static void *AudioDecoderForOnMemory(void *ptr) { THPReadBuffer readBuffer; s32 tmp, size, readFrame, frameNumber; size = ActivePlayer.initReadSize; readBuffer.ptr = (u8 *)ptr; readFrame = 0; while(1) { readBuffer.frameNumber = readFrame; AudioDecode(&readBuffer); frameNumber = (s32)((readFrame + ActivePlayer.initReadFrame) % ActivePlayer.header.numFrames); // Check end of THP movie data if (frameNumber == ActivePlayer.header.numFrames - 1) { // If loop playback, at beginning of movie data if (ActivePlayer.playFlag & THP_PLAY_LOOP) { size = *(s32 *)(readBuffer.ptr); readBuffer.ptr = ActivePlayer.movieData; } // Stop decode if one-shot playback else { if (readFrame < 2) { PrepareReady(TRUE); } OSSuspendThread(&AudioDecodeThread); } } // Move next frame pointer if not end else { tmp = *(s32 *)(readBuffer.ptr); readBuffer.ptr += size; size = tmp; } if (readFrame == 2) { PrepareReady(TRUE); } readFrame++; } return NULL; } /*---------------------------------------------------------------------------* Name: AudioDecode Description: Decoding of THP audio data. Arguments: readBuffer Pointer to buffer where THP frame stored. Returns: None *---------------------------------------------------------------------------*/ static void AudioDecode(THPReadBuffer *readBuffer) { THPAudioBuffer *audioBuffer; u32 i, sample; u32 *compSizePtr; u8 *ptr; compSizePtr = (u32 *)(readBuffer->ptr + 8); ptr = readBuffer->ptr + ActivePlayer.compInfo.numComponents * 4 + 8; audioBuffer = PopFreeAudioBuffer(); for (i = 0 ; i < ActivePlayer.compInfo.numComponents ; i++) { switch (ActivePlayer.compInfo.frameComp[i]) { case THP_AUDIO_COMP: sample = THPAudioDecode(audioBuffer->buffer, ptr + (*compSizePtr) * ActivePlayer.curAudioTrack, THP_AUDIO_INTERLEAVE); audioBuffer->validSample = sample; audioBuffer->curPtr = audioBuffer->buffer; PushDecodedAudioBuffer(audioBuffer); return; default: ptr += *compSizePtr; compSizePtr++; } } return; } /*---------------------------------------------------------------------------* Name: PopFreeAudioBuffer Description: Acquire audio buffers not used. Arguments: None Returns: Pointer for audio buffers not used. *---------------------------------------------------------------------------*/ void *PopFreeAudioBuffer() { OSMessage msg; OSReceiveMessage(&FreeAudioBufferQueue, &msg, OS_MESSAGE_BLOCK); return msg; } /*---------------------------------------------------------------------------* Name: PushFreeAudioBuffer Description: Free THP audio data finished playing back. Arguments: buffer Pointer for THP audio data finished playing back. Returns: None *---------------------------------------------------------------------------*/ void PushFreeAudioBuffer(void *buffer) { OSSendMessage(&FreeAudioBufferQueue, buffer, OS_MESSAGE_NOBLOCK); return; } /*---------------------------------------------------------------------------* Name: PopDecodedAudioBuffer Description: Acquire decoded THP audio data. Arguments: Block until can get decoded THP audio data if flag OS_MESSAGE_BLOCK. Do not block if OS_MESSAGE_NOBLOCK. Returns: If successful, return audio buffer pointer. If unsuccessful, NULL is returned. *---------------------------------------------------------------------------*/ void *PopDecodedAudioBuffer(s32 flag) { OSMessage msg; if (OSReceiveMessage(&DecodedAudioBufferQueue, &msg, flag) == TRUE) { return msg; } else { return NULL; } } /*---------------------------------------------------------------------------* Name: PushDecodedAudioBuffer Description: Push THP audio that has finished decoding into queue Arguments: buffer Pointer for decoded THP audio data. Returns: None *---------------------------------------------------------------------------*/ void PushDecodedAudioBuffer(void *buffer) { OSSendMessage(&DecodedAudioBufferQueue, buffer, OS_MESSAGE_BLOCK); return; }