[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    extragear/multimedia/kmid/win
From:       Pedro Lopez-Cabanillas <pedro.lopez.cabanillas () gmail ! com>
Date:       2010-04-11 11:02:07
Message-ID: 20100411110207.BBE13AC894 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1113634 by pedrol:

Windows MIDI backend: implemented mapper transformations

 M  +159 -59   winmidioutput.cpp  
 M  +4 -1      winmidioutput.h  


--- trunk/extragear/multimedia/kmid/win/winmidioutput.cpp #1113633:1113634
@@ -24,12 +24,19 @@
 #include <QStringList>
 #include <QByteArray>
 #include <QVarLengthArray>
+#include <qmath.h>
 
 #include <windows.h>
 #include <mmsystem.h>
 
 namespace KMid {
 
+    union WinMIDIPacket {
+        WinMIDIPacket() : dwPacket(0) {};
+        DWORD dwPacket;
+        quint8 data[sizeof(DWORD)];
+    };
+
     class WinMIDIOutput::WinMIDIOutputPrivate {
     public:
         WinMIDIOutputPrivate():
@@ -54,9 +61,14 @@
 
         void close()
         {
+            MMRESULT result;
             if (m_outHandle != NULL) {
-                midiOutReset( m_outHandle );
-                midiOutClose( m_outHandle );
+                result = midiOutReset( m_outHandle );
+                if (result != MMSYSERR_NOERROR)
+                    kDebug() << "midiOutReset() err:" << result;
+                result = midiOutClose( m_outHandle );
+                if (result != MMSYSERR_NOERROR)
+                    kDebug() << "midiOutClose() err:" << result;
                 m_outHandle = NULL;
             }
         }
@@ -70,16 +82,109 @@
             close();
             result = midiOutOpen( &m_outHandle, device,
                                   NULL, NULL, CALLBACK_NULL );
+            if (result != MMSYSERR_NOERROR)
+                kDebug() << "midiOutOpen() err:" << result;
             return (result == MMSYSERR_NOERROR);
         }
 
+        void transformControllerEvent(WinMIDIPacket *packet)
+        {
+            int param = packet->data[1];
+            if (m_mapper != NULL && m_mapper->isOK()) {
+                param = m_mapper->controller(param);
+                if (param >= 0 && param < 128)
+                    packet->data[1] = param;
+            }
+            if (param == MIDI_CTL_MSB_MAIN_VOLUME) {
+                int chan = packet->data[0] & 0x0f;
+                int value = packet->data[2];
+                m_volume[chan] = value;
+                value = floor(value * m_volumeShift[chan]);
+                if (value < 0) value = 0;
+                if (value > 127) value = 127;
+                packet->data[2] = value;
+            }
+        }
+
+        void transformNoteEvent(WinMIDIPacket *packet)
+        {
+            int note, channel;
+            channel = packet->data[0] & 0x0f;
+            note = packet->data[1];
+            if (channel != MIDI_GM_DRUM_CHANNEL) {
+                note += m_pitchShift;
+                while (note > 127) note -= 12;
+                while (note < 0) note += 12;
+                packet->data[1] = note;
+            } else if (m_mapper != NULL && m_mapper->isOK()) {
+                note = m_mapper->key( channel,
+                                      m_lastpgm[channel],
+                                      note );
+                if (note >= 0 && note < 128)
+                    packet->data[1] = note;
+            }
+        }
+
+        void transformProgramEvent(WinMIDIPacket *packet)
+        {
+            if (m_mapper != NULL && m_mapper->isOK()) {
+                int channel = packet->data[0] & 0x0f;
+                m_lastpgm[channel] = packet->data[1];
+                int pgm = m_mapper->patch(channel, m_lastpgm[channel]);
+                if (pgm >= 0 && pgm < 128)
+                    packet->data[1] = pgm;
+            }
+        }
+
+        void transformPitchBendEvent(WinMIDIPacket *packet)
+        {
+            if (m_mapper != NULL && m_mapper->isOK()) {
+                int value = (packet->data[1] + packet->data[2] * 128) - 8192;
+                value = m_mapper->pitchBender(value);
+                if (value < -8192) value = -8192;
+                if (value > 8191) value = 8191;
+                quint16 newval = value + 8192;
+                packet->data[1] = newval % 0x80;
+                packet->data[2] = newval / 0x80;
+            }
+        }
+
+        void transform(WinMIDIPacket *packet)
+        {
+            quint8 status = packet->data[0] & 0xf0;
+            quint8 chan = packet->data[0] & 0x0f;
+            switch ( status ) {
+            case MIDI_STATUS_CONTROLCHANGE:
+                transformControllerEvent(packet);
+                break;
+            case MIDI_STATUS_NOTEOFF:
+            case MIDI_STATUS_NOTEON:
+                transformNoteEvent(packet);
+                break;
+            case MIDI_STATUS_PROGRAMCHANGE:
+                transformProgramEvent(packet);
+                break;
+            case MIDI_STATUS_PITCHBEND:
+                transformPitchBendEvent(packet);
+                break;
+            default:
+                break;
+            }
+            if ( status >= MIDI_STATUS_NOTEOFF &&
+                 status <  MIDI_STATUS_SYSEX &&
+                 m_mapper != NULL && m_mapper->isOK() ) {
+                int channel = m_mapper->channel(chan);
+                if (channel >= 0 && channel < MIDI_CHANNELS)
+                    packet->data[0] = status + channel;
+            }
+        }
+
         HMIDIOUT m_outHandle;
         MidiMapper *m_mapper;
         int m_pitchShift;
         bool m_clientFilter;
         QString m_currentOutput;
         QStringList m_outputDevices;
-
         int m_lastpgm[MIDI_CHANNELS];
         qreal m_volumeShift[MIDI_CHANNELS];
         int m_volume[MIDI_CHANNELS];
@@ -283,92 +388,87 @@
             sendSysexEvent(d->m_resetMessage);
     }
 
-    void WinMIDIOutput::sendShortMessage(uchar *msg, int len)
+    void WinMIDIOutput::sendShortMessage(WinMIDIPacket* packet)
     {
         MMRESULT res;
-        DWORD packet = 0;
-        uchar* ptr = reinterpret_cast<uchar*>(&packet);
-        for ( int i=0; i<len; ++i )
-            ptr[i] = msg[i];
-        res = midiOutShortMsg( d->m_outHandle, packet );
-        //return ( res == MMSYSERR_NOERROR );
+        quint8 status;
+        quint8 chan;
+        bool ok;
+        d->transform(packet);
+        status = packet->data[0] & 0xf0;
+        chan = packet->data[0] & 0x0f;
+        ok = ( status >= MIDI_STATUS_NOTEOFF ) &&
+             ( ( status == MIDI_STATUS_SYSEX ) |
+               ( status < MIDI_STATUS_SYSEX &&
+                 !d->m_muted[chan] ) );
+        if ( ok && status == MIDI_STATUS_PROGRAMCHANGE )
+            ok = !d->m_locked[chan];
+        if (ok) {
+            res = midiOutShortMsg( d->m_outHandle, packet->dwPacket );
+            if ( res != MMSYSERR_NOERROR )
+                kDebug() << "midiOutShortMsg() err:" << res;
+        }
     }
 
     void WinMIDIOutput::sendNoteOn(int chan, int note, int vel)
     {
-        uchar data[3];
-        if ( d->m_muted[chan] )
-            return;
-        data[0] = MIDI_STATUS_NOTEON | (chan & 0x0f);
-        data[1] = note;
-        data[2] = vel;
-        sendShortMessage(&data[0], sizeof(data));
+        WinMIDIPacket packet;
+        packet.data[0] = MIDI_STATUS_NOTEON | (chan & 0x0f);
+        packet.data[1] = note;
+        packet.data[2] = vel;
+        sendShortMessage(&packet);
     }
 
     void WinMIDIOutput::sendNoteOff(int chan, int note, int vel)
     {
-        uchar data[3];
-        if ( d->m_muted[chan] )
-            return;
-        data[0] = MIDI_STATUS_NOTEOFF | (chan & 0x0f);
-        data[1] = note;
-        data[2] = vel;
-        sendShortMessage(&data[0], sizeof(data));
+        WinMIDIPacket packet;
+        packet.data[0] = MIDI_STATUS_NOTEOFF | (chan & 0x0f);
+        packet.data[1] = note;
+        packet.data[2] = vel;
+        sendShortMessage(&packet);
     }
 
     void WinMIDIOutput::sendController(int chan, int control, int value)
     {
-        uchar data[3];
-        if ( d->m_muted[chan] )
-            return;
-        data[0] = MIDI_STATUS_CONTROLCHANGE | (chan & 0x0f);
-        data[1] = control;
-        data[2] = value;
-        sendShortMessage(&data[0], sizeof(data));
+        WinMIDIPacket packet;
+        packet.data[0] = MIDI_STATUS_CONTROLCHANGE | (chan & 0x0f);
+        packet.data[1] = control;
+        packet.data[2] = value;
+        sendShortMessage(&packet);
     }
 
     void WinMIDIOutput::sendKeyPressure(int chan, int note, int value)
     {
-        uchar data[3];
-        if ( d->m_muted[chan] )
-            return;
-        data[0] = MIDI_STATUS_KEYPRESURE | (chan & 0x0f);
-        data[1] = note;
-        data[2] = value;
-        sendShortMessage(&data[0], sizeof(data));
+        WinMIDIPacket packet;
+        packet.data[0] = MIDI_STATUS_KEYPRESURE | (chan & 0x0f);
+        packet.data[1] = note;
+        packet.data[2] = value;
+        sendShortMessage(&packet);
     }
 
     void WinMIDIOutput::sendProgram(int chan, int program)
     {
-        uchar data[2];
-        if ( d->m_muted[chan] )
-            return;
-        if ( d->m_locked[chan] )
-            return;
-        data[0] = MIDI_STATUS_PROGRAMCHANGE | (chan & 0x0f);
-        data[1] = program;
-        sendShortMessage(&data[0], sizeof(data));
+        WinMIDIPacket packet;
+        packet.data[0] = MIDI_STATUS_PROGRAMCHANGE | (chan & 0x0f);
+        packet.data[1] = program;
+        sendShortMessage(&packet);
     }
 
     void WinMIDIOutput::sendChannelPressure(int chan, int value)
     {
-        uchar data[2];
-        if ( d->m_muted[chan] )
-            return;
-        data[0] = MIDI_STATUS_CHANNELPRESSURE | (chan & 0x0f);
-        data[1] = value;
-        sendShortMessage(&data[0], sizeof(data));
+        WinMIDIPacket packet;
+        packet.data[0] = MIDI_STATUS_CHANNELPRESSURE | (chan & 0x0f);
+        packet.data[1] = value;
+        sendShortMessage(&packet);
     }
 
     void WinMIDIOutput::sendPitchBend(int chan, int value)
     {
-        uchar data[3];
-        if ( d->m_muted[chan] )
-            return;
-        data[0] = MIDI_STATUS_PITCHBEND | (chan & 0x0f);
-        data[1] = value % 0x80; // LSB
-        data[2] = value / 0x80; // MSB
-        sendShortMessage(&data[0], sizeof(data));
+        WinMIDIPacket packet;
+        packet.data[0] = MIDI_STATUS_PITCHBEND | (chan & 0x0f);
+        packet.data[1] = value % 0x80; // LSB
+        packet.data[2] = value / 0x80; // MSB
+        sendShortMessage(&packet);
     }
 
     void WinMIDIOutput::sendSysexEvent(const QByteArray& data)
--- trunk/extragear/multimedia/kmid/win/winmidioutput.h #1113633:1113634
@@ -36,6 +36,9 @@
 #define MIDI_STATUS_MASK            0x80
 
 namespace KMid {
+
+    union WinMIDIPacket;
+
     class WinMIDIOutput : public MIDIOutput
     {
         Q_OBJECT
@@ -51,7 +54,7 @@
         virtual bool isMuted(int channel) const;
         virtual MidiMapper* midiMap();
         virtual int pitchShift();
-        void sendShortMessage(uchar *msg, int len);
+        void sendShortMessage(WinMIDIPacket* msg);
 
     public Q_SLOTS:
         void setVolume(int channel, qreal);
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic