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