⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miniport.cpp

📁 winddk src目录下的WDM源码压缩!
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                }
                break;
            } // if bVelocity.
            //NOTE: no break specified here. On an else case we want to continue through and turn key off

        case 0x80:
            /* turn key off */
            //  we don't care what the velocity is on note off
            if (bChannel == DRUMCHANNEL)
            {
                Opl3_NoteOff((BYTE) (bNote + 128),bNote, bChannel, 0);
            }
            else
            {
                Opl3_NoteOff ((BYTE) m_bPatch[bChannel],bNote, bChannel, m_bSustain[ bChannel ]);
            }
            break;

        case 0xb0:
            /* change control */
            switch (bNote) 
            {
                case 7:
                    /* change channel volume */
                    Opl3_ChannelVolume(bChannel,gbVelocityAtten[bVelocity >> 1]);
                    break;

                case 8:
                case 10:
                    /* change the pan level */
                    Opl3_SetPan(bChannel, bVelocity);
                    break;

                case 64:
                    /* Change the sustain level */
                    Opl3_SetSustain(bChannel, bVelocity);
                    break;

                default:
                    if (bNote >= 120)        /* Channel mode messages */
                    {
                        Opl3_ChannelNotesOff(bChannel);
                    }
                    //  else unknown controller
            };
            break;

        case 0xc0:
            if (bChannel != DRUMCHANNEL)
            {
               m_bPatch[ bChannel ] = bNote ;

            }
            break;

        case 0xe0:  // pitch bend
            wTemp = ((WORD) bVelocity << 9) | ((WORD) bNote << 2);
            m_iBend[bChannel] = (short) (WORD) (wTemp + 0x8000);
            Opl3_PitchBend(bChannel, m_iBend[bChannel]);

            break;
    };
    KeReleaseSpinLock(&m_Miniport->m_SpinLock,oldIrql);
    
    return;
}

// ========================= opl3 specific methods ============================
#pragma code_seg()
// ==========================================================================
// Opl3_AllNotesOff - turn off all notes
// ==========================================================================
void 
CMiniportMidiStreamFM::
Opl3_AllNotesOff()
{
    BYTE i;
    KIRQL   oldIrql;

    KeAcquireSpinLock(&m_Miniport->m_SpinLock,&oldIrql);
    for (i = 0; i < NUM2VOICES; i++) 
    {
        Opl3_NoteOff(m_Voice[i].bPatch, m_Voice[i].bNote, m_Voice[i].bChannel, 0);
    }
    KeReleaseSpinLock(&m_Miniport->m_SpinLock,oldIrql);
}

#pragma code_seg()
// ==========================================================================
//  void Opl3_NoteOff
//
//  Description:
//     This turns off a note, including drums with a patch
//     # of the drum note + 128, but the first drum instrument is at MIDI note _35_.
//
//  Parameters:
//     BYTE bPatch
//        MIDI patch
//
//     BYTE bNote
//        MIDI note
//
//     BYTE bChannel
//        MIDI channel
//
//  Return Value:
//     Nothing.
//
//
// ==========================================================================
void 
CMiniportMidiStreamFM::
Opl3_NoteOff
(
    BYTE            bPatch,
    BYTE            bNote,
    BYTE            bChannel,
    BYTE            bSustain
)
{
   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

   patchStruct FAR  *lpPS ;
   WORD             wOffset, wTemp ;

   // Find the note slot
   wTemp = Opl3_FindFullSlot( bNote, bChannel ) ;

   if (wTemp != 0xffff)
   {
      if (bSustain)
      {
          // This channel is sustained, don't really turn the note off,
          // just flag it.
          //
          m_Voice[ wTemp ].bSusHeld = 1;
          
          return;
      }
      
      // get a pointer to the patch
      lpPS = glpPatch + (BYTE) m_Voice[ wTemp ].bPatch ;

      // shut off the note portion
      // we have the note slot, turn it off.
      wOffset = wTemp;
      if (wTemp >= (NUM2VOICES / 2))
         wOffset += (0x100 - (NUM2VOICES / 2));

      m_Miniport->SoundMidiSendFM(m_PortBase, AD_BLOCK + wOffset,
                  (BYTE)(m_Voice[ wTemp ].bBlock[ 0 ] & 0x1f) ) ;

      // Note this...
      m_Voice[ wTemp ].bOn = FALSE ;
      m_Voice[ wTemp ].bBlock[ 0 ] &= 0x1f ;
      m_Voice[ wTemp ].bBlock[ 1 ] &= 0x1f ;
      m_Voice[ wTemp ].dwTime = m_dwCurTime ;
   }
}

#pragma code_seg()
// ==========================================================================
//  WORD Opl3_FindFullSlot
//
//  Description:
//     This finds a slot with a specific note, and channel.
//     If it is not found then 0xFFFF is returned.
//
//  Parameters:
//     BYTE bNote
//        MIDI note number
//
//     BYTE bChannel
//        MIDI channel #
//
//  Return Value:
//     WORD
//        note slot #, or 0xFFFF if can't find it
//
//
// ==========================================================================
WORD 
CMiniportMidiStreamFM::
Opl3_FindFullSlot
(
    BYTE            bNote,
    BYTE            bChannel
)
{
   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

   WORD  i ;

   for (i = 0; i < NUM2VOICES; i++)
   {
      if ((bChannel == m_Voice[ i ].bChannel) 
            && (bNote == m_Voice[ i ].bNote) 
            && (m_Voice[ i ].bOn))
      {
            return ( i ) ;
      }
   // couldn't find it
   }
   return ( 0xFFFF ) ;
} 


#pragma code_seg()
//------------------------------------------------------------------------
//  void Opl3_FMNote
//
//  Description:
//     Turns on an FM-synthesizer note.
//
//  Parameters:
//     WORD wNote
//        the note number from 0 to NUMVOICES
//
//     noteStruct FAR *lpSN
//        structure containing information about what
//        is to be played.
//
//  Return Value:
//     Nothing.
//------------------------------------------------------------------------
void 
CMiniportMidiStreamFM::
Opl3_FMNote
(
    WORD                wNote,
    noteStruct FAR *    lpSN
)
{
   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

   WORD            i ;
   WORD            wOffset ;
   operStruct FAR  *lpOS ;

   // write out a note off, just to make sure...

   wOffset = wNote;
   if (wNote >= (NUM2VOICES / 2))
      wOffset += (0x100 - (NUM2VOICES / 2));

   m_Miniport->SoundMidiSendFM(m_PortBase, AD_BLOCK + wOffset, 0 ) ;

   // writing the operator information

//   for (i = 0; i < (WORD)((wNote < NUM4VOICES) ? NUMOPS : 2); i++)
   for (i = 0; i < 2; i++)
   {
      lpOS = &lpSN -> op[ i ] ;
      wOffset = gw2OpOffset[ wNote ][ i ] ;
      m_Miniport->SoundMidiSendFM( m_PortBase, 0x20 + wOffset, lpOS -> bAt20) ;
      m_Miniport->SoundMidiSendFM( m_PortBase, 0x40 + wOffset, lpOS -> bAt40) ;
      m_Miniport->SoundMidiSendFM( m_PortBase, 0x60 + wOffset, lpOS -> bAt60) ;
      m_Miniport->SoundMidiSendFM( m_PortBase, 0x80 + wOffset, lpOS -> bAt80) ;
      m_Miniport->SoundMidiSendFM( m_PortBase, 0xE0 + wOffset, lpOS -> bAtE0) ;

   }

   // write out the voice information
   wOffset = (wNote < 9) ? wNote : (wNote + 0x100 - 9) ;
   m_Miniport->SoundMidiSendFM(m_PortBase, 0xa0 + wOffset, lpSN -> bAtA0[ 0 ] ) ;
   m_Miniport->SoundMidiSendFM(m_PortBase, 0xc0 + wOffset, lpSN -> bAtC0[ 0 ] ) ;

   // Note on...
   m_Miniport->SoundMidiSendFM(m_PortBase, 0xb0 + wOffset,
               (BYTE)(lpSN -> bAtB0[ 0 ] | 0x20) ) ;

} // end of Opl3_FMNote()

#pragma code_seg()
//=======================================================================
//  WORD Opl3_NoteOn
//
//  Description:
//     This turns on a note, including drums with a patch # of the
//     drum note + 0x80.  The first GM drum instrument is mapped to note 35 instead of zero, though, so
//     we expect 0 as the first drum patch (acoustic kick) if note 35 comes in.
//
//  Parameters:
//     BYTE bPatch
//        MIDI patch
//
//     BYTE bNote
//        MIDI note
//
//     BYTE bChannel
//        MIDI channel
//
//     BYTE bVelocity
//        velocity value
//
//     short iBend
//        current pitch bend from -32768 to 32767
//
//  Return Value:
//     WORD
//        note slot #, or 0xFFFF if it is inaudible
//=======================================================================
void 
CMiniportMidiStreamFM::
Opl3_NoteOn
(
    BYTE            bPatch,
    BYTE            bNote,
    BYTE            bChannel,
    BYTE            bVelocity,
    short           iBend
)
{
   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

   WORD             wTemp, i, j ;
   BYTE             b4Op, bTemp, bMode, bStereo ;
   patchStruct FAR  *lpPS ;
   DWORD            dwBasicPitch, dwPitch[ 2 ] ;
   noteStruct       NS ;

   // Get a pointer to the patch
   lpPS = glpPatch + bPatch ;

   // Find out the basic pitch according to our
   // note value.  This may be adjusted because of
   // pitch bends or special qualities for the note.

   dwBasicPitch = gdwPitch[ bNote % 12 ] ;
   bTemp = bNote / (BYTE) 12 ;
   if (bTemp > (BYTE) (60 / 12))
      dwBasicPitch = AsLSHL( dwBasicPitch, (BYTE)(bTemp - (BYTE)(60/12)) ) ;
   else if (bTemp < (BYTE) (60/12))
      dwBasicPitch = AsULSHR( dwBasicPitch, (BYTE)((BYTE) (60/12) - bTemp) ) ;

   // Copy the note information over and modify
   // the total level and pitch according to
   // the velocity, midi volume, and tuning.

   RtlCopyMemory( (LPSTR) &NS, (LPSTR) &lpPS -> note, sizeof( noteStruct ) ) ;
   b4Op = (BYTE)(NS.bOp != PATCH_1_2OP) ;

   for (j = 0; j < 2; j++)
   {
      // modify pitch
      dwPitch[ j ] = dwBasicPitch ;
      bTemp = (BYTE)((NS.bAtB0[ j ] >> 2) & 0x07) ;
      if (bTemp > 4)
         dwPitch[ j ] = AsLSHL( dwPitch[ j ], (BYTE)(bTemp - (BYTE)4) ) ;
      else if (bTemp < 4)
         dwPitch[ j ] = AsULSHR( dwPitch[ j ], (BYTE)((BYTE)4 - bTemp) ) ;

      wTemp = Opl3_CalcFAndB( Opl3_CalcBend( dwPitch[ j ], iBend ) ) ;
      NS.bAtA0[ j ] = (BYTE) wTemp ;
      NS.bAtB0[ j ] = (BYTE) 0x20 | (BYTE) (wTemp >> 8) ;
   }

   // Modify level for each operator, but only
   // if they are carrier waves

   bMode = (BYTE) ((NS.bAtC0[ 0 ] & 0x01) * 2 + 4) ;

   for (i = 0; i < 2; i++)
   {
      wTemp = (BYTE) 
          Opl3_CalcVolume(  (BYTE)(NS.op[ i ].bAt40 & (BYTE) 0x3f),
                            bChannel, 
                            bVelocity, 
                            (BYTE) i, 
                            bMode ) ;
      NS.op[ i ].bAt40 = (NS.op[ i ].bAt40 & (BYTE)0xc0) | (BYTE) wTemp ;
   }

   // Do stereo panning, but cutting off a left or
   // right channel if necessary...

   bStereo = Opl3_CalcStereoMask( bChannel ) ;
   NS.bAtC0[ 0 ] &= bStereo ;

   // Find an empty slot, and use it...
   wTemp = Opl3_FindEmptySlot( bPatch ) ;

   Opl3_FMNote(wTemp, &NS ) ;
   m_Voice[ wTemp ].bNote = bNote ;
   m_Voice[ wTemp ].bChannel = bChannel ;
   m_Voice[ wTemp ].bPatch = bPatch ;
   m_Voice[ wTemp ].bVelocity = bVelocity ;
   m_Voice[ wTemp ].bOn = TRUE ;
   m_Voice[ wTemp ].dwTime = m_dwCurTime++ ;
   m_Voice[ wTemp ].dwOrigPitch[0] = dwPitch[ 0 ] ;  // not including bend
   m_Voice[ wTemp ].dwOrigPitch[1] = dwPitch[ 1 ] ;  // not including bend
   m_Voice[ wTemp ].bBlock[0] = NS.bAtB0[ 0 ] ;
   m_Voice[ wTemp ].bBlock[1] = NS.bAtB0[ 1 ] ;
   m_Voice[ wTemp ].bSusHeld = 0;


} // end of Opl3_NoteOn()

#pragma code_seg()
//=============================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -