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