diff --git a/build/systemMenu_RED/Launcher/ARM9/Makefile b/build/systemMenu_RED/Launcher/ARM9/Makefile index 0a563f99..a3707be2 100644 --- a/build/systemMenu_RED/Launcher/ARM9/Makefile +++ b/build/systemMenu_RED/Launcher/ARM9/Makefile @@ -43,7 +43,7 @@ MISC_DIR = ../../misc BG_DIR = ../../data SRCS_LOGO = logoDemo.c logoData.c -SRCS = main.c launcher.c \ +SRCS = main.c launcher.c sound.c\ $(addprefix $(LOGO_DIR)/, $(SRCS_LOGO)) \ $(MISC_DIR)/src/misc.c $(MISC_DIR)/src/cmn.c \ $(BG_DIR)/BGData_Launcher.c diff --git a/build/systemMenu_RED/Launcher/ARM9/main.rsf b/build/systemMenu_RED/Launcher/ARM9/main.rsf index 928b92aa..42ce8c68 100644 --- a/build/systemMenu_RED/Launcher/ARM9/main.rsf +++ b/build/systemMenu_RED/Launcher/ARM9/main.rsf @@ -152,5 +152,5 @@ RomSpec Segment ALL HostRoot ../../data Root /data - File NTR_IPL_font_m.NFTR NoCardBanner.bnr EmptyBanner.bnr NoBanner.bnr + File NTR_IPL_font_m.NFTR NoCardBanner.bnr EmptyBanner.bnr NoBanner.bnr fanfare.32.wav } \ No newline at end of file diff --git a/build/systemMenu_RED/Launcher/ARM9/src/launcher.c b/build/systemMenu_RED/Launcher/ARM9/src/launcher.c index e17e7d0f..7c40a005 100644 --- a/build/systemMenu_RED/Launcher/ARM9/src/launcher.c +++ b/build/systemMenu_RED/Launcher/ARM9/src/launcher.c @@ -18,6 +18,7 @@ #include #include "misc.h" #include "launcher.h" +#include "sound.h" #include @@ -110,7 +111,10 @@ static int bar_left = BAR_ZERO_X; static fx32 s_selected_banner_size; static BOOL s_wavstop = FALSE; +//static StreamInfo strm; // stream info + // const data ----------------------------------------- +//const char filename[] = "data/fanfare.32.wav"; //=============================================== // Launcher.c @@ -365,6 +369,10 @@ void LauncherInit( TitleProperty *pTitleList ) GX_DispOn(); GXS_DispOn(); + // streamInfo初期化 + //FS_InitFile(&strm.file); + //strm.isPlay = FALSE; + #ifdef DBGBNR BannerInit(); #endif @@ -542,6 +550,7 @@ static TitleProperty *ProcessPads( TitleProperty *pTitleList ) if( ( pad.trg & PAD_BUTTON_A ) || ( tp_select ) ) { // メニュー項目への分岐 if( pTitleList[selected].flags.isValid ) { + //PlayStream(&strm, filename); ret = &pTitleList[selected]; } } diff --git a/build/systemMenu_RED/Launcher/ARM9/src/main.c b/build/systemMenu_RED/Launcher/ARM9/src/main.c index 10700244..d8a8b014 100644 --- a/build/systemMenu_RED/Launcher/ARM9/src/main.c +++ b/build/systemMenu_RED/Launcher/ARM9/src/main.c @@ -19,6 +19,7 @@ #include "launcher.h" #include "misc.h" #include "logoDemo.h" +#include "sound.h" // extern data----------------------------------------------------------------- @@ -32,8 +33,15 @@ static void INTR_VBlank( void ); // static variable------------------------------------------------------------- static TitleProperty s_titleList[ LAUNCHER_TITLE_LIST_NUM ]; +static u64 strmThreadStack[THREAD_STACK_SIZE / sizeof(u64)]; +static OSThread strmThread; + +static StreamInfo strm; // stream info + // const data------------------------------------------------------------------ +const char filename[] = "data/fanfare.32.wav"; + // メイン void TwlMain( void ) { @@ -68,6 +76,8 @@ void TwlMain( void ) PM_Init(); TP_Init(); RTC_Init(); + SND_Init();// sound init + // 割り込み許可-------------------- (void)OS_SetIrqFunction(OS_IE_V_BLANK, INTR_VBlank); @@ -115,16 +125,37 @@ void TwlMain( void ) state = LOGODEMO_INIT; } + // チャンネルをロックする + SND_LockChannel((1 << L_CHANNEL) | (1 << R_CHANNEL), 0); + + /* ストリームスレッドの起動 */ + OS_CreateThread(&strmThread, + StrmThread, + NULL, + strmThreadStack + THREAD_STACK_SIZE / sizeof(u64), + THREAD_STACK_SIZE, STREAM_THREAD_PRIO); + OS_WakeupThreadDirect(&strmThread); + // メインループ-------------------- while( 1 ) { OS_WaitIrq(1, OS_IE_V_BLANK); // Vブランク割り込み待ち + // ARM7コマンド応答受信 + while (SND_RecvCommandReply(SND_COMMAND_NOBLOCK) != NULL) + { + } + ReadKeyPad(); // キー入力の取得 ReadTP(); // TP入力の取得 switch( state ) { case LOGODEMO_INIT: LogoInit(); + // 音鳴らすテスト + FS_InitFile(&strm.file); + strm.isPlay = FALSE; + PlayStream(&strm, filename); + state = LOGODEMO; break; case LOGODEMO: @@ -177,6 +208,9 @@ void TwlMain( void ) // カードアプリリストの取得(スレッドで随時カード挿抜を通知されるものをメインループで取得) (void)SYSM_GetCardTitleList( s_titleList ); + + // コマンドフラッシュ + (void)SND_FlushCommand(SND_COMMAND_NOBLOCK); } } diff --git a/build/systemMenu_RED/Launcher/ARM9/src/sound.c b/build/systemMenu_RED/Launcher/ARM9/src/sound.c new file mode 100644 index 00000000..9b2c3519 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/sound.c @@ -0,0 +1,349 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: sound.c + + Copyright 2007 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. + + $Date:: 2007-10-25#$ + $Rev: 1800 $ + $Author: ida $ + *---------------------------------------------------------------------------*/ + +#include "sound.h" + +static BOOL ReadWaveFormat(StreamInfo * strm); +static void ReadStrmData(StreamInfo * strm); +static void SoundAlarmHandler(void *arg); +static void VBlankIntr(void); + +static u16 Cont; +static u16 Trg; +static OSMessageQueue msgQ; +static OSMessage msgBuf[1]; + +static u8 strm_lbuf[STRM_BUF_SIZE] ATTRIBUTE_ALIGN(32); +static u8 strm_rbuf[STRM_BUF_SIZE] ATTRIBUTE_ALIGN(32); +static u8 strm_tmp[STRM_BUF_PAGESIZE * 2] ATTRIBUTE_ALIGN(32); + +/*---------------------------------------------------------------------------* + Name: PlayStream + + Description: ストリーム再生を再生 + + Arguments: strm - ストリームオブジェクト + filename - ストリーム再生するファイル名 + + Returns: None. + *---------------------------------------------------------------------------*/ +void PlayStream(StreamInfo * strm, const char *filename) +{ + int timerValue; + u32 alarmPeriod; + + // 再生中であれば停止する + if (strm->isPlay) + { + u32 tag; + StopStream(strm); + tag = SND_GetCurrentCommandTag(); + (void)SND_FlushCommand(SND_COMMAND_NOBLOCK | SND_COMMAND_IMMEDIATE); + SND_WaitForCommandProc(tag); // 停止を待つ + } + + // ファイル走査 + if (FS_IsFile(&strm->file)) + (void)FS_CloseFile(&strm->file); + if ( ! FS_OpenFile(&strm->file, filename) ) { + OS_Panic("Error: failed to open file %s\n", filename); + } + if (!ReadWaveFormat(strm)) + { + OS_Panic("Error: failed to read wavefile\n"); + } + + strm->isPlay = TRUE; + + /* パラメータ設定 */ + timerValue = SND_TIMER_CLOCK / strm->format.sampleRate; + alarmPeriod = timerValue * STRM_BUF_PAGESIZE / 32U; + alarmPeriod /= (strm->format.bitPerSample == 16) ? sizeof(s16) : sizeof(s8); + + // 初期ストリームデータ読み込み + (void)FS_SeekFile(&strm->file, (s32)strm->beginPos, FS_SEEK_SET); + strm->bufPage = 0; + ReadStrmData(strm); + ReadStrmData(strm); + + // チャンネルとアラームをセットアップ + SND_SetupChannelPcm(L_CHANNEL, + (strm->format.bitPerSample == + 16) ? SND_WAVE_FORMAT_PCM16 : SND_WAVE_FORMAT_PCM8, strm_lbuf, + SND_CHANNEL_LOOP_REPEAT, 0, STRM_BUF_SIZE / sizeof(u32), 127, + SND_CHANNEL_DATASHIFT_NONE, timerValue, 0); + SND_SetupChannelPcm(R_CHANNEL, + (strm->format.bitPerSample == + 16) ? SND_WAVE_FORMAT_PCM16 : SND_WAVE_FORMAT_PCM8, + (strm->format.channels == 1) ? strm_lbuf : strm_rbuf, + SND_CHANNEL_LOOP_REPEAT, 0, STRM_BUF_SIZE / sizeof(u32), 127, + SND_CHANNEL_DATASHIFT_NONE, timerValue, 127); + SND_SetupAlarm(ALARM_NUM, alarmPeriod, alarmPeriod, SoundAlarmHandler, strm); + SND_StartTimer((1 << L_CHANNEL) | (1 << R_CHANNEL), 0, 1 << ALARM_NUM, 0); +} + +/*---------------------------------------------------------------------------* + Name: StopStream + + Description: ストリーム再生を停止 + + Arguments: strm - ストリームオブジェクト + + Returns: None. + *---------------------------------------------------------------------------*/ +void StopStream(StreamInfo * strm) +{ + SND_StopTimer((1 << L_CHANNEL) | (1 << R_CHANNEL), 0, 1 << ALARM_NUM, 0); + if (FS_IsFile(&strm->file)) + (void)FS_CloseFile(&strm->file); + strm->isPlay = FALSE; +} + +/*---------------------------------------------------------------------------* + Name: StrmThread + + Description: ストリームスレッド + + Arguments: arg - ユーザーデータ(未使用) + + Returns: None. + *---------------------------------------------------------------------------*/ +void StrmThread(void * /*arg */ ) +{ + OSMessage message; + + OS_InitMessageQueue(&msgQ, msgBuf, 1); + + while (1) + { + (void)OS_ReceiveMessage(&msgQ, &message, OS_MESSAGE_BLOCK); + (void)ReadStrmData((StreamInfo *) message); + } +} + +/*---------------------------------------------------------------------------* + Name: SoundAlarmHandler + + Description: アラームコールバック関数 + + Arguments: arg - ストリームオブジェクト + + Returns: None. + *---------------------------------------------------------------------------*/ +static void SoundAlarmHandler(void *arg) +{ + (void)OS_SendMessage(&msgQ, (OSMessage)arg, OS_MESSAGE_NOBLOCK); +} + +/*---------------------------------------------------------------------------* + Name: ReadStrmData + + Description: ストリームデータ読み込み関数 + ファイルからバッファの1ページ分のストリームデータを読み込む + + Arguments: strm - ストリームオブジェクト + + Returns: None. + *---------------------------------------------------------------------------*/ +static void ReadStrmData(StreamInfo * strm) +{ + int i; + s32 readSize; + u8 *lbuf, *rbuf; + + // ストリームが終端に達している + if (strm->dataSize <= 0) + { + StopStream(strm); + return; + } + + // バッファのページ設定 + if (strm->bufPage == 0) + { + lbuf = strm_lbuf; + rbuf = strm_rbuf; + strm->bufPage = 1; + } + else + { + lbuf = strm_lbuf + STRM_BUF_PAGESIZE; + rbuf = strm_rbuf + STRM_BUF_PAGESIZE; + strm->bufPage = 0; + } + + // データ読み込み + if (strm->format.channels == 1) + { + // モノラル + readSize = FS_ReadFile(&strm->file, + strm_tmp, + (strm->dataSize < + STRM_BUF_PAGESIZE) ? strm->dataSize : STRM_BUF_PAGESIZE); + if (readSize == -1) + OS_Panic("read file end\n"); + + if (strm->format.bitPerSample == 16) + { + // 16bitデータ + for (i = 0; i < readSize / sizeof(s16); i++) + { + ((s16 *)lbuf)[i] = ((s16 *)strm_tmp)[i]; + } + for (; i < STRM_BUF_PAGESIZE / sizeof(s16); i++) + { + ((s16 *)lbuf)[i] = 0; // ストリームの終端に達した場合、残りを0で埋める + } + } + else + { + // 8bitデータ + for (i = 0; i < readSize / sizeof(s8); i++) + { + ((s8 *)lbuf)[i] = (s8)((s16)strm_tmp[i] - 128); + } + for (; i < STRM_BUF_PAGESIZE / sizeof(s8); i++) + { + ((s8 *)lbuf)[i] = 0; + } + } + } + else + { + // ステレオ + readSize = FS_ReadFile(&strm->file, + strm_tmp, + (strm->dataSize < + STRM_BUF_PAGESIZE * 2) ? strm->dataSize : STRM_BUF_PAGESIZE * 2); + if (readSize == -1) + OS_Panic("read file end\n"); + + if (strm->format.bitPerSample == 16) + { + // 16bitデータ + for (i = 0; i < (readSize / 2) / sizeof(s16); i++) + { + ((s16 *)lbuf)[i] = ((s16 *)strm_tmp)[2 * i]; + ((s16 *)rbuf)[i] = ((s16 *)strm_tmp)[2 * i + 1]; + } + for (; i < STRM_BUF_PAGESIZE / sizeof(s16); i++) + { + ((s16 *)lbuf)[i] = 0; + ((s16 *)rbuf)[i] = 0; + } + } + else + { + // 8bitデータ + for (i = 0; i < (readSize / 2) / sizeof(s8); i++) + { + ((s8 *)lbuf)[i] = (s8)((s16)strm_tmp[2 * i] - 128); + ((s8 *)rbuf)[i] = (s8)((s16)strm_tmp[2 * i + 1] - 128); + } + for (; i < STRM_BUF_PAGESIZE / sizeof(s8); i++) + { + ((s8 *)lbuf)[i] = 0; + ((s8 *)rbuf)[i] = 0; + } + } + } + + strm->dataSize -= readSize; + + return; +} + + +/*---------------------------------------------------------------------------* + Name: ReadWaveFormat + + Description: WAVEフォーマットのデータのヘッダとデータ列の先頭位置、データサイズを取得 + + Arguments: strm - ストリームオブジェクト + + Returns: 読み取りに成功したらTRUE、失敗したらFALSE + *---------------------------------------------------------------------------*/ +static BOOL ReadWaveFormat(StreamInfo * strm) +{ + u32 tag; + s32 size; + BOOL fFmt = FALSE, fData = FALSE; + + (void)FS_SeekFileToBegin(&strm->file); + + (void)FS_ReadFile(&strm->file, &tag, 4); + if (tag != FOURCC_RIFF) + return FALSE; + + (void)FS_ReadFile(&strm->file, &size, 4); + + (void)FS_ReadFile(&strm->file, &tag, 4); + if (tag != FOURCC_WAVE) + return FALSE; + + while (size > 0) + { + s32 chunkSize; + if (FS_ReadFile(&strm->file, &tag, 4) == -1) + { + return FALSE; + } + if (FS_ReadFile(&strm->file, &chunkSize, 4) == -1) + { + return FALSE; + } + + switch (tag) + { + case FOURCC_fmt: + if (FS_ReadFile(&strm->file, (u8 *)&strm->format, chunkSize) == -1) + { + return FALSE; + } + fFmt = TRUE; + break; + case FOURCC_data: + strm->beginPos = FS_GetPosition(&strm->file); + strm->dataSize = chunkSize; + (void)FS_SeekFile(&strm->file, chunkSize, FS_SEEK_CUR); + fData = TRUE; + break; + default: + (void)FS_SeekFile(&strm->file, chunkSize, FS_SEEK_CUR); + break; + } + if (fFmt && fData) + { + return TRUE; // fmt と data を読み終えたら強制終了 + } + + size -= chunkSize; + } + + if (size != 0) + return FALSE; + return TRUE; +} + +//-------------------------------------------------------------------------------- +// Vブランク割り込み処理 +// +static void VBlankIntr(void) +{ + // 割り込みチェックフラグ + OS_SetIrqCheckFlag(OS_IE_V_BLANK); +} diff --git a/build/systemMenu_RED/Launcher/ARM9/src/sound.h b/build/systemMenu_RED/Launcher/ARM9/src/sound.h new file mode 100644 index 00000000..a84f662b --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/sound.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: sound.h + + Copyright 2007 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. + + $Date:: 2007-11-20#$ + $Rev: 231 $ + $Author: yosiokat $ + *---------------------------------------------------------------------------*/ + +#ifndef __LAUNCHER_SOUND_H__ +#define __LAUNCHER_SOUND_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// define data------------------------------------------------------- + +#define MAKE_FOURCC(cc1, cc2, cc3, cc4) (u32)((cc1) | (cc2 << 8) | (cc3 << 16) | (cc4 << 24)) + +#define FOURCC_RIFF MAKE_FOURCC('R', 'I', 'F', 'F') +#define FOURCC_WAVE MAKE_FOURCC('W', 'A', 'V', 'E') +#define FOURCC_fmt MAKE_FOURCC('f', 'm', 't', ' ') +#define FOURCC_data MAKE_FOURCC('d', 'a', 't', 'a') + +#define L_CHANNEL 4 +#define R_CHANNEL 5 +#define ALARM_NUM 0 +#define STREAM_THREAD_PRIO 12 +#define THREAD_STACK_SIZE 1024 +#define STRM_BUF_PAGESIZE 1024*32 +#define STRM_BUF_SIZE STRM_BUF_PAGESIZE*2 + +// WAVフォーマットヘッダ +typedef struct WaveFormat +{ + u16 format; + u16 channels; + s32 sampleRate; + u32 dataRate; + u16 blockAlign; + u16 bitPerSample; +} +WaveFormat; + +// ストリームオブジェクト +typedef struct StreamInfo +{ + FSFile file; + WaveFormat format; + u32 beginPos; + s32 dataSize; + u32 bufPage; + BOOL isPlay; +} +StreamInfo; + +// global variables-------------------------------------------------- + +// function---------------------------------------------------------- + +void PlayStream(StreamInfo * strm, const char *filename); +void StopStream(StreamInfo * strm); +void StrmThread(void *arg); + + +#ifdef __cplusplus +} +#endif + +#endif // __LAUNCHER_H__ diff --git a/build/systemMenu_RED/data/fanfare.32.wav b/build/systemMenu_RED/data/fanfare.32.wav new file mode 100644 index 00000000..eb6cc56b Binary files /dev/null and b/build/systemMenu_RED/data/fanfare.32.wav differ