|
|||||||
![]() |
|
|
LinkBack | Thread Tools |
|
|
#1 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
midi port in c++
hi all,
since i made a lot of tests with my dsp synthesizer and the audigys soundfont sampler, i asked me, how good an own midi input could be in c++. i mean, what can i expect? (before i start working on it) actually the midi timing feels like a chewing rubber. i know that there ever were midi timing problems in kx (in contrast to the original creative drivers) but i hope there is a way to improve this. thanks, stylus |
|
|
|
|
|
#2 | |
|
DH Senior Member
Join Date: Jan 2003
Location: The Netherlands
Posts: 1,879
Rep Power: 48 ![]() ![]() ![]() ![]() |
?? I already answered that here;
log_dane, exp_dane in c++ Quote:
There is a "soundfont attack" issue and a "sysex issue" but "kX MIDI IN Port" works just as fine as Creative driver. As I already explained before; "KX MIDI Automation" is to slow for your application, but opening "kX MIDI IN Port" (or any other midi port) through WMM API works fast enough for triggering synths. However, if you want to playback from a sequencer, you must install MidiYoke's virtual midi port. (kinda same as Hubi's). Such virtual midi ports add overhead so timing may suffer on busy sequences. |
|
|
|
|
|
|
#3 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
hi lex,
a thread on midi timing could interest many people. we have now a few instruments running on our cards and it's called "toy's are us". the emu dsp is a 32 bit audio processor. the audio signal processing capabilities are "state of the art". i can't agree with a designation "toy". ok, you have made a midi port in c++ for your synths and it's usable for triggering from external sequencers. that's what i wanted to hear. virtual midi routing like hubi's stuff is widely accepted by musicians. thus I can live. ![]() stylus |
|
|
|
|
|
#4 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
time for questions.
i tried out a low level midi callback function written in "c". (Low Level MIDI API) it returns short (notes, controller, pitch..) and long midi messages (sysex) from a midi input. quite good.. but how do i set dsp registers with these values? let's say there is a hex value for midi databyte 1 (note) and it should be written to dsp register "DATA_01_P" to process in a plugin. stylus |
|
|
|
|
|
#5 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
With the set_dsp_register function from the kX SDK (but I suspect you already know this, so I am unsure what you are really asking).
Last edited by Russ; May 6, 2008 at 11:08 AM. |
|
|
|
|
|
#6 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
yes i know, but it doesn't work.
void abc () { set_dsp_register(DATA_01_P, 0xccccccc); // 0.1 or any value } error C2065: 'set_dsp_register' : undeclared identifier
__________________
http://freenet-homepage.de/stylish-s...xas/index.html |
|
|
|
|
|
#7 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
Did you include the kX SDK headers (see stdafx.h from the demo plugin for the typical includes for a plugin), and link with the kX libs (kxapi.lib and kxgui.lib [COLOR=Gray](if you are using the kxgui API)[/COLOR])?
BTW: You should also add the \h and \lib directories (from the kX SDK) to your project. Last edited by Russ; May 6, 2008 at 11:37 AM. |
|
|
|
|
|
#8 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
i used the demo.dsw with modification.
here is the myname.cpp: #include "stdafx.h" #include "myname.h" #include "da_myname.cpp" // Get DSP Microcode //---------------------------------------------------- int imynamePlugin::request_microcode() { { publish_microcode(myname); // ? don't understood } return 0; } // plugin description //-------------------------------------------------- char *imynamePlugin::get_plugin_description(int id) { plugin_description(myname); } // set register //----------------------------------------------------- void abc () { set_dsp_register(DATA_01_P, 0xccccccc); // 0.1 or any value } the demo.cpp looks little different: ... int iDemoPlugin::set_param(int ndx, kxparam_t value) [COLOR=Teal]// member function?[/COLOR] { _params[ndx] = value; switch (ndx) { case VOL1_ID: // vol1 parameter directly corresponds to the vol1 DSP register [0x8002] set_dsp_register(VOL1_P, value); [COLOR=Teal]// i only want this [/COLOR]break; ...
__________________
http://freenet-homepage.de/stylish-s...xas/index.html |
|
|
|
|
|
#9 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
set_dsp_register is part of the plugin class, so you cannot call it from a global/static function.
I would probably do something like this instead: (psuedocode) Code:
// somewhere in your plugin code
midiInOpen(&m_hMidiIn, m_nPortMidiIn, (DWORD_PTR)MidiInProc, (DWORD_PTR)this, CALLBACK_FUNCTION); // pass plugin pointer to callback function
...
void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
CMyPlugin * pPlugin = (CMyPlugin *)dwInstance;
pPlugin->OnMidiIn(hMidiIn, wMsg, dwParam1, dwParam2); // pass data to plugin function
}
...
void CMyPlugin::OnMidiIn(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) // member function
{
// filter data and use however you want
switch (wMsg)
{
...
case MIM_DATA:
{
union
{
DWORD_PTR pData;
DWORD dwData;
BYTE bData[4];
} uMidiData;
uMidiData.pData = dwParam1;
switch (uMidiData.bData[0] & 0xF0)
{
case 0x80: // Note Off
// any calculations, etc
set_dsp_register...
break;
case 0x90: // Note On
...
}
}
break;
...
}
}
Last edited by Russ; May 6, 2008 at 01:28 PM. |
|
|
|
|
|
#10 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
this doesn't look easy because my small c/c++ knowledge. (still doing some tutorials )
__________________
http://freenet-homepage.de/stylish-s...xas/index.html |
|
|
|
|
|
#11 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
It can be confusing (callbacks in particulair), but take it a step at a time and lookup things that you do not understand (and if that doesn't help, ask about it).
You do not necessarily need to understand all the code to use it (but of course it is better if you do). For processing the MIDI data, you can use whatever methods you are more familair with, the above is just an example [COLOR=Gray](BTW: In the example, uMidiData.bData[0] would be the status byte, uMidiData.bData[1] would be the 1st data byte, and uMidiData.bData[2] would be the 2nd data byte)[/COLOR]. The main idea was just to pass the data back to the plugin so that you can use plugin functions with it. Last edited by Russ; May 6, 2008 at 01:08 PM. |
|
|
|
|
|
#12 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
thank you. let's see what i can do with it.
__________________
http://freenet-homepage.de/stylish-s...xas/index.html |
|
|
|
|
|
#13 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
have played around but no success. i did mix my midi callback code with the demo.cpp created some global variables which should hold now any mididata and tried to point on itusing something like that: [COLOR=White]
int midi_data_02 // global ... [/COLOR][COLOR=White]midi_data_02[/COLOR][COLOR=White]=((dwParam1>>16) & 0x000000FF);//assignment in the callback function ... set_dsp_register(VOL1_P, *(&[/COLOR][COLOR=White]midi_data_02[/COLOR][COLOR=White])*(0x1000000)); // point on any midi_data in the member function of the demo.cpp ... //blabla 8) [/COLOR]russ, i understand now a little bit more why/how data has to pass from one function to another but i fear have not the staying power to write a running code in the near future. there are to many problems for an implementation. i need for instance a data window in the .kxl to check what i'm doing. don't know if the debugger could help.. no idae if the midi callback works after putting it inside the demo.cpp. also the class concept is not yet fully understood (c++ basics). maybe we could find a common solution based on your idea above. stylus
__________________
http://freenet-homepage.de/stylish-s...xas/index.html Last edited by stylus02; May 18, 2008 at 04:04 PM. Reason: headless.. ;) |
|
|
|
|
|
#14 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
ok, maybe i should specify what it would be great to have for the time being. we have a running midi callback function , the kx demo workspace and our dsp (microcode) keyboard unit.
we want manipulate 2 registers in the kbu. one register should have a state 0 or 1 - our gate, which could get data from note volume. the second is the note register, which also ranges from 0..1 and gets the data from midi data byte 1. so far so good. we can set the right midi input device in the callback function after displaying it with a separately .exe also available here: Low Level MIDI API we don't need much filtering status bytes and sysex or do error treatment. simply set dsp registers with note and gate would be nice. stylus
__________________
http://freenet-homepage.de/stylish-s...xas/index.html Last edited by stylus02; May 18, 2008 at 04:43 PM. |
|
|
|
|
|
#15 |
|
DH Senior Member
Join Date: Jan 2003
Location: The Netherlands
Posts: 1,879
Rep Power: 48 ![]() ![]() ![]() ![]() |
To trace debug messages you could use kX message formatter function void debug(wchar_t *__format,...);
(iirc see debug.h). Then You could use Debugview DebugView for Windows to view the output. So in your code simply write debug code like debug("Value= %d string=%s", some_value, "some_string"); Start DebugView, load your plugin and voila,..examine the output. Usualy it's good practise to enclose the debug code lines in conditional compile like; #ifdef DEBUG_MY_STUFF debug("Value= %d string=%s", some_value, "some_string"); #endif that way you can turn all dbg msg on/off with 1 define. Hmm,..I don't know what you are doing in the rest of your code but looking at your code snippet I wunder if and when your set_dsp_register(VOL1_P, ...); is called. Anyway, apart from that, I think you don't see the full potential of the C/C++ kxl extension. The idea is to move ALL parameter computation from .da to .kxl. A basic example; - in your midi callback handler you process incoming midi events. Let's say you recieve a NoteOn; from that midi data you then compute the new Pitch coeff for your DSP Oscilator(s), send that pitch coeff through set_dsp_register(), send an ADSR trigger through set_dsp_register(). Note that all those pitch, filterCutOff and keyboard computations are now done in C/C++. that is much easier and will safe you alot of DSP gprs/instructions. The basic idea is; (pseudo code) void iSynthPlugin::midiCallbackHandler(MIDIMessage mididata) { if(mididate==NoteOn || mididate==NoteOFF) call midi_note_on_off(mididata) if(mididate==Controldata) call midi_control_data(mididata) if(mididate==PitchBend) call midi_PitchBend(mididata) // etc. etc. }; void iSynthPlugin::midi_note_on_off(MIDIMessage mididata) { // here you have to run a full keyboard schedular to // implement a 'real' analog keyboard with porta, glide, keymodes etc. // but basicly its the same as; // Turn off previous note set_dsp_register(R_ADSR_TRIG, ...); // compute new pitch coeff IN C/C++ set_dsp_register(R_PITCH_COEF, ...); // compute new Filter coeffS IN C/C++ set_dsp_register(R_FILTER_COEF, ...); etc. etc. // Turn on note set_dsp_register(R_ADSR_TRIG, ...); }; BTW: you really should use the mechanisme Russ already described to you to implement the above. There is no way around that (like you just tried) since the Callback must be able to notify your plugin when a midi msg arrives. Hence it must have access to a member function in your plugin class. Last edited by Lex Nahumury; May 19, 2008 at 12:12 AM. Reason: typo |
|
|
|
|
|
#16 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
thanks lex. for some time i asked me what the debug.h is for. the debugview works. so it can be very useful.
stylus
__________________
http://freenet-homepage.de/stylish-s...xas/index.html |
|
|
|
|
|
#17 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
I created a basic plugin (limited functionality, no GUI, no error checking, etc) that you can use for example (or as a starting point, etc).
It uses the default port for MIDI input and listens for Note On / Note Off messages on Channel 1 of that port, and sets DSP registers with calculated CV and Gate values, etc. [COLOR=Gray](temporary link - removed)[/COLOR] -Russ Last edited by Russ; May 20, 2008 at 03:19 AM. |
|
|
|
|
|
#18 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
russ, after compiling the sourcecode i got an error "syntax error on DWORD_PTR". i don't know what the _PTR means because we have a DWORD datatype which stands for a 32 bit unsigned long.
all i had to do was to substitute DWORD_PTR with DWORD in the callback function. now it works fine. we have a fast midi response in a compiled .kxl what makes the synthesizer more professional and its just great. i also want answer lex because the idea of the separation of midinote, controller or sysex etc. for the moment i don't want compile a lot of modules kxm 1xx..kxm9xx. so i had in mind to channel trough the midi data from our keyboard unit to a virtual midi out like "midi yoke out 1" or similar. from there the kx automation could get the controller data. this would give a good compatibility with all driver version. hope this works. stylus
__________________
http://freenet-homepage.de/stylish-s...xas/index.html Last edited by stylus02; May 20, 2008 at 07:34 AM. |
|
|
|
|
|
#19 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
Regarding DWORD_PTR, it sounds as though you do not have any recent Windows SDK installed. New data types were added (and functions were modified to use these new data types) for 64 bit support, etc.
|
|
|
|
|
|
#20 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
oh, this is interesting. i use windows xp and a microsoft visual c++ 6.0. no 64 bit support.
__________________
http://freenet-homepage.de/stylish-s...xas/index.html |
|
|
|
|
|
#21 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
Just installing the latest Windows SDK will update the headers for you, etc. In any case you should be fine for now, but at some point you should install the SDK. Regarding the code, as you have figured out, you can just replace DWORD_PTR with DWORD, and you can remove the DWORD_PTR line from the uMidiData union (and change "uMidiData.pData = dwParam1" to "uMidiData.dwData = dwParam1").
Last edited by Russ; May 20, 2008 at 07:23 PM. |
|
|
|
|
|
#22 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
have downloaded microsoft visual studio 2008 express. everything free, actual and ready for use.
for all who are interested in: Downloads
__________________
http://freenet-homepage.de/stylish-s...xas/index.html |
|
|
|
|
|
#23 |
|
DH Senior Member
Join Date: Jan 2003
Location: The Netherlands
Posts: 1,879
Rep Power: 48 ![]() ![]() ![]() ![]() |
iirc, M$VS 2008 Express doesn't come with MFC.
If so, then you probably run into KXGUI MFC dependency problems. |
|
|
|
|
|
#24 | |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
Quote:
Download details: Visual C++ 2005 Redistributable Package (x86)
__________________
http://freenet-homepage.de/stylish-s...xas/index.html |
|
|
|
|
|
|
#25 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
I am pretty sure that is just the .dll's and not the MFC header filers and libs, which is what Lex meant.
BTW: Info on how to get the necessary headers, etc can be found here: http://www.driverheaven.net/1046226-post14.html Also, in case you misunderstood, VC 6 is fine and actually is the preferred version for kX plugin development (since it includes the same MFC version (MFC42) that the kX SDK uses). Last edited by Russ; May 20, 2008 at 06:28 PM. |
|
|
|
|
|
#26 |
|
DH Senior Member
Join Date: Jan 2003
Location: The Netherlands
Posts: 1,879
Rep Power: 48 ![]() ![]() ![]() ![]() |
Yep, those are just the dlls.
But why on earth did you wanna switch in the first place while VC6 worked fine?? It's much easier to stick with MSVC 6 for now, especially in your case stylus. |
|
|
|
|
|
#27 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
ok, i've not realized the problem with the free express edition, which seems only to be free because the limitations. today i just saw randomly the offer on microsofts website and said to me "why not? it's only a 100 mb download."
neverthless.. i like the new environment, which looks to be easier for a beginner like me. if there is no way to get warm with it (kx & express) of course i take my hands off it. stylus
__________________
http://freenet-homepage.de/stylish-s...xas/index.html Last edited by stylus02; May 20, 2008 at 10:43 PM. |
|
|
|
|
|
#28 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
Not including a commercial library is not really a limitation...
|
|
|
|
|
|
#29 |
|
DriverHeaven Lover
Join Date: Jan 2008
Location: germany, sb0090
Posts: 158
Rep Power: 0 ![]() |
kxm120 beta 01
the km120 has got 2 combo boxes to change midi input device and midichannel. the midi devices are not listet by name but by number at the moment. you can try out or use the little program ListMidiDevs.exe below.
also you can use multiple instance of kxm120 but be careful that allways different midi input devices are selected, because same devices could not opened at same time. in later versions: - show the device names. - multiple outputs (notes, gates) which can set with midichannel (multitimbral) - midi controller data pass to kx control automatically (the impatient of you can use hubi's loopback for do that )- legato, glide, pitchbend and whatever can dreamed of.. [COLOR=DarkOrange] note: the kxl is compiled for 3538m![/COLOR] http://freenet-homepage.de/stylish-s...20_beta_01.kxl http://freenet-homepage.de/stylish-s...stMidiDevs.exe stylus
__________________
http://freenet-homepage.de/stylish-s...xas/index.html Last edited by stylus02; May 22, 2008 at 08:21 AM. Reason: speak&spell |
|
|
|
|
|
#30 |
|
DriverHeaven Extreme Member
Join Date: Jan 2005
Posts: 4,828
Rep Power: 41 ![]() ![]() ![]() |
What version of kX did you compile it for?
|
|
|
|
![]() |
| Bookmarks |
| Thread Tools | |
|
|