/*---------------------------------------------------------------------------* Project: NintendoWare File: snd_SequenceSoundPlayer.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. 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. $Revision: 27883 $ *---------------------------------------------------------------------------*/ /** * :include nw/snd/snd_SequenceSoundPlayer.h * * @file snd_SequenceSoundPlayer.h */ #ifndef NW_SND_SEQUENCE_SOUND_PLAYER_H_ #define NW_SND_SEQUENCE_SOUND_PLAYER_H_ #include #include #include #include // NoteOnCallback, NoteOnInfo #include namespace nw { namespace snd { // シーケンスコマンド'userproc'用コールバック //--------------------------------------------------------------------------- //! @brief 'userproc' コマンドで呼び出されるコールバックで使用される構造体です。 //! //! 'userproc' コマンドの詳細については、 //! シーケンスデータマニュアルを参照してください。 //--------------------------------------------------------------------------- struct SequenceUserprocCallbackParam { //--------------------------------------------------------------------------- //! @brief ローカル変数の配列です。 //! localVariable[0] から localVariable[15] まで指定できます。 //! 変数の値を参照、あるいは変更することができます。 //--------------------------------------------------------------------------- vs16* localVariable; //--------------------------------------------------------------------------- //! @brief グローバル変数の配列です。 //! globalVariable[0] から globalVariable[15] まで指定できます。 //! 変数の値を参照、あるいは変更することができます。 //--------------------------------------------------------------------------- vs16* globalVariable; //--------------------------------------------------------------------------- //! @brief トラック変数の配列です。 //! trackVariable[0] から trackVariable[15] まで指定できます。 //! 変数の値を参照、あるいは変更することができます。 //--------------------------------------------------------------------------- vs16* trackVariable; //--------------------------------------------------------------------------- //! @brief 比較コマンドで設定される真偽のフラグです。 //! フラグの状態を参照、あるいは変更することができます。 //--------------------------------------------------------------------------- bool cmpFlag; }; //--------------------------------------------------------------------------- //! @brief シーケンスサウンドで使用可能なユーザープロシージャのコールバックです。 //! //! このコールバックはシーケンスデータ内の 'userproc' //! コマンドによって呼び出されます。 //! 'userproc' コマンドが処理されたフレームで、 //! サウンドスレッドから呼び出されます。 //! //! procId は、シーケンスデータで 'userproc' //! コマンドのパラメータとして指定された値が渡されます。 //! //! param は、コールバック内で利用できるパラメータです。 //! データで設定されてる値を参照することができます。 //! また、この値を書き換えることでサウンドデータに反映することが出来ます。 //! //! 'userproc' コマンドの詳細については、 //! シーケンスデータマニュアルを参照してください。 //! //! @param[in] procId シーケンスデータで指定されたプロシージャ ID です。 //! @param[in] param コールバック内で利用できるパラメータです。 //! @param[in] arg ユーザー引数です。 //! //! @see @ref SoundArchivePlayer::SetSequenceUserprocCallback, //! @ref SequenceUserprocCallbackParam //--------------------------------------------------------------------------- typedef void (*SequenceUserprocCallback)( u16 procId, SequenceUserprocCallbackParam* param, void* arg ); namespace internal { namespace driver { /* ======================================================================== typename declaration ======================================================================== */ class SequenceTrack; class SequenceTrackAllocator; /* ======================================================================== class definition ======================================================================== */ class SequenceSoundPlayer : public BasicSoundPlayer, public DisposeCallback, public SoundThread::PlayerCallback { /* ------------------------------------------------------------------------ constant variable ------------------------------------------------------------------------ */ public: static const int PLAYER_VARIABLE_NUM = 16; static const int GLOBAL_VARIABLE_NUM = 16; static const int TRACK_NUM_PER_PLAYER = 16; static const int VARIABLE_DEFAULT_VALUE = -1; static const int DEFAULT_TIMEBASE = 48; /* 四分音符分解能 */ static const int DEFAULT_TEMPO = 120; static const int MAX_SKIP_TICK_PER_FRAME = 48*4*4; /* ------------------------------------------------------------------------ type definition ------------------------------------------------------------------------ */ public: struct ParserPlayerParam { u8 volume; u8 priority; u8 timebase; u16 tempo; NoteOnCallback* callback; }; #if 0 enum SetupResult { SETUP_SUCCESS = 0, SETUP_ERR_CANNOT_ALLOCATE_TRACK, SETUP_ERR_UNKNOWN }; #endif enum OffsetType { OFFSET_TYPE_TICK, OFFSET_TYPE_MILLISEC }; /* ------------------------------------------------------------------------ class member ------------------------------------------------------------------------ */ public: static void InitSequenceSoundPlayer(); SequenceSoundPlayer(); virtual ~SequenceSoundPlayer(); virtual void Initialize(); virtual void Finalize(); void Setup( SequenceTrackAllocator* trackAllocator, u32 allocTracks, NoteOnCallback* callback ); void SetSeqData( const void* seqBase, s32 seqOffset ); void SetBankData( const void* bankFiles[], u32 bankFileCount ); virtual void Start(); virtual void Stop(); virtual void Pause( bool flag ); void Skip( OffsetType offsetType, int offset ); Channel* NoteOn( u8 bankIndex, const NoteOnInfo& noteOnInfo ); void SetSequenceUserprocCallback( SequenceUserprocCallback callback, void* arg ); void CallSequenceUserprocCallback( u16 procId, SequenceTrack* track ); //------------------------------------------------------------------ // プレイヤーパラメータ void SetTempoRatio( float tempoRatio ); void SetPanRange( float panRange ); void SetChannelPriority( int priority ); void SetReleasePriorityFix( bool fix ); float GetTempoRatio() const { return m_TempoRatio; } float GetPanRange() const { return m_PanRange; } int GetChannelPriority() const { return m_ParserParam.priority; } bool IsReleasePriorityFix() const { return m_ReleasePriorityFixFlag; } //------------------------------------------------------------------ // トラックパラメータ void SetTrackMute( u32 trackBitFlag, SeqMute mute ); void SetTrackSilence( unsigned long trackBitFlag, bool silenceFlag, int fadeTimes ); void SetTrackVolume( u32 trackBitFlag, float volume ); void SetTrackPitch( u32 trackBitFlag, float pitch ); void SetTrackPan( u32 trackBitFlag, float pan ); void SetTrackSurroundPan( u32 trackBitFlag, float surroundPan ); void SetTrackPanRange( u32 trackBitFlag, float panRange ); void SetTrackLpfFreq( u32 trackBitFlag, float lpfFreq ); void SetTrackBiquadFilter( u32 trackBitFlag, int type, float value ); void SetTrackModDepth( u32 trackBitFlag, float depth ); void SetTrackModSpeed( u32 trackBitFlag, float speed ); bool SetTrackBankIndex( u32 trackBitFlag, int bankIndex ); void SetBankFile( u8 bankIndex, const void* pBankFile ) { m_pBankFiles[ bankIndex ] = pBankFile; } const void* GetBankFile( u8 bankIndex ) const { return m_pBankFiles[ bankIndex ]; } //------------------------------------------------------------------ // シーケンス変数 s16 GetLocalVariable( int varNo ) const; static s16 GetGlobalVariable( int varNo ); void SetLocalVariable( int varNo, s16 var ); static void SetGlobalVariable( int varNo, s16 var ); vs16* GetVariablePtr( int varNo ); //------------------------------------------------------------------ // invalidate virtual void InvalidateData( const void* start, const void* end ); //------------------------------------------------------------------ // info const ParserPlayerParam& GetParserPlayerParam() const { return m_ParserParam; } ParserPlayerParam& GetParserPlayerParam() { return m_ParserParam; } u32 GetTickCounter() const { return m_TickCounter; } //------------------------------------------------------------------ SequenceTrack* GetPlayerTrack( int trackNo ); const SequenceTrack* GetPlayerTrack( int trackNo ) const; void SetPlayerTrack( int trackNo, SequenceTrack* track ); const SequenceTrackAllocator* GetTrackAllocator() { return m_pSequenceTrackAllocator; } void Update(); virtual void ChannelCallback( Channel* channel ) { (void)channel; } protected: virtual void OnUpdateFrameSoundThread() { Update(); } virtual void OnShutdownSoundThread() { Stop(); } private: template< typename T > void SetTrackParam( u32 trackBitFlag, void (SequenceTrack::*func)( T ), T param ); template< typename T, typename U > void SetTrackParam( u32 trackBitFlag, void (SequenceTrack::*func)( T, U ), T param1, U param2 ); int ParseNextTick( bool doNoteOn ); void UpdateChannelParam(); void UpdateTick(); void SkipTick(); void CloseTrack( int trackNo ); void FinishPlayer(); f32 CalcTickPerMinute() const { return m_ParserParam.timebase * m_ParserParam.tempo * m_TempoRatio; } f32 CalcTickPerMsec() const { return CalcTickPerMinute() / ( 60 * 1000.0f ); } static vs16 m_GlobalVariable[ GLOBAL_VARIABLE_NUM ]; bool m_ReleasePriorityFixFlag; f32 m_PanRange; f32 m_TempoRatio; f32 m_TickFraction; u32 m_SkipTickCounter; f32 m_SkipTimeCounter; ParserPlayerParam m_ParserParam; SequenceTrackAllocator* m_pSequenceTrackAllocator; SequenceUserprocCallback m_SequenceUserprocCallback; void* m_pSequenceUserprocCallbackArg; SequenceTrack* m_pTracks[ TRACK_NUM_PER_PLAYER ]; vs16 m_LocalVariable[ PLAYER_VARIABLE_NUM ]; vu32 m_TickCounter; const void* m_pBankFiles[ SoundArchive::SEQ_BANK_MAX ]; }; template< typename T > void SequenceSoundPlayer::SetTrackParam( u32 trackBitFlag, void (SequenceTrack::*func)( T ), T param ) { for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER && trackBitFlag != 0 ; trackNo++, trackBitFlag >>= 1 ) { if ( ( trackBitFlag & 0x01 ) == 0 ) continue; SequenceTrack* track = GetPlayerTrack( trackNo ); if ( track != NULL ) (track->*func)( param ); } } template< typename T, typename U > void SequenceSoundPlayer::SetTrackParam( u32 trackBitFlag, void (SequenceTrack::*func)( T, U ), T param1, U param2 ) { for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER && trackBitFlag != 0 ; trackNo++, trackBitFlag >>= 1 ) { if ( ( trackBitFlag & 0x01 ) == 0 ) continue; SequenceTrack* track = GetPlayerTrack( trackNo ); if ( track != NULL ) (track->*func)( param1, param2 ); } } } // namespace nw::snd::internal::driver } // namespace nw::snd::internal } // namespace nw::snd } // namespace nw #endif /* NW_SND_SEQUENCE_SOUND_PLAYER_H_ */