[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