/*---------------------------------------------------------------------------* 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:41 aka Imported from Dolphin tree. 4 03/11/25 11:24 Dante Japanese to English translation of comments and text strings 3 03/09/16 15:39:00 Suzuki changed DECODE_BUFFER_NUM to DECODE_AUDIO_BUFFER_NUM. 2 02/05/14 9:12a Suzuki changed return value type and argument type of PopFreeAudioBuffer() , PushFreeAudioBuffer(), PopDecodedAudioBuffer(), PushDecodedAudioBuffer(). 1 02/01/16 10:52a Akagi Initial revision made by Suzuki-san (IRD). $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include "THPPlayer.h" #include "THPAudioDecode.h" #include "THPRead.h" /*---------------------------------------------------------------------------* 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, TRUE. If creation fails, 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 Return Values: None *---------------------------------------------------------------------------*/ void AudioDecodeThreadCancel(void) { if (AudioDecodeThreadCreated) { OSCancelThread(&AudioDecodeThread); AudioDecodeThreadCreated = 0; } return; } /*---------------------------------------------------------------------------* Name: AudioDecoder Description: Audio decoder for streaming playback Arguments: None Return Values: None *---------------------------------------------------------------------------*/ static void *AudioDecoder(void *ptr) { #pragma unused(ptr) THPReadBuffer *readBuffer; while(1) { readBuffer = (THPReadBuffer *)PopReadedBuffer(); AudioDecode(readBuffer); PushReadedBuffer2(readBuffer); } return NULL; } /*---------------------------------------------------------------------------* Name: AudioDecoderForOnMemory Description: Audio decoder for OnMemory playback. Arguments: None Return Values: 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 { OSSuspendThread(&AudioDecodeThread); } } // Move next frame pointer if not end else { tmp = *(s32 *)(readBuffer.ptr); readBuffer.ptr += size; size = tmp; } readFrame++; } return NULL; } /*---------------------------------------------------------------------------* Name: AudioDecode Description: Decoding of THP audio data. Arguments: readBuffer Pointer to buffer where the THP frame is stored. Return Values: 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: Get audio buffers not used. Arguments: None Return Values: 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. Return Values: None *---------------------------------------------------------------------------*/ void PushFreeAudioBuffer(void *buffer) { OSSendMessage(&FreeAudioBufferQueue, buffer, OS_MESSAGE_NOBLOCK); return; } /*---------------------------------------------------------------------------* Name: PopDecodedAudioBuffer Description: Get 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. Return Values: If successful, returns audio buffer pointer. If unsuccessful, returns NULL. *---------------------------------------------------------------------------*/ 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. Return Values: None *---------------------------------------------------------------------------*/ void PushDecodedAudioBuffer(void *buffer) { OSSendMessage(&DecodedAudioBufferQueue, buffer, OS_MESSAGE_BLOCK); return; }