mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@2 385bec56-5757-e545-9c3a-d8741f4650f1
241 lines
7.6 KiB
C++
241 lines
7.6 KiB
C++
/*---------------------------------------------------------------------------*
|
||
Project: Horizon
|
||
File: SimplePlayer.cpp
|
||
|
||
Copyright (C)2009 Nintendo Co., Ltd. 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.
|
||
|
||
$Rev$
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
#include <nn.h>
|
||
#include <nn/os.h>
|
||
#include <nn/fnd.h>
|
||
#include <nn/fs.h>
|
||
#include <nn/hid.h>
|
||
#include <nn/snd.h>
|
||
|
||
#include <string.h>
|
||
#include "SimplePlayer.h"
|
||
#include "wave.h"
|
||
#include "HeapManager.h"
|
||
|
||
namespace common
|
||
{
|
||
|
||
namespace
|
||
{
|
||
const int nFiles = 4; // 使用できる voice の最大値は 24
|
||
const char* apFileNames[nFiles] =
|
||
{
|
||
"rom:/ok.wav",
|
||
"rom:/ng.wav",
|
||
"rom:/cursor.wav",
|
||
"rom:/annotation.wav"
|
||
};
|
||
|
||
nn::snd::CTR::Voice* apVoice[nFiles];
|
||
nn::snd::CTR::WaveBuffer aBuffer[nFiles];
|
||
WaveFmt fmt[nFiles];
|
||
WaveData data[nFiles];
|
||
u8* apMemory[nFiles];
|
||
|
||
nn::os::CriticalSection s_CriticalSection;
|
||
bool s_SoundThreadInitialized = false;
|
||
|
||
// サウンドスレッド関連
|
||
const int SOUND_THREAD_STACK_SIZE = 4096;
|
||
nn::os::StackBuffer<SOUND_THREAD_STACK_SIZE> s_SoundThreadStack;
|
||
nn::os::Thread threadSound;
|
||
bool threadSoundFlag;
|
||
void SoundThreadFunc()
|
||
{
|
||
// サウンド出力をステレオに
|
||
nn::snd::SetSoundOutputMode(nn::snd::OUTPUT_MODE_STEREO);
|
||
|
||
// マスターボリュームを設定
|
||
nn::snd::SetMasterVolume( 1.0 );
|
||
|
||
NN_LOG("Loading wav files...\n");
|
||
|
||
// ファイルを開く
|
||
for (int i = 0; i < nFiles; i++)
|
||
{
|
||
if (apFileNames[i] == NULL) continue;
|
||
|
||
nn::snd::Voice* pVoice = NULL;
|
||
|
||
nn::fs::FileReader fileReader;
|
||
nn::Result result = fileReader.TryInitialize(apFileNames[i]);
|
||
NN_UTIL_PANIC_IF_FAILED(result);
|
||
if (::std::strcmp(::std::strrchr(apFileNames[i], '.'), ".wav") == false)
|
||
{
|
||
// 連続メモリ領域の取得、確認
|
||
apMemory[i] = reinterpret_cast<u8*>(HeapManager::GetHeap()->Allocate(GetWaveLength(fileReader), 32));
|
||
if (apMemory[i] == NULL)
|
||
{
|
||
NN_LOG("Failed to allocate continuous memory\n");
|
||
continue;
|
||
}
|
||
|
||
|
||
// Wave データを読み込み、キャッシュを無効に
|
||
data[i].buf = apMemory[i];
|
||
LoadWave(fileReader, &fmt[i], &data[i]);
|
||
nn::snd::FlushDataCache(reinterpret_cast<uptr>(apMemory[i]), data[i].size);
|
||
|
||
NN_LOG("%s (%1dch, %5dHz, %2d-bit wav file)\n",
|
||
apFileNames[i], fmt[i].channel, fmt[i].sample_rate, fmt[i].quantum_bits);
|
||
|
||
pVoice = apVoice[i] = nn::snd::AllocVoice(128, NULL, NULL);
|
||
NN_TASSERT_(pVoice);
|
||
|
||
nn::snd::SampleFormat format = (fmt[i].quantum_bits == 8) ?
|
||
nn::snd::SAMPLE_FORMAT_PCM8 :
|
||
nn::snd::SAMPLE_FORMAT_PCM16;
|
||
|
||
pVoice->SetChannelCount( fmt[i].channel );
|
||
pVoice->SetSampleFormat( format );
|
||
|
||
nn::snd::InitializeWaveBuffer(&aBuffer[i]);
|
||
aBuffer[i].bufferAddress = apMemory[i];
|
||
aBuffer[i].sampleLength = nn::snd::GetSampleLength(data[i].size, format, fmt[i].channel);
|
||
aBuffer[i].loopFlag = false;
|
||
|
||
fileReader.Finalize();
|
||
|
||
// 音量の設定
|
||
nn::snd::MixParam mix;
|
||
mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_LEFT ] = 0.707f; // メインボリューム (L)
|
||
mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_RIGHT] = 0.707f; // メインボリューム (R)
|
||
pVoice->SetMixParam(mix);
|
||
pVoice->SetVolume(1.0f);
|
||
|
||
// pitch の設定
|
||
pVoice->SetSampleRate(fmt[i].sample_rate);
|
||
pVoice->SetPitch(1.0f);
|
||
|
||
}
|
||
}
|
||
|
||
// 再生開始
|
||
for (int i = 0; i < nFiles; i++)
|
||
{
|
||
if (apFileNames[i] != NULL)
|
||
{
|
||
apVoice[i]->SetState( nn::snd::Voice::STATE_PLAY );
|
||
}
|
||
}
|
||
|
||
s_SoundThreadInitialized = true;
|
||
|
||
threadSoundFlag = true;
|
||
while (threadSoundFlag)
|
||
{
|
||
nn::snd::WaitForDspSync(); // DSP からのデータ受信を待つ。
|
||
|
||
|
||
s_CriticalSection.Enter(); // メインスレッドとの排他制御
|
||
nn::snd::SendParameterToDsp(); // パラメータを DSP に送信。
|
||
s_CriticalSection.Leave(); // メインスレッドとの排他制御
|
||
}
|
||
|
||
// 再生終了
|
||
for (int i = 0; i < nFiles; i++)
|
||
{
|
||
if (apVoice[i])
|
||
{
|
||
nn::snd::FreeVoice(apVoice[i]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void InitializeSimplePlayer()
|
||
{
|
||
NN_LOG("Initialize SimplePlayer\n");
|
||
|
||
nn::Result result;
|
||
|
||
const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
|
||
static char buffer[ROMFS_BUFFER_SIZE];
|
||
NN_UTIL_PANIC_IF_FAILED(
|
||
nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
|
||
|
||
// dsp, snd の初期化
|
||
result = nn::dsp::Initialize();
|
||
NN_UTIL_PANIC_IF_FAILED(result);
|
||
result = nn::dsp::LoadDefaultComponent();
|
||
NN_UTIL_PANIC_IF_FAILED(result);
|
||
result = nn::snd::Initialize();
|
||
NN_UTIL_PANIC_IF_FAILED(result);
|
||
|
||
s_CriticalSection.Initialize();
|
||
|
||
// サウンドスレッドを起動(DSP 割り込みイベント待ち)
|
||
threadSound.Start(SoundThreadFunc, s_SoundThreadStack);
|
||
}
|
||
|
||
void PlaySound(u8 index)
|
||
{
|
||
NN_ASSERT(0 <= index <= nFiles);
|
||
|
||
while(!s_SoundThreadInitialized)
|
||
{
|
||
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(1));
|
||
}
|
||
|
||
nn::snd::CTR::Voice* pVoice = apVoice[index];
|
||
|
||
if (!pVoice->IsPlaying())
|
||
{
|
||
nn::snd::InitializeWaveBuffer(&aBuffer[index]);
|
||
aBuffer[index].bufferAddress = apMemory[index];
|
||
nn::snd::SampleFormat format = (fmt[index].quantum_bits == 8) ? nn::snd::SAMPLE_FORMAT_PCM8
|
||
: nn::snd::SAMPLE_FORMAT_PCM16;
|
||
|
||
aBuffer[index].sampleLength = nn::snd::GetSampleLength(data[index].size, format, fmt[index].channel);
|
||
aBuffer[index].loopFlag = false;
|
||
|
||
pVoice->AppendWaveBuffer(&aBuffer[index]);
|
||
NN_LOG("[voice%d] %s (pitch = %f)\n",
|
||
index,
|
||
(pVoice->GetState() == nn::snd::Voice::STATE_PAUSE ? "pause" : "play "),
|
||
pVoice->GetPitch());
|
||
}
|
||
}
|
||
|
||
void FinalizeSimplePlayer()
|
||
{
|
||
nn::Result result;
|
||
|
||
// サウンドスレッドの破棄
|
||
threadSoundFlag = false;
|
||
threadSound.Join();
|
||
|
||
// SND の終了処理
|
||
result = nn::snd::Finalize();
|
||
NN_UTIL_PANIC_IF_FAILED(result);
|
||
|
||
s_CriticalSection.Finalize();
|
||
|
||
// DSP の終了処理
|
||
result = nn::dsp::UnloadComponent();
|
||
NN_UTIL_PANIC_IF_FAILED(result);
|
||
nn::dsp::Finalize();
|
||
|
||
|
||
NN_LOG("Finalize SimplePlayer\n");
|
||
|
||
}
|
||
|
||
} // namespace ConsoleBackup
|
||
/*---------------------------------------------------------------------------*
|
||
End of file
|
||
*---------------------------------------------------------------------------*/
|