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