1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SequenceTrack.cpp
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: 23660 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_SequenceTrack.h>
19 
20 #include <nw/snd/snd_SequenceSoundPlayer.h>
21 #include <nw/snd/snd_HardwareManager.h>
22 
23 namespace nw {
24 namespace snd {
25 namespace internal {
26 namespace driver {
27 
28 /* ========================================================================
29         memnber function
30    ======================================================================== */
31 
SetPlayerTrackNo(int playerTrackNo)32 void SequenceTrack::SetPlayerTrackNo( int playerTrackNo )
33 {
34     NW_MINMAX_ASSERT( playerTrackNo, 0, SequenceSoundPlayer::TRACK_NUM_PER_PLAYER );
35     m_PlayerTrackNo  = static_cast<u8>( playerTrackNo );
36 }
37 
SequenceTrack()38 SequenceTrack::SequenceTrack()
39 : m_OpenFlag( false ),
40   m_pSequenceSoundPlayer( NULL ),
41   m_pChannelList( NULL )
42 
43 {
44     InitParam();
45 }
46 
~SequenceTrack()47 SequenceTrack::~SequenceTrack()
48 {
49     Close();
50 }
51 
52 /*---------------------------------------------------------------------------*
53   Name:         InitParam
54 
55   Description:  トラック構造体を初期化します
56 
57   Arguments:    track - トラックポインタ
58 
59   Returns:      None.
60  *---------------------------------------------------------------------------*/
InitParam()61 void SequenceTrack::InitParam()
62 {
63     m_ExtVolume                  = 1.0f;
64     m_ExtPitch                   = 1.0f;
65     m_ExtPan                     = 0.0f;
66     m_ExtSurroundPan             = 0.0f;
67     m_PanRange                   = 1.0f;
68 
69     // Parser Param
70     m_ParserTrackParam.baseAddr       = NULL;
71     m_ParserTrackParam.currentAddr    = NULL;
72 
73     m_ParserTrackParam.cmpFlag        = true;
74     m_ParserTrackParam.noteWaitFlag   = true;
75     m_ParserTrackParam.tieFlag        = false;
76     m_ParserTrackParam.monophonicFlag = false;
77 
78     m_ParserTrackParam.callStackDepth = 0;
79 
80     m_ParserTrackParam.wait           = 0;
81 
82     m_ParserTrackParam.muteFlag       = false;
83     m_ParserTrackParam.silenceFlag    = false;
84     m_ParserTrackParam.noteFinishWait = false;
85     m_ParserTrackParam.portaFlag      = false;
86     m_ParserTrackParam.damperFlag     = false;
87 
88     m_ParserTrackParam.bankIndex      = 0;
89     m_ParserTrackParam.prgNo          = 0;
90 
91     m_ParserTrackParam.lfoParam.Initialize();
92     m_ParserTrackParam.lfoTarget = Channel::LFO_TARGET_PITCH;
93     m_ParserTrackParam.sweepPitch     = 0.0f;
94 
95     m_ParserTrackParam.volume.InitValue( 127 );
96     m_ParserTrackParam.pan.InitValue( 0 );
97     m_ParserTrackParam.surroundPan.InitValue( 0 );
98     m_ParserTrackParam.volume2        = 127;
99     m_ParserTrackParam.velocityRange  = 127;
100     m_ParserTrackParam.pitchBend.InitValue( 0 );
101     m_ParserTrackParam.bendRange      = DEFAULT_BENDRANGE;
102     m_ParserTrackParam.initPan        = 0;
103     m_ParserTrackParam.transpose      = 0;
104     m_ParserTrackParam.priority       = DEFAULT_PRIORITY;
105     m_ParserTrackParam.portaKey       = DEFAULT_PORTA_KEY;
106     m_ParserTrackParam.portaTime      = 0;
107 
108     m_ParserTrackParam.attack         = INVALID_ENVELOPE;
109     m_ParserTrackParam.decay          = INVALID_ENVELOPE;
110     m_ParserTrackParam.sustain        = INVALID_ENVELOPE;
111     m_ParserTrackParam.release        = INVALID_ENVELOPE;
112     m_ParserTrackParam.envHold        = INVALID_ENVELOPE;
113 
114     m_ParserTrackParam.mainSend       = 127;
115     for ( int i=0; i<AUX_BUS_NUM; i++ )
116     {
117         m_ParserTrackParam.fxSend[i] = 0;
118     }
119 
120     m_ParserTrackParam.lpfFreq        = 0.0f;
121     m_ParserTrackParam.biquadType     = 0;
122     m_ParserTrackParam.biquadValue    = 0;
123 
124     for( int varNo = 0; varNo < TRACK_VARIABLE_NUM ; varNo++ )
125     {
126         m_TrackVariable[ varNo ] = SequenceSoundPlayer::VARIABLE_DEFAULT_VALUE;
127     }
128 }
129 
130 /*---------------------------------------------------------------------------*
131   Name:         SetSeqData
132 
133   Description:  シーケンスデータをセットします
134 
135   Arguments:    seqBase - シーケンスデータベースアドレス
136                 seqOffset - シーケンスデータオフセット
137 
138   Returns:      None.
139  *---------------------------------------------------------------------------*/
SetSeqData(const void * seqBase,s32 seqOffset)140 void SequenceTrack::SetSeqData( const void* seqBase, s32 seqOffset )
141 {
142     m_ParserTrackParam.baseAddr    = static_cast<const u8*>( seqBase );
143     m_ParserTrackParam.currentAddr = m_ParserTrackParam.baseAddr + seqOffset;
144 }
145 
Open()146 void SequenceTrack::Open()
147 {
148     m_ParserTrackParam.noteFinishWait = false;
149     m_ParserTrackParam.callStackDepth = 0;
150     m_ParserTrackParam.wait           = 0;
151 
152     m_OpenFlag = true;
153 }
154 
155 /*---------------------------------------------------------------------------*
156   Name:         Close
157 
158   Description:  トラックを閉じます
159 
160   Arguments:    player - プレイヤーポインタ
161 
162   Returns:      None.
163  *---------------------------------------------------------------------------*/
Close()164 void SequenceTrack::Close()
165 {
166     ReleaseAllChannel( -1 );
167     FreeAllChannel();
168 
169     m_OpenFlag = false;
170 }
171 
172 /*---------------------------------------------------------------------------*
173   Name:         UpdateChannelLength
174 
175   Description:  チャンネル長を更新します
176 
177   Arguments:    None.
178 
179   Returns:      None.
180  *---------------------------------------------------------------------------*/
UpdateChannelLength()181 void SequenceTrack::UpdateChannelLength()
182 {
183     if ( ! m_OpenFlag ) return;
184 
185     Channel* channel = m_pChannelList;
186     while( channel != NULL )
187     {
188         if ( channel->GetLength() > 0 )
189         {
190             channel->SetLength( channel->GetLength() - 1 );
191         }
192 
193         UpdateChannelRelease( channel );
194 
195         if ( ! channel->IsAutoUpdateSweep() )
196         {
197             channel->UpdateSweep( 1 );
198         }
199 
200         channel = channel->GetNextTrackChannel();
201     }
202 }
203 
204 /*---------------------------------------------------------------------------*
205   Name:         UpdateChannelRelease
206 
207   Description:  チャンネルをリリース状態を更新する
208 
209   Arguments:    channel - チャンネル
210 
211   Returns:      なし
212  *---------------------------------------------------------------------------*/
UpdateChannelRelease(Channel * channel)213 void SequenceTrack::UpdateChannelRelease( Channel* channel )
214 {
215     if ( ( channel->GetLength() == 0 ) && ( ! channel->IsRelease() ) )
216     {
217         if ( ! m_ParserTrackParam.damperFlag )
218         {
219             channel->NoteOff();
220         }
221     }
222 }
223 
224 /*---------------------------------------------------------------------------*
225   Name:         ParseNextTick
226 
227   Description:  トラックのシーケンス処理を進めます
228 
229   Arguments:    doNoteOn - ノートオンするかどうか
230 
231   Returns:      シーケンス継続時には正を、終了時には負を、未Open時には0を返します
232  *---------------------------------------------------------------------------*/
ParseNextTick(bool doNoteOn)233 int SequenceTrack::ParseNextTick( bool doNoteOn )
234 {
235     if ( ! m_OpenFlag ) {
236         return 0;
237     }
238 
239     // MoveValueの更新
240     m_ParserTrackParam.volume.Update();
241     m_ParserTrackParam.pan.Update();
242     m_ParserTrackParam.surroundPan.Update();
243     m_ParserTrackParam.pitchBend.Update();
244 
245     // ウェイトチェック
246     if ( m_ParserTrackParam.noteFinishWait ) {
247         if ( m_pChannelList != NULL ) {
248             return 1;
249         }
250         m_ParserTrackParam.noteFinishWait = false;
251     }
252     if ( m_ParserTrackParam.wait > 0 ) {
253         m_ParserTrackParam.wait--;
254         if ( m_ParserTrackParam.wait > 0 ) {
255             return 1;
256         }
257     }
258 
259     // シーケンス処理
260     if ( m_ParserTrackParam.currentAddr != NULL )
261     {
262         while( m_ParserTrackParam.wait == 0 && ! m_ParserTrackParam.noteFinishWait )
263         {
264             ParseResult result = Parse( doNoteOn );
265             if ( result == PARSE_RESULT_FINISH ) {
266                 return -1;
267             }
268         }
269     }
270 
271     return 1;
272 }
273 
274 /*---------------------------------------------------------------------------*
275   Name:         StopAllChannel
276 
277   Description:  トラックのチャンネルを全て停止します
278 
279   Arguments:    None.
280 
281   Returns:      None.
282  *---------------------------------------------------------------------------*/
StopAllChannel()283 void SequenceTrack::StopAllChannel()
284 {
285     Channel* channel = m_pChannelList;
286 
287     while( channel != NULL )
288     {
289         Channel::FreeChannel( channel );
290         channel->Stop();
291         channel = channel->GetNextTrackChannel();
292     }
293 
294     m_pChannelList = NULL;
295 }
296 
297 /*---------------------------------------------------------------------------*
298   Name:         ReleaseAllChannel
299 
300   Description:  トラックのチャンネルを全てリリースします
301 
302   Arguments:    release - リリース値(負値の場合は、既に設定されているリリース値を使用する)
303 
304   Returns:      None.
305  *---------------------------------------------------------------------------*/
ReleaseAllChannel(int release)306 void SequenceTrack::ReleaseAllChannel( int release )
307 {
308     UpdateChannelParam();
309 
310     Channel* channel = m_pChannelList;
311     while( channel != NULL )
312     {
313         if ( channel->IsActive() )
314         {
315             if ( release >= 0 )
316             {
317                 NW_MINMAX_ASSERT( release, 0, 127 );
318                 channel->SetRelease( static_cast<u8>( release ) );
319             }
320             channel->Release();
321         }
322         channel = channel->GetNextTrackChannel();
323     }
324 }
325 
326 /*---------------------------------------------------------------------------*
327   Name:         PauseAllChannel
328 
329   Description:  トラックのチャンネルを全てポーズします
330 
331   Arguments:    track - トラックポインタ
332                 player - プレイヤーポインタ
333                 release - リリース値(負値の場合は、既に設定されているリリース値を使用する)
334 
335   Returns:      None.
336  *---------------------------------------------------------------------------*/
PauseAllChannel(bool flag)337 void SequenceTrack::PauseAllChannel( bool flag )
338 {
339     Channel* channel = m_pChannelList;
340 
341     while( channel != NULL )
342     {
343         if ( channel->IsActive() && ( channel->IsPause() != flag ) )
344         {
345             channel->Pause( flag );
346         }
347         channel = channel->GetNextTrackChannel();
348     }
349 }
350 
351 /*---------------------------------------------------------------------------*
352   Name:         AddChannel
353 
354   Description:  トラックへチャンネルを追加します
355 
356   Arguments:    channel - チャンネルポインタ
357 
358   Returns:      None.
359  *---------------------------------------------------------------------------*/
AddChannel(Channel * channel)360 void SequenceTrack::AddChannel( Channel* channel )
361 {
362     channel->SetNextTrackChannel( m_pChannelList );
363     m_pChannelList = channel;
364 }
365 
366 /*---------------------------------------------------------------------------*
367   Name:         UpdateChannelParam
368 
369   Description:  トラックが保持しているチャンネルのパラメータを更新します
370 
371   Arguments:    None.
372 
373   Returns:      None.
374  *---------------------------------------------------------------------------*/
UpdateChannelParam()375 void SequenceTrack::UpdateChannelParam()
376 {
377     if ( ! m_OpenFlag ) return;
378 
379     if ( m_pChannelList == NULL ) {
380         // 更新不要
381         return;
382     }
383 
384     // volume
385     register float volume
386         = m_ParserTrackParam.volume.GetValue()
387         * m_ParserTrackParam.volume2
388         * m_pSequenceSoundPlayer->GetParserPlayerParam().volume
389         / (127.0f * 127.0f * 127.0f);
390     volume = volume * volume * m_ExtVolume * m_pSequenceSoundPlayer->GetVolume();
391 
392     f32 pitch = ( m_ParserTrackParam.pitchBend.GetValue() / 128.0f ) * m_ParserTrackParam.bendRange;
393 
394     float pitchRatio = m_pSequenceSoundPlayer->GetPitch() * m_ExtPitch;
395 
396     // pan
397     register float pan
398         = ut::Clamp( static_cast<float>( m_ParserTrackParam.pan.GetValue() ) / 63.0f, -1.0f, 1.0f )
399         * m_PanRange
400         * m_pSequenceSoundPlayer->GetPanRange()
401         + m_ExtPan
402         + m_pSequenceSoundPlayer->GetPan();
403 
404     // surround pan
405     float surroundPan
406         = ut::Clamp( static_cast<float>( m_ParserTrackParam.surroundPan.GetValue() ) / 63.0f, 0.0f, 2.0f )
407         + m_ExtSurroundPan
408         + m_pSequenceSoundPlayer->GetSurroundPan();
409 
410     // lpf freq
411     float lpfFreq
412         = m_ParserTrackParam.lpfFreq
413         + m_pSequenceSoundPlayer->GetLpfFreq();
414 
415     // biquad filter
416     int biquadType = m_ParserTrackParam.biquadType;
417     float biquadValue = m_ParserTrackParam.biquadValue;
418     if ( m_pSequenceSoundPlayer->GetBiquadFilterType() != BIQUAD_FILTER_TYPE_NONE )
419     {
420         biquadType = m_pSequenceSoundPlayer->GetBiquadFilterType();
421         biquadValue = m_pSequenceSoundPlayer->GetBiquadFilterValue();
422     }
423 
424     // main send
425     float mainSend
426         = static_cast<float>( m_ParserTrackParam.mainSend ) / 127.0f - 1.0f // -1.0 ~ 0.0 に
427         + m_pSequenceSoundPlayer->GetMainSend();
428 
429     float fxSend[ AUX_BUS_NUM ];
430     for ( int i=0; i<AUX_BUS_NUM; i++ )
431     {
432         AuxBus bus = static_cast<AuxBus>( i );
433         fxSend[ i ] = static_cast<float>( m_ParserTrackParam.fxSend[i] ) / 127.0f
434                       + m_pSequenceSoundPlayer->GetFxSend( bus );
435     }
436 
437     // set channel params of track
438     register Channel* channel = m_pChannelList;
439     while( channel != NULL )
440     {
441         channel->SetUserVolume( volume );
442         channel->SetUserPitch( pitch );
443         channel->SetUserPitchRatio( pitchRatio );
444         channel->SetUserPan( pan );
445         channel->SetUserSurroundPan( surroundPan );
446         channel->SetUserLpfFreq( lpfFreq );
447         channel->SetBiquadFilter( biquadType, biquadValue );
448         channel->SetMainSend( mainSend );
449         for ( int i=0; i<AUX_BUS_NUM; i++ )
450         {
451             AuxBus bus = static_cast<AuxBus>( i );
452             channel->SetFxSend( bus, fxSend[ i ] );
453         }
454 
455         channel->SetLfoParam( m_ParserTrackParam.lfoParam );
456         channel->SetLfoTarget( static_cast<Channel::LfoTarget>( m_ParserTrackParam.lfoTarget ) );
457 
458         channel = channel->GetNextTrackChannel();
459     }
460 }
461 
462 /*---------------------------------------------------------------------------*
463   Name:         FreeAllChannel
464 
465   Description:  トラックのチャンネルを全て解放します
466 
467   Arguments:    track - トラックポインタ
468 
469   Returns:      None.
470  *---------------------------------------------------------------------------*/
FreeAllChannel(void)471 void SequenceTrack::FreeAllChannel( void )
472 {
473     Channel* channel = m_pChannelList;
474 
475     while( channel != NULL ) {
476         Channel::FreeChannel( channel );
477         channel = channel->GetNextTrackChannel();
478     }
479     m_pChannelList = NULL;
480 }
481 
482 
483 /*---------------------------------------------------------------------------*
484   Name:         GetChannelCount
485 
486   Description:  トラックが保持しているチャンネル数を取得する
487 
488   Arguments:    なし
489 
490   Returns:      チャンネル数
491  *---------------------------------------------------------------------------*/
GetChannelCount() const492 int SequenceTrack::GetChannelCount() const
493 {
494     Channel* channel = m_pChannelList;
495     int count = 0;
496     while( channel != NULL ) {
497         ++count;
498         channel = channel->GetNextTrackChannel();
499     }
500 
501     return count;
502 }
503 
504 /*---------------------------------------------------------------------------*
505   Name:         ChannelCallbackFunc
506 
507   Description:  チャンネルから呼びだされるコールバック関数
508 
509   Arguments:    dropChannel - チャンネルポインタ
510                 status - チャンネルコールバックステータス
511                 userData - トラックポインタを格納したコールバックユーザーデータ
512 
513   Returns:      None.
514  *---------------------------------------------------------------------------*/
ChannelCallbackFunc(Channel * dropChannel,Channel::ChannelCallbackStatus status,u32 userData)515 void SequenceTrack::ChannelCallbackFunc(
516     Channel* dropChannel,
517     Channel::ChannelCallbackStatus status,
518     u32 userData
519 )
520 {
521     SequenceTrack* track = reinterpret_cast<SequenceTrack*>( userData );
522 
523     NW_NULL_ASSERT( dropChannel );
524     NW_NULL_ASSERT( track );
525 
526     switch ( status )
527     {
528     case Channel::CALLBACK_STATUS_STOPPED:
529     case Channel::CALLBACK_STATUS_FINISH:
530         Channel::FreeChannel( dropChannel );
531         break;
532     }
533 
534     if ( track->m_pSequenceSoundPlayer != NULL ) {
535         track->m_pSequenceSoundPlayer->ChannelCallback( dropChannel );
536     }
537 
538     // チャンネル参照の切断
539     if ( track->m_pChannelList == dropChannel ) {
540         track->m_pChannelList = dropChannel->GetNextTrackChannel();
541         return;
542     }
543 
544     Channel* channel = track->m_pChannelList;
545     NW_NULL_ASSERT( channel );
546     while( channel->GetNextTrackChannel() != NULL ) {
547         if ( channel->GetNextTrackChannel() == dropChannel ) {
548             channel->SetNextTrackChannel( dropChannel->GetNextTrackChannel() );
549             return;
550         }
551         channel = channel->GetNextTrackChannel();
552     }
553 
554     NW_ASSERT( false );
555 }
556 
SetMute(SeqMute mute)557 void SequenceTrack::SetMute( SeqMute mute )
558 {
559     switch ( mute )
560     {
561     case SEQ_MUTE_OFF:
562         m_ParserTrackParam.muteFlag = false;
563         break;
564     case SEQ_MUTE_STOP:
565         StopAllChannel();
566         m_ParserTrackParam.muteFlag = true;
567         break;
568     case SEQ_MUTE_RELEASE:
569         ReleaseAllChannel( -1 );
570         FreeAllChannel();
571         m_ParserTrackParam.muteFlag = true;
572         break;
573     case SEQ_MUTE_NO_STOP:
574         m_ParserTrackParam.muteFlag = true;
575         break;
576     }
577 }
578 
SetSilence(bool silenceFlag,int fadeTimes)579 void SequenceTrack::SetSilence( bool silenceFlag, int fadeTimes )
580 {
581     m_ParserTrackParam.silenceFlag = silenceFlag;
582 
583     Channel* channel = m_pChannelList;
584     while( channel != NULL )
585     {
586         channel->SetSilence(
587             silenceFlag,
588             ( fadeTimes + HardwareManager::SOUND_FRAME_INTERVAL_MSEC - 1 ) /
589               HardwareManager::SOUND_FRAME_INTERVAL_MSEC );
590         channel = channel->GetNextTrackChannel();
591     }
592 }
593 
SetBiquadFilter(int type,float value)594 void SequenceTrack::SetBiquadFilter( int type, float value )
595 {
596     m_ParserTrackParam.biquadType = static_cast<u8>( type );
597     m_ParserTrackParam.biquadValue = value;
598 }
599 
SetBankIndex(int bankIndex)600 void SequenceTrack::SetBankIndex( int bankIndex )
601 {
602     // SequenceSoundHandle::SetTrackBankIndex でも範囲チェックしているが、念のため。
603     NW_MINMAXLT_ASSERT( bankIndex, 0, SoundArchive::SEQ_BANK_MAX );
604     m_ParserTrackParam.bankIndex = static_cast<u8>( bankIndex );
605 }
606 
607 /*---------------------------------------------------------------------------*
608   Name:         GetTrackVariable
609 
610   Description:  シーケンストラック変数を取得します。
611 
612   Arguments:    varNo - 変数番号
613 
614   Returns:      変数の値
615  *---------------------------------------------------------------------------*/
GetTrackVariable(int varNo) const616 s16 SequenceTrack::GetTrackVariable( int varNo ) const
617 {
618     NW_MINMAXLT_ASSERT( varNo, 0, TRACK_VARIABLE_NUM );
619 
620     return m_TrackVariable[ varNo ];
621 }
622 
623 /*---------------------------------------------------------------------------*
624   Name:         SetTrackVariable
625 
626   Description:  シーケンスローカル変数を設定します。
627 
628   Arguments:    player - プレイヤー
629                 varNo - 変数番号
630                 var - 変数値
631 
632   Returns:      変数の値
633  *---------------------------------------------------------------------------*/
SetTrackVariable(int varNo,s16 var)634 void SequenceTrack::SetTrackVariable( int varNo, s16 var )
635 {
636     NW_MINMAXLT_ASSERT( varNo, 0, TRACK_VARIABLE_NUM );
637 
638     m_TrackVariable[ varNo ] = var;
639 }
640 
641 /*---------------------------------------------------------------------------*
642   Name:         GetVariablePtr
643 
644   Description:  変数のポインタを取得します
645 
646   Arguments:    player - プレイヤーポインタ
647                 varNo    - 変数番号
648 
649   Returns:      変数のポインタ
650  *---------------------------------------------------------------------------*/
GetVariablePtr(int varNo)651 vs16* SequenceTrack::GetVariablePtr( int varNo )
652 {
653     NW_MINMAX_ASSERT( varNo, 0, TRACK_VARIABLE_NUM );
654 
655     if ( varNo < TRACK_VARIABLE_NUM )
656     {
657         return & m_TrackVariable[ varNo ];
658     }
659     else
660     {
661         return NULL;
662     }
663 }
664 
665 /*---------------------------------------------------------------------------*
666   Name:         NoteOn
667 
668   Description:  ノートオン
669 
670   Arguments:    key      - キー番号
671                 velocity - ベロシティ
672                 length   - ノート長 ( -1 なら無限長 )
673                 tieFlag  - タイフラグ
674 
675   Returns:      発音したチャンネルのポインタ
676  *---------------------------------------------------------------------------*/
NoteOn(int key,int velocity,s32 length,bool tieFlag)677 Channel* SequenceTrack::NoteOn(
678     int key,
679     int velocity,
680     s32 length,
681     bool tieFlag
682 )
683 {
684     NW_MINMAX_ASSERT( key, 0, 127 );
685     NW_MINMAX_ASSERT( velocity, 0, 127 );
686 
687     const SequenceSoundPlayer::ParserPlayerParam& playerParam = m_pSequenceSoundPlayer->GetParserPlayerParam();
688 
689     Channel* channel = NULL;
690 
691     // ベロシティレンジ適用
692     velocity = velocity * m_ParserTrackParam.velocityRange / 127;
693 
694     if ( tieFlag )
695     {
696         // タイ
697         channel = GetLastChannel();
698         if ( channel != NULL )
699         {
700             channel->SetKey( static_cast<u8>( key ) );
701             float initVolume = static_cast<float>( velocity ) / 127.0f;
702             channel->SetInitVolume( initVolume * initVolume );
703             // TODO: パンも更新するか?
704         }
705     }
706 
707     if ( GetParserTrackParam().monophonicFlag )
708     {
709         // モノフォニック
710         channel = GetLastChannel();
711         if ( channel != NULL )
712         {
713             if ( channel->IsRelease() )
714             {
715                 channel->Stop();
716                 channel = NULL;
717             }
718             else
719             {
720                 channel->SetKey( static_cast<u8>( key ) );
721                 float initVolume = static_cast<float>( velocity ) / 127.0f;
722                 channel->SetInitVolume( initVolume * initVolume );
723                 channel->SetLength( length );
724             }
725         }
726     }
727 
728     if ( channel == NULL )
729     {
730         NoteOnInfo noteOnInfo = {
731             m_ParserTrackParam.prgNo,
732             key,
733             velocity,
734             tieFlag ? -1 : length,
735             m_ParserTrackParam.initPan,
736             playerParam.priority + m_ParserTrackParam.priority,
737             SequenceTrack::ChannelCallbackFunc,
738             reinterpret_cast<u32>( this )
739         };
740         channel = m_pSequenceSoundPlayer->NoteOn(
741             m_ParserTrackParam.bankIndex,
742             noteOnInfo
743         );
744         if ( channel == NULL ) return NULL;
745 
746         // オルタネートアサイン処理
747         if ( channel->GetKeyGroupId() > 0 )
748         {
749             Channel* itr = m_pChannelList;
750             while( itr != NULL )
751             {
752                 if ( itr->GetKeyGroupId() == channel->GetKeyGroupId() )
753                 {
754                     itr->Release();
755                 }
756                 itr = itr->GetNextTrackChannel();
757             }
758         }
759 
760         // チャンネルリストへの結合
761         AddChannel( channel );
762     }
763 
764     // 初期パラメータ設定
765 
766     // エンベロープ更新
767     if ( m_ParserTrackParam.attack <= SequenceTrack::MAX_ENVELOPE_VALUE )
768     {
769         channel->SetAttack( m_ParserTrackParam.attack );
770     }
771 
772     if ( m_ParserTrackParam.decay <= SequenceTrack::MAX_ENVELOPE_VALUE )
773     {
774         channel->SetDecay( m_ParserTrackParam.decay );
775     }
776 
777     if ( m_ParserTrackParam.sustain <= SequenceTrack::MAX_ENVELOPE_VALUE )
778     {
779         channel->SetSustain( m_ParserTrackParam.sustain );
780     }
781 
782     if ( m_ParserTrackParam.release <= SequenceTrack::MAX_ENVELOPE_VALUE )
783     {
784         channel->SetRelease( m_ParserTrackParam.release );
785     }
786     if ( m_ParserTrackParam.envHold <= SequenceTrack::MAX_ENVELOPE_VALUE )
787     {
788         channel->SetHold( m_ParserTrackParam.envHold );
789     }
790 
791     // スイープ&ポルタメント更新
792     f32 sweepPitch = m_ParserTrackParam.sweepPitch;
793 
794     if ( m_ParserTrackParam.portaFlag )
795     {
796         sweepPitch += m_ParserTrackParam.portaKey - key;
797     }
798 
799     if ( m_ParserTrackParam.portaTime == 0 )
800     {
801         NW_WARNING( length != 0, "portatime zero is invalid." );
802         channel->SetSweepParam( sweepPitch, length, false );
803     }
804     else
805     {
806         int sweepTime = m_ParserTrackParam.portaTime;
807         sweepTime *= sweepTime;
808         sweepTime = static_cast<int>( sweepTime * ( sweepPitch >= 0 ? sweepPitch : -sweepPitch ) );
809         sweepTime >>= 5;
810         sweepTime *= 5; // 単位はmsec
811 
812         channel->SetSweepParam( sweepPitch, sweepTime, true );
813     }
814 
815     // ポルタメント開始キーを更新
816     m_ParserTrackParam.portaKey = static_cast<u8>( key );
817 
818     // その他
819     channel->SetSilence( m_ParserTrackParam.silenceFlag != 0, 0 );
820     channel->SetReleasePriorityFix( m_pSequenceSoundPlayer->IsReleasePriorityFix() );
821     channel->SetPanMode( m_pSequenceSoundPlayer->GetPanMode() );
822     channel->SetPanCurve( m_pSequenceSoundPlayer->GetPanCurve() );
823     channel->SetFrontBypass( m_ParserTrackParam.frontBypassFlag );
824 
825     return channel;
826 }
827 
828 } // namespace nw::snd::internal::driver
829 } // namespace nw::snd::internal
830 } // namespace nw::snd
831 } // namespace nw
832 
833