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