1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SequenceSoundPlayer.h
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Revision: 27883 $
14  *---------------------------------------------------------------------------*/
15 /**
16  * :include nw/snd/snd_SequenceSoundPlayer.h
17  *
18  * @file snd_SequenceSoundPlayer.h
19  */
20 
21 #ifndef NW_SND_SEQUENCE_SOUND_PLAYER_H_
22 #define NW_SND_SEQUENCE_SOUND_PLAYER_H_
23 
24 #include <nw/snd/snd_BasicSoundPlayer.h>
25 #include <nw/snd/snd_DisposeCallback.h>
26 #include <nw/snd/snd_SoundThread.h>
27 #include <nw/snd/snd_NoteOnCallback.h>      // NoteOnCallback, NoteOnInfo
28 #include <nw/snd/snd_SoundArchive.h>
29 
30 namespace nw {
31 namespace snd {
32 
33 // シーケンスコマンド'userproc'用コールバック
34 //---------------------------------------------------------------------------
35 //! @brief    'userproc' コマンドで呼び出されるコールバックで使用される構造体です。
36 //!
37 //!           'userproc' コマンドの詳細については、
38 //!           シーケンスデータマニュアルを参照してください。
39 //---------------------------------------------------------------------------
40 struct SequenceUserprocCallbackParam
41 {
42     //---------------------------------------------------------------------------
43     //! @brief    ローカル変数の配列です。
44     //!           localVariable[0] から localVariable[15] まで指定できます。
45     //!           変数の値を参照、あるいは変更することができます。
46     //---------------------------------------------------------------------------
47     vs16* localVariable;
48 
49     //---------------------------------------------------------------------------
50     //! @brief    グローバル変数の配列です。
51     //!           globalVariable[0] から globalVariable[15] まで指定できます。
52     //!           変数の値を参照、あるいは変更することができます。
53     //---------------------------------------------------------------------------
54     vs16* globalVariable;
55 
56     //---------------------------------------------------------------------------
57     //! @brief    トラック変数の配列です。
58     //!           trackVariable[0] から trackVariable[15] まで指定できます。
59     //!           変数の値を参照、あるいは変更することができます。
60     //---------------------------------------------------------------------------
61     vs16* trackVariable;
62 
63     //---------------------------------------------------------------------------
64     //! @brief    比較コマンドで設定される真偽のフラグです。
65     //!           フラグの状態を参照、あるいは変更することができます。
66     //---------------------------------------------------------------------------
67     bool cmpFlag;
68 };
69 
70 //---------------------------------------------------------------------------
71 //! @brief    シーケンスサウンドで使用可能なユーザープロシージャのコールバックです。
72 //!
73 //!           このコールバックはシーケンスデータ内の 'userproc'
74 //!           コマンドによって呼び出されます。
75 //!           'userproc' コマンドが処理されたフレームで、
76 //!           サウンドスレッドから呼び出されます。
77 //!
78 //!           procId は、シーケンスデータで 'userproc'
79 //!           コマンドのパラメータとして指定された値が渡されます。
80 //!
81 //!           param は、コールバック内で利用できるパラメータです。
82 //!           データで設定されてる値を参照することができます。
83 //!           また、この値を書き換えることでサウンドデータに反映することが出来ます。
84 //!
85 //!           'userproc' コマンドの詳細については、
86 //!           シーケンスデータマニュアルを参照してください。
87 //!
88 //! @param[in] procId     シーケンスデータで指定されたプロシージャ ID です。
89 //! @param[in] param      コールバック内で利用できるパラメータです。
90 //! @param[in] arg        ユーザー引数です。
91 //!
92 //! @see      @ref SoundArchivePlayer::SetSequenceUserprocCallback,
93 //!           @ref SequenceUserprocCallbackParam
94 //---------------------------------------------------------------------------
95 typedef void (*SequenceUserprocCallback)(
96     u16 procId,
97     SequenceUserprocCallbackParam* param,
98     void* arg
99 );
100 
101 namespace internal {
102 namespace driver {
103 
104 /* ========================================================================
105         typename declaration
106    ======================================================================== */
107 
108 class SequenceTrack;
109 class SequenceTrackAllocator;
110 
111 /* ========================================================================
112         class definition
113    ======================================================================== */
114 
115 class SequenceSoundPlayer : public BasicSoundPlayer, public DisposeCallback, public SoundThread::PlayerCallback
116 {
117     /* ------------------------------------------------------------------------
118             constant variable
119        ------------------------------------------------------------------------ */
120   public:
121     static const int PLAYER_VARIABLE_NUM    = 16;
122     static const int GLOBAL_VARIABLE_NUM    = 16;
123     static const int TRACK_NUM_PER_PLAYER   = 16;
124     static const int VARIABLE_DEFAULT_VALUE = -1;
125 
126     static const int DEFAULT_TIMEBASE       = 48; /* 四分音符分解能 */
127     static const int DEFAULT_TEMPO          = 120;
128 
129     static const int MAX_SKIP_TICK_PER_FRAME = 48*4*4;
130 
131     /* ------------------------------------------------------------------------
132             type definition
133        ------------------------------------------------------------------------ */
134   public:
135     struct ParserPlayerParam
136     {
137         u8 volume;
138         u8 priority;
139         u8 timebase;
140         u16 tempo;
141 
142         NoteOnCallback* callback;
143     };
144 
145 #if 0
146     enum SetupResult
147     {
148         SETUP_SUCCESS = 0,
149         SETUP_ERR_CANNOT_ALLOCATE_TRACK,
150         SETUP_ERR_UNKNOWN
151     };
152 #endif
153 
154     enum OffsetType
155     {
156         OFFSET_TYPE_TICK,
157         OFFSET_TYPE_MILLISEC
158     };
159 
160     /* ------------------------------------------------------------------------
161             class member
162        ------------------------------------------------------------------------ */
163   public:
164     static void InitSequenceSoundPlayer();
165 
166     SequenceSoundPlayer();
167     virtual ~SequenceSoundPlayer();
168 
169     virtual void Initialize();
170     virtual void Finalize();
171 
172     void Setup(
173         SequenceTrackAllocator* trackAllocator,
174         u32 allocTracks,
175         NoteOnCallback* callback
176     );
177 
178     void SetSeqData( const void* seqBase, s32 seqOffset );
179     void SetBankData( const void* bankFiles[], u32 bankFileCount );
180 
181     virtual void Start();
182     virtual void Stop();
183     virtual void Pause( bool flag );
184     void Skip( OffsetType offsetType, int offset );
185 
186     Channel* NoteOn(
187         u8 bankIndex,
188         const NoteOnInfo& noteOnInfo
189     );
190 
191     void SetSequenceUserprocCallback( SequenceUserprocCallback callback, void* arg );
192     void CallSequenceUserprocCallback( u16 procId, SequenceTrack* track );
193 
194     //------------------------------------------------------------------
195     // プレイヤーパラメータ
196     void SetTempoRatio( float tempoRatio );
197     void SetPanRange( float panRange );
198     void SetChannelPriority( int priority );
199     void SetReleasePriorityFix( bool fix );
200 
GetTempoRatio()201     float GetTempoRatio() const { return m_TempoRatio; }
GetPanRange()202     float GetPanRange() const { return m_PanRange; }
GetChannelPriority()203     int GetChannelPriority() const { return m_ParserParam.priority; }
204 
IsReleasePriorityFix()205     bool IsReleasePriorityFix() const { return m_ReleasePriorityFixFlag; }
206 
207     //------------------------------------------------------------------
208     // トラックパラメータ
209     void SetTrackMute( u32 trackBitFlag, SeqMute mute );
210     void SetTrackSilence( unsigned long trackBitFlag, bool silenceFlag, int fadeTimes );
211     void SetTrackVolume( u32 trackBitFlag, float volume );
212     void SetTrackPitch( u32 trackBitFlag, float pitch );
213     void SetTrackPan( u32 trackBitFlag, float pan );
214     void SetTrackSurroundPan( u32 trackBitFlag, float surroundPan );
215     void SetTrackPanRange( u32 trackBitFlag, float panRange );
216     void SetTrackLpfFreq( u32 trackBitFlag, float lpfFreq );
217     void SetTrackBiquadFilter( u32 trackBitFlag, int type, float value );
218     void SetTrackModDepth( u32 trackBitFlag, float depth );
219     void SetTrackModSpeed( u32 trackBitFlag, float speed );
220     bool SetTrackBankIndex( u32 trackBitFlag, int bankIndex );
221 
SetBankFile(u8 bankIndex,const void * pBankFile)222     void SetBankFile( u8 bankIndex, const void* pBankFile )
223     {
224         m_pBankFiles[ bankIndex ] = pBankFile;
225     }
GetBankFile(u8 bankIndex)226     const void* GetBankFile( u8 bankIndex ) const { return m_pBankFiles[ bankIndex ]; }
227 
228     //------------------------------------------------------------------
229     // シーケンス変数
230     s16 GetLocalVariable( int varNo ) const;
231     static s16 GetGlobalVariable( int varNo );
232     void SetLocalVariable( int varNo, s16 var );
233     static void SetGlobalVariable( int varNo, s16 var );
234 
235     vs16* GetVariablePtr( int varNo );
236 
237     //------------------------------------------------------------------
238     // invalidate
239     virtual void InvalidateData( const void* start, const void* end );
240 
241     //------------------------------------------------------------------
242     // info
GetParserPlayerParam()243     const ParserPlayerParam& GetParserPlayerParam() const { return m_ParserParam; }
GetParserPlayerParam()244     ParserPlayerParam& GetParserPlayerParam() { return m_ParserParam; }
GetTickCounter()245     u32 GetTickCounter() const { return m_TickCounter; }
246 
247     //------------------------------------------------------------------
248     SequenceTrack* GetPlayerTrack( int trackNo );
249     const SequenceTrack* GetPlayerTrack( int trackNo ) const;
250     void SetPlayerTrack( int trackNo, SequenceTrack* track );
251 
GetTrackAllocator()252     const SequenceTrackAllocator* GetTrackAllocator() { return m_pSequenceTrackAllocator; }
253 
254     void Update();
255 
ChannelCallback(Channel * channel)256     virtual void ChannelCallback( Channel* channel ) { (void)channel; }
257 
258   protected:
OnUpdateFrameSoundThread()259     virtual void OnUpdateFrameSoundThread() { Update(); }
OnShutdownSoundThread()260     virtual void OnShutdownSoundThread() { Stop(); }
261 
262   private:
263     template< typename T >
264     void SetTrackParam( u32 trackBitFlag, void (SequenceTrack::*func)( T ), T param );
265     template< typename T, typename U >
266     void SetTrackParam( u32 trackBitFlag, void (SequenceTrack::*func)( T, U ), T param1, U param2 );
267 
268     int  ParseNextTick( bool doNoteOn );
269 
270     void UpdateChannelParam();
271     void UpdateTick();
272     void SkipTick();
273 
274     void CloseTrack( int trackNo );
275     void FinishPlayer();
276 
CalcTickPerMinute()277     f32 CalcTickPerMinute() const { return m_ParserParam.timebase * m_ParserParam.tempo * m_TempoRatio; }
CalcTickPerMsec()278     f32 CalcTickPerMsec() const { return CalcTickPerMinute() / ( 60 * 1000.0f ); }
279 
280     static vs16 m_GlobalVariable[ GLOBAL_VARIABLE_NUM ];
281 
282     bool m_ReleasePriorityFixFlag;
283 
284     f32 m_PanRange;
285     f32 m_TempoRatio;
286     f32 m_TickFraction;
287     u32 m_SkipTickCounter;
288     f32 m_SkipTimeCounter;
289 
290     ParserPlayerParam m_ParserParam;
291     SequenceTrackAllocator* m_pSequenceTrackAllocator;
292 
293     SequenceUserprocCallback m_SequenceUserprocCallback;
294     void* m_pSequenceUserprocCallbackArg;
295 
296     SequenceTrack* m_pTracks[ TRACK_NUM_PER_PLAYER ];
297 
298     vs16 m_LocalVariable[ PLAYER_VARIABLE_NUM ];
299     vu32 m_TickCounter;
300 
301     const void* m_pBankFiles[ SoundArchive::SEQ_BANK_MAX ];
302 };
303 
304 template< typename T >
SetTrackParam(u32 trackBitFlag,void (SequenceTrack::* func)(T),T param)305 void SequenceSoundPlayer::SetTrackParam( u32 trackBitFlag, void (SequenceTrack::*func)( T ), T param )
306 {
307     for( int trackNo = 0;
308          trackNo < TRACK_NUM_PER_PLAYER && trackBitFlag != 0 ;
309          trackNo++, trackBitFlag >>= 1
310     )
311     {
312         if ( ( trackBitFlag & 0x01 ) == 0 ) continue;
313         SequenceTrack* track = GetPlayerTrack( trackNo );
314         if ( track != NULL ) (track->*func)( param );
315     }
316 }
317 
318 template< typename T, typename U >
SetTrackParam(u32 trackBitFlag,void (SequenceTrack::* func)(T,U),T param1,U param2)319 void SequenceSoundPlayer::SetTrackParam( u32 trackBitFlag, void (SequenceTrack::*func)( T, U ), T param1, U param2 )
320 {
321     for( int trackNo = 0;
322          trackNo < TRACK_NUM_PER_PLAYER && trackBitFlag != 0 ;
323          trackNo++, trackBitFlag >>= 1
324     )
325     {
326         if ( ( trackBitFlag & 0x01 ) == 0 ) continue;
327         SequenceTrack* track = GetPlayerTrack( trackNo );
328         if ( track != NULL ) (track->*func)( param1, param2 );
329     }
330 }
331 
332 } // namespace nw::snd::internal::driver
333 } // namespace nw::snd::internal
334 } // namespace nw::snd
335 } // namespace nw
336 
337 
338 #endif /* NW_SND_SEQUENCE_SOUND_PLAYER_H_ */
339 
340