1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_MidiSequencePlayer.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: 22432 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_MidiSequencePlayer.h>
19 
20 #include <nw/snd/snd_SequenceTrack.h>
21 
22 namespace nw {
23 namespace snd {
24 namespace internal {
25 namespace driver {
26 
27 /* ========================================================================
28         public function
29    ======================================================================== */
30 
31 /*---------------------------------------------------------------------------*
32   Name:         MidiSequencePlayer
33 
34   Description:  コンストラクタ
35 
36   Arguments:    None.
37 
38   Returns:      None.
39  *---------------------------------------------------------------------------*/
MidiSequencePlayer()40 MidiSequencePlayer::MidiSequencePlayer()
41 {
42     for( int i = 0 ; i < NOTE_INFO_COUNT ; i++ ) {
43         m_NoteInfo[i].channel = NULL;
44     }
45 }
46 
~MidiSequencePlayer()47 MidiSequencePlayer::~MidiSequencePlayer()
48 {
49 }
50 
Start()51 void MidiSequencePlayer::Start()
52 {
53     SequenceSoundPlayer::Start();
54 
55     // 全てのトラックをOpenしないとトラックのチャンネルがUpdateされない
56     for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
57     {
58         SequenceTrack* track = GetPlayerTrack( trackNo );
59         if ( track == NULL ) continue;
60         track->Open();
61     }
62 }
63 
SendMessage(u8 status,u8 data1,u8 data2)64 void MidiSequencePlayer::SendMessage( u8 status, u8 data1, u8 data2 )
65 {
66     u8 channel = static_cast<u8>(status & 0x0f);
67 
68     switch ( status & 0xf0 )
69     {
70     case MIDI_MSG_NOTE_OFF:
71         NoteOff( channel, data1, data2 );
72         break;
73 
74     case MIDI_MSG_NOTE_ON:
75         if (data2 != 0)
76         {
77             NoteOn( channel, data1, data2 );
78         }
79         else
80         {
81             NoteOff( channel, data1, data2 );
82         }
83         break;
84 
85     case MIDI_MSG_POLY_KEY_PRESSURE:
86         break;
87 
88     case MIDI_MSG_CONTROL_CHANGE:
89         if ( data1 < 120 )
90         {
91             HandleControlChangeMessage( channel, data1, data2 );
92         }
93         else
94         {
95             HandleChannelModeMessage( data1, data2 );
96         }
97         break;
98 
99     case MIDI_MSG_PROGRAM_CHANGE:
100         HandleProgramChangeMessage( channel, data1 );
101         break;
102 
103     case MIDI_MSG_CHANNEL_PRESSURE:
104         break;
105 
106     case MIDI_MSG_PITCH_BEND:
107         HandlePitchBendMessage( channel, data1, data2 );
108         break;
109 
110     case MIDI_MSG_SYSTEM:
111         switch (status)
112         {
113         case 0xfe:                    // active sencing
114             break;
115         case 0xff:                    // reset
116             Reset();
117             break;
118         }
119         break;
120     }
121 }
122 
SetProgramNumber(int channelIndex,int prgNo)123 void MidiSequencePlayer::SetProgramNumber( int channelIndex, int prgNo )
124 {
125     SequenceTrack* track = GetPlayerTrack( channelIndex );
126     track->GetParserTrackParam().prgNo = prgNo;
127 }
128 
NoteOn(u8 channelIndex,u8 key,u8 velocity)129 void MidiSequencePlayer::NoteOn( u8 channelIndex, u8 key, u8 velocity )
130 {
131     SequenceTrack* track = GetPlayerTrack( channelIndex );
132     if ( track == NULL ) return;
133 
134     SequenceTrack::ParserTrackParam& trackParam = track->GetParserTrackParam();
135 
136     key = static_cast<u8>( ut::Clamp( key + trackParam.transpose, 0, 127 ) );
137 
138     if ( trackParam.monophonicFlag )
139     {
140         NoteInfo* noteInfo = FindNoteInfo( channelIndex );
141         if ( noteInfo != NULL )
142         {
143             Channel* channel = noteInfo->channel;
144             if ( ! channel->IsRelease() )
145             {
146                 channel->SetKey( key );
147                 float initVolume = static_cast<float>( velocity ) / 127.0f;
148                 channel->SetInitVolume( initVolume * initVolume );
149                 noteInfo->key = key;
150                 return;
151             }
152             channel->Stop();
153             noteInfo->channel = NULL;
154         }
155     }
156 
157     Channel* channel = track->NoteOn( key, velocity, -1, false );
158     if ( channel == NULL ) return;
159 
160     NoteInfo* noteInfo = FindFreeNoteInfo();
161     NW_NULL_ASSERT( noteInfo );
162 
163     noteInfo->channel = channel;
164     noteInfo->channelIndex = channelIndex;
165     noteInfo->key = key;
166 }
167 
NoteOff(u8 channelIndex,u8 key,u8 velocity)168 void MidiSequencePlayer::NoteOff( u8 channelIndex, u8 key, u8 velocity )
169 {
170     (void)velocity;
171 
172     SequenceTrack* track = GetPlayerTrack( channelIndex );
173     if ( track == NULL ) return;
174     SequenceTrack::ParserTrackParam& param = track->GetParserTrackParam();
175 
176     key = static_cast<u8>( ut::Clamp( key + param.transpose, 0, 127 ) );
177 
178     while( 1 )
179     {
180         NoteInfo* noteInfo = FindNoteInfo( channelIndex, key );
181         if ( noteInfo == NULL ) break;
182 
183         noteInfo->channel->SetLength( 0 );
184         track->UpdateChannelRelease( noteInfo->channel );
185         noteInfo->channel = NULL;
186     }
187 }
188 
HandleControlChangeMessage(u8 channelIndex,u8 control,u8 value)189 void MidiSequencePlayer::HandleControlChangeMessage( u8 channelIndex, u8 control, u8 value )
190 {
191     SequenceTrack* track = GetPlayerTrack( channelIndex );
192     if ( track == NULL ) return;
193     SequenceSoundPlayer* player = track->GetSequenceSoundPlayer();
194     if ( player == NULL ) return;
195 
196     SequenceTrack::ParserTrackParam& param = track->GetParserTrackParam();
197     SequenceSoundPlayer::ParserPlayerParam& playerParam = player->GetParserPlayerParam();
198 
199     switch ( control )
200     {
201     case MIDI_CTRLCHG_BANK_SELECT:
202         param.bankIndex = value;
203         break;
204     case MIDI_CTRLCHG_MOD_DEPTH:
205         param.lfoParam.depth = value / 128.0f;
206         break;
207     case MIDI_CTRLCHG_INIT_PAN:
208         param.initPan = static_cast<s8>(value - 64);
209         break;
210     case MIDI_CTRLCHG_PORTA_TIME:
211         param.portaTime = value;
212         break;
213     case MIDI_CTRLCHG_DATA_ENTRY:
214         switch ( m_ParameterControlInfo[ channelIndex ].mode )
215         {
216         case ParameterControlInfo::RPN:
217             HandleRpnMessage( channelIndex, value );
218             break;
219         case ParameterControlInfo::NRPN:
220             HandleNrpnMessage( channelIndex, value );
221             break;
222         }
223         break;
224     case MIDI_CTRLCHG_VOLUME:
225         param.volume.SetTarget( value, 0 );
226         break;
227 #ifdef NW_PLATFORM_RVL
228     case MIDI_CTRLCHG_SPAN:
229         param.surroundPan.SetTarget( static_cast<s8>(value), 0 );
230         break;
231 #endif
232     case MIDI_CTRLCHG_PAN:
233         param.pan.SetTarget( static_cast<s8>(value - 64), 0 );
234         break;
235     case MIDI_CTRLCHG_EXPRESSION:
236         param.volume2 = value;
237         break;
238     case MIDI_CTRLCHG_MAIN_VOLUME:
239         playerParam.volume = value;
240         break;
241     case MIDI_CTRLCHG_TRANSPOSE:
242         param.transpose = static_cast<s8>(value - 64);
243         break;
244     case MIDI_CTRLCHG_PRIORITY:
245         param.priority = value;
246         break;
247     case MIDI_CTRLCHG_SETVAR_0:
248     case MIDI_CTRLCHG_SETVAR_1:
249     case MIDI_CTRLCHG_SETVAR_2:
250     case MIDI_CTRLCHG_SETVAR_3:
251         track->SetTrackVariable( control - MIDI_CTRLCHG_SETVAR_0, value );
252         break;
253 
254     case MIDI_CTRLCHG_BEND_RANGE:
255         param.bendRange = value;
256         break;
257     case MIDI_CTRLCHG_MOD_SPEED:
258         param.lfoParam.speed = value * 0.390625f;
259         break;
260     case MIDI_CTRLCHG_MOD_TYPE:
261         param.lfoTarget = value;
262         break;
263     case MIDI_CTRLCHG_MOD_RANGE:
264         param.lfoParam.range = value;
265         break;
266     case MIDI_CTRLCHG_BIQUAD_TYPE:
267         param.biquadType = value;
268         break;
269     case MIDI_CTRLCHG_BIQUAD_VALUE:
270         param.biquadValue = static_cast<f32>( value ) / 127.0f;
271         break;
272     case MIDI_CTRLCHG_MOD_DELAY:
273         param.lfoParam.delay = static_cast<u32>( value * 5 );
274         break;
275     case MIDI_CTRLCHG_MOD_DELAY_10:
276         param.lfoParam.delay = static_cast<u32>( (value * 5) * 10 );
277         break;
278     case MIDI_CTRLCHG_SWEEP_PITCH:
279         param.sweepPitch = (value - 64) / 64.0f;
280         break;
281     case MIDI_CTRLCHG_SWEEP_PITCH_24:
282         param.sweepPitch = (value - 64) / 64.0f * 24;
283         break;
284     case MIDI_CTRLCHG_DAMPER:
285         param.damperFlag = (value >= 64) ? true : false;
286         break;
287     case MIDI_CTRLCHG_PORTA:
288         param.portaFlag = (value >= 64) ? true : false;
289         break;
290     case MIDI_CTRLCHG_MONOPHONIC:
291         param.monophonicFlag = (value >= 64) ? true : false;
292         if ( param.monophonicFlag )
293         {
294             NoteOffAll();
295         }
296         break;
297     case MIDI_CTRLCHG_CUTOFF:
298         param.lpfFreq = static_cast<f32>( value - 64 ) / 64.0f;
299         break;
300     case MIDI_CTRLCHG_PORTA_CONTROL:
301         param.portaKey = static_cast<u8>(value + param.transpose);
302         param.portaFlag = true;
303         break;
304     case MIDI_CTRLCHG_ATTACK:
305         param.attack = value;
306         break;
307     case MIDI_CTRLCHG_DECAY:
308         param.decay = value;
309         break;
310     case MIDI_CTRLCHG_SUSTAIN:
311         param.sustain = value;
312         break;
313     case MIDI_CTRLCHG_RELEASE:
314         param.release = value;
315         break;
316     case MIDI_CTRLCHG_ENV_HOLD:
317         param.envHold = value;
318         break;
319     case MIDI_CTRLCHG_FXSEND_A:
320         param.fxSend[ AUX_BUS_A ] = value;
321         break;
322     case MIDI_CTRLCHG_FXSEND_B:
323         param.fxSend[ AUX_BUS_B ] = value;
324         break;
325 #ifdef NW_PLATFORM_RVL
326     case MIDI_CTRLCHG_FXSEND_C:
327         param.fxSend[ AUX_BUS_C ] = value;
328         break;
329 #endif
330     case MIDI_CTRLCHG_MAINSEND:
331         param.mainSend = value;
332         break;
333     case MIDI_CTRLCHG_NRPN_LSB:
334         m_ParameterControlInfo[ channelIndex ].nrpnLsb = value;
335         m_ParameterControlInfo[ channelIndex ].mode = ParameterControlInfo::NRPN;
336         break;
337     case MIDI_CTRLCHG_NRPN_MSB:
338         m_ParameterControlInfo[ channelIndex ].nrpnMsb = value;
339         m_ParameterControlInfo[ channelIndex ].mode = ParameterControlInfo::NRPN;
340         break;
341     case MIDI_CTRLCHG_RPN_LSB:
342         m_ParameterControlInfo[ channelIndex ].rpnLsb = value;
343         m_ParameterControlInfo[ channelIndex ].mode = ParameterControlInfo::RPN;
344         break;
345     case MIDI_CTRLCHG_RPN_MSB:
346         m_ParameterControlInfo[ channelIndex ].rpnMsb = value;
347         m_ParameterControlInfo[ channelIndex ].mode = ParameterControlInfo::RPN;
348         break;
349     case MIDI_CTRLCHG_FRONTBYPASS:
350         param.frontBypassFlag = (value >= 64) ? true : false;
351         break;
352     }
353 }
354 
HandleRpnMessage(u8 channelIndex,u8 value)355 void MidiSequencePlayer::HandleRpnMessage( u8 channelIndex, u8 value )
356 {
357     int parameterNumber =
358         ( static_cast<int>( m_ParameterControlInfo[ channelIndex ].rpnMsb ) << 8 ) +
359         m_ParameterControlInfo[ channelIndex ].rpnLsb
360         ;
361 
362     SequenceTrack* track = GetPlayerTrack( channelIndex );
363     if ( track == NULL ) return;
364     SequenceSoundPlayer* player = track->GetSequenceSoundPlayer();
365     if ( player == NULL ) return;
366 
367     SequenceTrack::ParserTrackParam& param = track->GetParserTrackParam();
368     SequenceSoundPlayer::ParserPlayerParam& playerParam = player->GetParserPlayerParam();
369 
370     switch ( parameterNumber )
371     {
372     case MIDI_RPN_PITCHBEND_SENSITIVITY:
373         param.bendRange = value;
374         break;
375     case MIDI_RPN_NULL:
376         break;
377     }
378 }
379 
HandleNrpnMessage(u8 channelIndex,u8 value)380 void MidiSequencePlayer::HandleNrpnMessage( u8 channelIndex, u8 value )
381 {
382     int parameterNumber =
383         ( static_cast<int>( m_ParameterControlInfo[ channelIndex ].nrpnMsb ) << 8 ) +
384         m_ParameterControlInfo[ channelIndex ].nrpnLsb
385         ;
386 
387     SequenceTrack* track = GetPlayerTrack( channelIndex );
388     if ( track == NULL ) return;
389     SequenceSoundPlayer* player = track->GetSequenceSoundPlayer();
390     if ( player == NULL ) return;
391 
392     SequenceTrack::ParserTrackParam& param = track->GetParserTrackParam();
393     SequenceSoundPlayer::ParserPlayerParam& playerParam = player->GetParserPlayerParam();
394 
395     (void)value;
396 
397     switch ( parameterNumber )
398     {
399     case MIDI_NRPN_ENV_RESET:
400         param.attack = SequenceTrack::INVALID_ENVELOPE;
401         param.decay = SequenceTrack::INVALID_ENVELOPE;
402         param.sustain = SequenceTrack::INVALID_ENVELOPE;
403         param.release = SequenceTrack::INVALID_ENVELOPE;
404         param.envHold = SequenceTrack::INVALID_ENVELOPE;
405         break;
406     case MIDI_NRPN_NULL:
407         break;
408     }
409 }
410 
HandleChannelModeMessage(u8 control,u8 value)411 void MidiSequencePlayer::HandleChannelModeMessage( u8 control, u8 value )
412 {
413     (void)value;
414 
415     switch( control )
416     {
417     case MIDI_MODEMSG_ALL_SOUND_OFF:
418         StopAllSound();
419         break;
420     case MIDI_MODEMSG_RESET_ALL_CONTROLER:
421         ResetAllController();
422         break;
423     case MIDI_MODEMSG_LOCAL_CONTROL:
424         break;
425     case MIDI_MODEMSG_ALL_NOTE_OFF:
426         NoteOffAll();
427         break;
428     case MIDI_MODEMSG_OMNI_OFF:
429     case MIDI_MODEMSG_OMNI_ON:
430     case MIDI_MODEMSG_MONO_MODE:
431     case MIDI_MODEMSG_POLY_MODE:
432         break;
433     }
434 }
435 
HandleProgramChangeMessage(u8 channelIndex,u8 program)436 void MidiSequencePlayer::HandleProgramChangeMessage( u8 channelIndex, u8 program )
437 {
438     SetProgramNumber( channelIndex, program );
439 }
440 
HandlePitchBendMessage(u8 channelIndex,u8 lsb,u8 msb)441 void MidiSequencePlayer::HandlePitchBendMessage( u8 channelIndex, u8 lsb, u8 msb )
442 {
443     s16 value = static_cast<s16>( ((msb << 7) | lsb) - 0x2000 );
444     value >>= 6;
445 
446     SequenceTrack* track = GetPlayerTrack( channelIndex );
447     if ( track == NULL ) return;
448     SequenceTrack::ParserTrackParam& param = track->GetParserTrackParam();
449     param.pitchBend.SetTarget( static_cast<s8>(value), 0 );
450 }
451 
NoteOffAll()452 void MidiSequencePlayer::NoteOffAll()
453 {
454     for( int i = 0 ; i < NOTE_INFO_COUNT ; i++ ) {
455         if ( m_NoteInfo[i].channel != NULL )
456         {
457             m_NoteInfo[i].channel->Release();
458             m_NoteInfo[i].channel = NULL;
459         }
460     }
461 }
462 
StopAllSound()463 void MidiSequencePlayer::StopAllSound()
464 {
465     for( int i = 0 ; i < NOTE_INFO_COUNT ; i++ ) {
466         if ( m_NoteInfo[i].channel != NULL )
467         {
468             m_NoteInfo[i].channel = NULL;
469         }
470     }
471 
472     for ( int channelIndex = 0 ; channelIndex < TRACK_NUM_PER_PLAYER ; channelIndex++ ) {
473         SequenceTrack* track = GetPlayerTrack( channelIndex );
474         if ( track != NULL ) {
475             track->StopAllChannel();
476         }
477     }
478 }
479 
ResetAllController()480 void MidiSequencePlayer::ResetAllController()
481 {
482     for ( int channelIndex = 0 ; channelIndex < TRACK_NUM_PER_PLAYER ; channelIndex++ ) {
483         SequenceTrack* track = GetPlayerTrack( channelIndex );
484         if ( track != NULL ) {
485             track->InitParam();
486         }
487     }
488 }
489 
Reset()490 void MidiSequencePlayer::Reset()
491 {
492     for( int i = 0 ; i < NOTE_INFO_COUNT ; i++ ) {
493         if ( m_NoteInfo[i].channel != NULL )
494         {
495             m_NoteInfo[i].channel = NULL;
496         }
497     }
498 
499     for ( int channelIndex = 0 ; channelIndex < TRACK_NUM_PER_PLAYER ; channelIndex++ ) {
500         SequenceTrack* track = GetPlayerTrack( channelIndex );
501         if ( track != NULL ) {
502             track->StopAllChannel();
503             track->InitParam();
504         }
505     }
506 }
507 
FindFreeNoteInfo()508 MidiSequencePlayer::NoteInfo* MidiSequencePlayer::FindFreeNoteInfo()
509 {
510     for( int i = 0 ; i < NOTE_INFO_COUNT ; i++ ) {
511         if ( m_NoteInfo[i].channel == NULL ) {
512             return &m_NoteInfo[i];
513         }
514     }
515     return NULL;
516 }
517 
FindNoteInfo(int channelIndex,int key)518 MidiSequencePlayer::NoteInfo* MidiSequencePlayer::FindNoteInfo( int channelIndex, int key )
519 {
520     for( int i = 0 ; i < NOTE_INFO_COUNT ; i++ ) {
521         if ( m_NoteInfo[i].channel != NULL &&
522              m_NoteInfo[i].channelIndex == channelIndex &&
523              m_NoteInfo[i].key == key )
524         {
525             return &m_NoteInfo[i];
526         }
527     }
528     return NULL;
529 }
530 
FindNoteInfo(int channelIndex)531 MidiSequencePlayer::NoteInfo* MidiSequencePlayer::FindNoteInfo( int channelIndex )
532 {
533     for( int i = 0 ; i < NOTE_INFO_COUNT ; i++ ) {
534         if ( m_NoteInfo[i].channel != NULL &&
535              m_NoteInfo[i].channelIndex == channelIndex )
536         {
537             return &m_NoteInfo[i];
538         }
539     }
540     return NULL;
541 }
542 
ChannelCallback(Channel * channel)543 void MidiSequencePlayer::ChannelCallback( Channel* channel )
544 {
545     for( int i = 0 ; i < NOTE_INFO_COUNT ; i++ ) {
546         if ( m_NoteInfo[i].channel == channel ) {
547             m_NoteInfo[i].channel = NULL;
548         }
549     }
550 }
551 
552 } // namespace nw::snd::internal::driver
553 } // namespace nw::snd::internal
554 } // namespace nw::snd
555 } // namespace nw
556 
557