COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :

Go Back   Cockos Incorporated Forums > Other Software Discussion > WDL users forum

Reply
 
Thread Tools Display Modes
Old 08-20-2011, 07:41 AM   #1
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default IPlug/LICE blitting ?s and other newbie ?s

As some of you know from seeing my posts in KVR I want to make VSTs using IPlug/LICE and I have a few questions to get started:

-I'd like to be able to do all my graphics on a RGB buffer of my own, then when it's all done copy/blit its contents to the window created by MakeGraphics(), what should I call to make it efficient?

-I'd need to handle the mouse input myself (although I could always use transparent controls for mostly classical controls), what do I use for that? OnMouseDown() seems to do something like that? Can there be a callback that works for any mouse events (both movements and click changes) that concerns my window, à la SDL?

-I just cloned Tale's git repo and can't build LICE (using VS 2010), it complains about ..\zlib\gzio.c, zlib.h, ..\libpng\pngvcrd.c and ..\libpng\pnggccrd.c missing. I was able to build the main repo without any such problem. EDIT: I copied those files from the official cockos repo and now it builds, except in 64-bit, it still complains about a lack of zlib.h when dealing with libpng\pngstruct.h, dunno why..

-All the images in the 'img' folder in IPlugExample are somehow included automatically inside the plugin when compiled. How does it work? How does the compiler know which files to build it? Can I build a plugin that uses dynamically linked libraries and somehow have those DLLs inserted inside my plugin's DLL? Like, let's say I want to use pthread, can I do that?

-I don't suppose there's any documentation anywhere? I couldn't find any. Not a big problem, it only means I might have more questions to ask you .

That's all for now, but rest assured that I'll soon find more to ask .

Last edited by A_SN; 08-20-2011 at 11:08 AM.
A_SN is offline   Reply With Quote
Old 08-20-2011, 11:26 AM   #2
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Hi again, and welcome at the WDL users forum.

Quote:
Originally Posted by A_SN View Post
I'd like to be able to do all my graphics on a RGB buffer of my own, then when it's all done copy/blit its contents to the window created by MakeGraphics(), what should I call to make it efficient?
You can directly access pixels in the LICE bitmap like this:

Code:
IGraphics pGraphics = mPlug->GetGUI();
LICE_IBitmap* pLB = pGraphics->GetDrawBitmap();
LICE_pixel* px = pLB->getBits();
int width = pLB->getRowSpan();
int x = 400, y = 300;
px += y * width + x;
*px = LICE_RGBA(255, 0, 0, 255);
You could also call IGraphics::ForcePixel, but the direct approach is probably more efficient, because you can reuse the LICE_pixel pointer for manipulating more pixels.

Quote:
Originally Posted by A_SN View Post
I'd need to handle the mouse input myself (although I could always use transparent controls for mostly classical controls), what do I use for that? OnMouseDown() seems to do something like that? Can there be a callback that works for any mouse events (both movements and click changes) that concerns my window, à la SDL?
Transparent controls should work. See IControl.h for all the mouse event methods (OnMouseDown, OnMouseUp etc.) you can override. If you want to capture mouse movements using OnMouseOver and OnMouseOut, then you need to enable this by calling IGraphics::HandleMouseOver:

Code:
IGraphics* pGraphics = MakeGraphics(this, 640, 480);
pGraphics->HandleMouseOver(true);
Quote:
Originally Posted by A_SN View Post
I just cloned Tale's git repo and can't build LICE (using VS 2010), it complains about ..\zlib\gzio.c, zlib.h, ..\libpng\pngvcrd.c and ..\libpng\pnggccrd.c missing. I was able to build the main repo without any such problem.
Oops, sorry about that. I have updated zlib and libpng to the latest versions, but because I don't use Visual Studio myself, I haven't updated the VS project files accordingly. I think it should work if you remove zlib/gzio.c, libpng/pngvcrd.c, and libpng/pnggccrd.c from the project, and add ../zlib to the includes path (so libpng knows where to find zlib.h). You may also need to define NO_GZCOMPRESS for zlib, and remove all predefined macros (PNG_*) for libpng.

Quote:
Originally Posted by A_SN View Post
All the images in the 'img' folder in IPlugExample are somehow included automatically inside the plugin when compiled. How does it work? How does the compiler know which files to build it? Can I build a plugin that uses dynamically linked libraries and somehow have those DLLs inserted inside my plugin's DLL? Like, let's say I want to use pthread, can I do that?
The image files included as resources, see IPlugExample.rc.

Including code from dynamically linked libraries is another thing though, I don't think that is even possible. I do think you can load a DLL on runtime (using the LoadLibrary WinAPI call?).

Quote:
Originally Posted by A_SN View Post
I don't suppose there's any documentation anywhere? I couldn't find any. Not a big problem, it only means I might have more questions to ask you .
No, there is no real documentation. But there are the commit messages in the Git repository, and the comments included in the source files. And there is a lot of info on the forum.
Tale is offline   Reply With Quote
Old 08-20-2011, 01:26 PM   #3
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Thanks a lot for the reply!

Quote:
Originally Posted by Tale View Post
You can directly access pixels in the LICE bitmap like this:

Code:
IGraphics pGraphics = mPlug->GetGUI();
LICE_IBitmap* pLB = pGraphics->GetDrawBitmap();
LICE_pixel* px = pLB->getBits();
int width = pLB->getRowSpan();
int x = 400, y = 300;
px += y * width + x;
*px = LICE_RGBA(255, 0, 0, 255);
About ->getRowSpan(), can the value it returns be different from the originally defined width of the window? As in you create a window 397 pixels wide and getRowSpan() returns 400 because of alignment? Or is it always the same? I'm asking because if it's always the same then I can just memcpy() the whole buffer. As for the colour format, I use a bit-field that's designed to be reversed on __APPLE__, so I guess I should be fine for memcpy()ing the whole thing.


Quote:
Originally Posted by Tale View Post
Oops, sorry about that. I have updated zlib and libpng to the latest versions, but because I don't use Visual Studio myself, I haven't updated the VS project files accordingly. I think it should work if you remove zlib/gzio.c, libpng/pngvcrd.c, and libpng/pnggccrd.c from the project, and add ../zlib to the includes path (so libpng knows where to find zlib.h). You may also need to define NO_GZCOMPRESS for zlib, and remove all predefined macros (PNG_*) for libpng.
OK thanks I've done that (except removing the PNG_* macros, didn't know where to find that) and it works. So I thought I'd share the modified lice.vcxproj file: http://pastebin.com/fD8MytB5
A_SN is offline   Reply With Quote
Old 08-20-2011, 02:16 PM   #4
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

OK I have a couple of other problems trying to compile the IPlugExample now.

When I compile for Win32 it says
Code:
1>IPlug.lib(IGraphics.obj) : error LNK2019: unresolved external symbol "public: __thiscall LICE_CachedFont::LICE_CachedFont(void)" (??0LICE_CachedFont@@QAE@XZ) referenced in function "protected: static class LICE_IFont * __cdecl IGraphics::CacheFont(struct IText *)" (?CacheFont@IGraphics@@KAPAVLICE_IFont@@PAUIText@@@Z)
I tried to create an X64 target but when I try to compile it says
Code:
1>MSVCRT.lib(MSVCR100.dll) : error LNK2005: free already defined in LIBCMT.lib(free.obj)
1>MSVCRT.lib(MSVCR100.dll) : error LNK2005: malloc already defined in LIBCMT.lib(malloc.obj)
1>MSVCRT.lib(MSVCR100.dll) : error LNK2005: realloc already defined in LIBCMT.lib(realloc.obj)
1>MSVCRT.lib(MSVCR100.dll) : error LNK2005: memmove already defined in LIBCMT.lib(memcpy.obj)
1>MSVCRT.lib(MSVCR100.dll) : error LNK2005: tolower already defined in LIBCMT.lib(tolower.obj)
1>MSVCRT.lib(MSVCR100.dll) : error LNK2005: isupper already defined in LIBCMT.lib(_ctype.obj)
1>MSVCRT.lib(ti_inst.obj) : error LNK2005: "private: __cdecl type_info::type_info(class type_info const &)" (??0type_info@@AEAA@AEBV0@@Z) already defined in LIBCMT.lib(typinfo.obj)
1>MSVCRT.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __cdecl type_info::operator=(class type_info const &)" (??4type_info@@AEAAAEAV0@AEBV0@@Z) already defined in LIBCMT.lib(typinfo.obj)
1>MSVCRT.lib(MSVCR100.dll) : error LNK2005: _stricmp already defined in LIBCMT.lib(stricmp.obj)
1>     Creating library X64\Release\test.lib and object X64\Release\test.exp
1>LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
before what it also says for the 32 bit build. I tried to set the NODEFAULTLIB thing but when I do it's even worse, the linker can't find references to a whole lot of standard functions.
A_SN is offline   Reply With Quote
Old 08-20-2011, 02:28 PM   #5
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
About ->getRowSpan(), can the value it returns be different from the originally defined width of the window? As in you create a window 397 pixels wide and getRowSpan() returns 400 because of alignment? Or is it always the same? I'm asking because if it's always the same then I can just memcpy() the whole buffer.
getRowSpan indeed does not necessarily return the original width. However, I don't think it will change unless you resize the bitmap.

Quote:
Originally Posted by A_SN View Post
As for the colour format, I use a bit-field that's designed to be reversed on __APPLE__, so I guess I should be fine for memcpy()ing the whole thing.
I think the LICE_RGBA macro does something similar, so yeah, that should work.

Quote:
Originally Posted by A_SN View Post
OK thanks I've done that (except removing the PNG_* macros, didn't know where to find that) and it works. So I thought I'd share the modified lice.vcxproj file: http://pastebin.com/fD8MytB5
Cheers, thanks a lot! With your permission I would like to include it my Git repository.
Tale is offline   Reply With Quote
Old 08-20-2011, 02:31 PM   #6
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by Tale View Post
Cheers, thanks a lot! With your permission I would like to include it my Git repository.
Of course you can include it! If I can fix my issues with building the IPlugExample for VS 2010 and that I can have it make X64 builds too you might wanna include that as well? Right now it only has an old .vcproj file for that.
A_SN is offline   Reply With Quote
Old 08-20-2011, 02:43 PM   #7
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
When I compile for Win32 it says
Code:
1>IPlug.lib(IGraphics.obj) : error LNK2019: unresolved external symbol "public: __thiscall LICE_CachedFont::LICE_CachedFont(void)" (??0LICE_CachedFont@@QAE@XZ) referenced in function "protected: static class LICE_IFont * __cdecl IGraphics::CacheFont(struct IText *)" (?CacheFont@IGraphics@@KAPAVLICE_IFont@@PAUIText@@@Z)
If you add lice/lice_textnew.cpp to the project (and perhaps remove lice/lice_text.cpp), this should be fixed.

Quote:
Originally Posted by A_SN View Post
I tried to create an X64 target but when I try to compile it says
Code:
1>MSVCRT.lib(MSVCR100.dll) : error LNK2005: free already defined in LIBCMT.lib(free.obj)
before what it also says for the 32 bit build. I tried to set the NODEFAULTLIB thing but when I do it's even worse, the linker can't find references to a whole lot of standard functions.
I am not sure, but Google says LNK2005 could be caused by mixing static (/MT) and dynamic (/MD) linking (you will want /MT).
Tale is offline   Reply With Quote
Old 08-20-2011, 02:47 PM   #8
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
Of course you can include it! If I can fix my issues with building the IPlugExample for VS 2010 and that I can have it make X64 builds too you might wanna include that as well?
Yes, please.

Quote:
Originally Posted by A_SN View Post
Right now it only has an old .vcproj file for that.
You are using the lice.vcproj in IPlug, right? There is actually a better project in lice/lice.vcxproj, which also already includes X64 builds. However, it again isn't updated with the latest zlib, libpng and lice_textnew.cpp.
Tale is offline   Reply With Quote
Old 08-20-2011, 03:12 PM   #9
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by Tale View Post
If you add lice/lice_textnew.cpp to the project (and perhaps remove lice/lice_text.cpp), this should be fixed.
I'm talking about the IPlugExample project, it doesn't have those.

Quote:
Originally Posted by Tale View Post
I am not sure, but Google says LNK2005 could be caused by mixing static (/MT) and dynamic (/MD) linking (you will want /MT).
Wait so I set the configuration type to static library and it all built fine, only it would only output a .lib file, not a .dll (since I'm building a VST that's wrong). If I make it output a .dll then the problem remains, and switching to /MD doesn't help...
A_SN is offline   Reply With Quote
Old 08-20-2011, 03:56 PM   #10
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
I'm talking about the IPlugExample project, it doesn't have those.
I know, but the IPlugExample project is linked with both IPlug.lib and lice.lib. Lice.lib is missing lice_textnew.cpp, which IPlug.lib needs, which is why you can't link the IPlugExample (IPlugExample > IPlug > lice, you see?).

I have just checked my own makefile, and I am pretty sure advapi32.lib needs to be added to the IPlugExample project before it can be successfully linked.

Quote:
Originally Posted by A_SN View Post
Wait so I set the configuration type to static library and it all built fine, only it would only output a .lib file, not a .dll (since I'm building a VST that's wrong). If I make it output a .dll then the problem remains, and switching to /MD doesn't help...
I'm sorry if I wasn't clear, but I meant to say that the runtime libs should be statically linked along with your DLL, which means you should use /MT everywhere.

BTW, if I were you I would stick to 32-bit for now, and worry about x64 later.
Tale is offline   Reply With Quote
Old 08-20-2011, 05:43 PM   #11
olilarkin
Human being with feelings
 
olilarkin's Avatar
 
Join Date: Apr 2009
Location: Huddersfield, UK
Posts: 1,153
Default

since i did a lot of work lately on making good vs2010 projects i uploaded a zip of my iplug, without the rtas stuff (hopefully that doesn't break anything).

http://www.olilarkin.co.uk/dev/wdl-o...011-nortas.zip

If you look in IPlugExamples/IPlugMultiTargets/ you will find vs2010 and xcode projects and you can work out the links to projects for related static libraries for lice and IPlug where appropriate. You can probably drop the msvc/xcode projects into tales repo, since I pulled in his changes regarding libpng and zlib.
__________________
VirtualCZ | pMix | Endless Series | iPlug2 | Linkedin | Facebook
Available for Audio Dev tuition via Skype (IPlug/JUCE/C++)
olilarkin is offline   Reply With Quote
Old 08-21-2011, 11:09 AM   #12
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

I have now updated my Git repository, so it should work again with Visual Studio (although I haven't tested it yet).
Tale is offline   Reply With Quote
Old 08-21-2011, 12:20 PM   #13
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by Tale View Post
I have now updated my Git repository, so it should work again with Visual Studio (although I haven't tested it yet).
Alright I tested and it works smoothly. Except for the 64-bit parts where the settings (/MT vs /MD, optimisation settings and so forth..) were different, so I copied the parameters from the 32 bit configs to the 64 bit ones. Here are the fixed files working for 64-bit just as nicely as it does for 32-bits:

lice.vcxproj: http://pastebin.com/zdpz1a7T
IPlug.vcxproj: http://pastebin.com/Nd1epnWd
IPlugExample.vcxproj: http://pastebin.com/GeWP9rL6

Completely unrelatedly, how do you report the delay of an effect to the host?
A_SN is offline   Reply With Quote
Old 08-21-2011, 12:28 PM   #14
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
Alright I tested and it works smoothly. Except for the 64-bit parts where the settings (/MT vs /MD, optimisation settings and so forth..) were different, so I copied the parameters from the 32 bit configs to the 64 bit ones. Here are the fixed files working for 64-bit just as nicely as it does for 32-bits:

lice.vcxproj: http://pastebin.com/zdpz1a7T
IPlug.vcxproj: http://pastebin.com/Nd1epnWd
IPlugExample.vcxproj: http://pastebin.com/GeWP9rL6
Cool! I assume I have permission to reuse these again?

Quote:
Originally Posted by A_SN View Post
Completely unrelatedly, how do you report the delay of an effect to the host?
I think you report the initial/maximum latency (in samples) using #define PLUG_LATENCY in resource.h. You can later change the latency by calling SetLatency for hosts that support on-the-fly latency changes.
Tale is offline   Reply With Quote
Old 08-21-2011, 12:30 PM   #15
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by Tale View Post
Cool! I assume I have permission to reuse these again?
Naturally!


Quote:
Originally Posted by Tale View Post
I think you report the initial/maximum latency (in samples) using #define PLUG_LATENCY in resource.h. You can later change the latency by calling SetLatency for hosts that support on-the-fly latency changes.
OK thanks!
A_SN is offline   Reply With Quote
Old 08-21-2011, 01:05 PM   #16
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
Naturally!
Thanks. I have added/updated them in my Git repository.
Tale is offline   Reply With Quote
Old 08-22-2011, 01:07 PM   #17
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Is there any way with IPlug for several instances of the same plugin in the same host to communicate/share memory? In one of my planned VSTs there will be a very large (200 MB) look-up table used for synthesis, and ideally all instances of the plugin will be able to access the same table rather than having each their own copy. Is that possible in any way?
A_SN is offline   Reply With Quote
Old 08-22-2011, 01:15 PM   #18
olilarkin
Human being with feelings
 
olilarkin's Avatar
 
Join Date: Apr 2009
Location: Huddersfield, UK
Posts: 1,153
Default

make it a static member? some how count instances of your plugin in a static variable and free the memory when the last one goes?
__________________
VirtualCZ | pMix | Endless Series | iPlug2 | Linkedin | Facebook
Available for Audio Dev tuition via Skype (IPlug/JUCE/C++)
olilarkin is offline   Reply With Quote
Old 08-22-2011, 01:18 PM   #19
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by olilarkin View Post
make it a static member? some how count instances of your plugin in a static variable and free the memory when the last one goes?
Wait... static variables are accessible across instances? Well, sounds like that's my answer then.

What about (non-static) globals? Are they accessible across instances too?

EDIT: nvm, just did some more reading on it.

Last edited by A_SN; 08-22-2011 at 02:57 PM.
A_SN is offline   Reply With Quote
Old 08-24-2011, 01:33 PM   #20
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

I just don't get how mutexes work in IPlug, what is "IMutexLock lock(this);" supposed to do? Where is the mutex (I don't see a name)? How does it get unlocked?

I'm used to working with pthread's semaphores, can I do that here? Or use platform specific code? (I assume Windows uses its own semaphores and Mac OS uses pthread?)
A_SN is offline   Reply With Quote
Old 08-24-2011, 01:51 PM   #21
olilarkin
Human being with feelings
 
olilarkin's Avatar
 
Join Date: Apr 2009
Location: Huddersfield, UK
Posts: 1,153
Default

i am not a mutex/threading expert but here are some clues that may or may not be accurate!

in IPlugBase.h you'll find a member mMutex (type WDL_Mutex, see mutex.h) and a class/struct called IMutexLock which is AFAIK a helper to lock/unlock the mutex based on the scope of the method it is called in... so that is why you see it at the top of some IPlugBase methods (or methods you override in your plugin class)... it unlocks the mutex at the end of the method when the IMutexLock goes out of scope.

if you look in mutex.h you will see exactly what pthread/windows stuff gets called when you call IMutexLock lock(this);

hth,

oli
__________________
VirtualCZ | pMix | Endless Series | iPlug2 | Linkedin | Facebook
Available for Audio Dev tuition via Skype (IPlug/JUCE/C++)

Last edited by olilarkin; 08-24-2011 at 02:04 PM.
olilarkin is offline   Reply With Quote
Old 08-24-2011, 02:49 PM   #22
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by olilarkin View Post
i am not a mutex/threading expert but here's some clues that may or may not be accurate!

in IPlugBase.h you'll find a member mMutex (type WDL_Mutex, see mutex.h) and a class/struct called IMutexLock which is AFAIK a helper to lock/unlock the mutex based on the scope of the method it is called in... so that is why you see it at the top of some IPlugBase methods (or methods you override in your plugin class)... it unlocks the mutex at the end of the method when the IMutexLock goes out of scope.

if you look in mutex.h you will see exactly what pthread/windows stuff gets called when you call IMutexLock lock(this);

hth,

oli
OK thanks, so it just unlocks when you leave the function? I think I'll just roll with my own wrapper based on each OS's respective native mutex/semaphore system as I need to protect (shorter, not function-wide) things not just from other instances of a function but from other concurrent functions too. Let me know if you'd like me to share when it's done (I'll probably write it in C though).
A_SN is offline   Reply With Quote
Old 08-24-2011, 11:10 PM   #23
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
I need to protect (shorter, not function-wide) things
I think you could do

Code:
...
{
	IMutexLock lock(this);
	...
} // Mutex unlocks here
...
to protect a shorter piece of code.
Tale is offline   Reply With Quote
Old 08-25-2011, 09:46 AM   #24
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

OK, back to the original blitting question, I tested writing pixels directly to the pointer but it doesn't do anything, the window remains white. My guess is I need to call something to refresh the display?

Code:
MyPlug::MyPlug(IPlugInstanceInfo instanceInfo)
:	IPLUG_CTOR(kNumParams, 0, instanceInfo)
{
	IGraphics* pGraphics = MakeGraphics(this, kW, kH);
	AttachGraphics(pGraphics);
}

void MyPlug::ProcessDoubleReplacing(double **inputs, double **outputs, int nFrames)
{
	int32_t ix, iy;
	LICE_pixel *fb = GetGUI()->GetDrawBitmap()->getBits();

	// that does nothing on screen although it does take a lot of CPU (naturally)
	for (iy=0; iy<kH; iy++)
		for (ix=0; ix<kW; ix++)
			fb[iy*kW + ix] = LICE_RGBA(iy, ix*4+iy*3, ix, 255);
}
EDIT: Unrelatedly, how do I create a thread with IPlug? Is there any code for that? I can't find any.

Last edited by A_SN; 08-25-2011 at 10:14 AM.
A_SN is offline   Reply With Quote
Old 08-25-2011, 10:28 AM   #25
olilarkin
Human being with feelings
 
olilarkin's Avatar
 
Join Date: Apr 2009
Location: Huddersfield, UK
Posts: 1,153
Default

you probably need to make at least one IControl, in which you do the drawing.

Code:
class IDrawControl : public IControl 
{
public:
  IDrawControl(IPlugBase* pPlug, IRECT pR)
  : IControl(pPlug, pR) {}
  
  bool Draw(IGraphics* pGraphics)
  {
    int32_t ix, iy;
    LICE_pixel *fb = pGraphics->GetDrawBitmap()->getBits();
    
    for (iy=0; iy<mRECT.H(); iy++)
      for (ix=0; ix<mRECT.W(); ix++)
        fb[iy*mRECT.W() + ix] = LICE_RGBA(iy, ix*4+iy*3, ix, 255);
    
    return true;
  }
  
  //bool IsDirty() { return true;} // uncomment to redraw every frame ~25fps
};
Code:
IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight);
pGraphics->AttachControl(new IDrawControl(this, &IRECT(0, 0, kWidth, kHeight)));
AttachGraphics(pGraphics);
__________________
VirtualCZ | pMix | Endless Series | iPlug2 | Linkedin | Facebook
Available for Audio Dev tuition via Skype (IPlug/JUCE/C++)
olilarkin is offline   Reply With Quote
Old 08-25-2011, 10:52 AM   #26
olilarkin
Human being with feelings
 
olilarkin's Avatar
 
Join Date: Apr 2009
Location: Huddersfield, UK
Posts: 1,153
Default

Quote:
EDIT: Unrelatedly, how do I create a thread with IPlug? Is there any code for that? I can't find any.
there is some code here (didn't try it myself)
http://forum.cockos.com/showthread.p...ghlight=thread

try searching the forum before posting... there is a lot of information here about how to use IPlug, much of it is hidden away in old threads, which are not necessarily on topic
__________________
VirtualCZ | pMix | Endless Series | iPlug2 | Linkedin | Facebook
Available for Audio Dev tuition via Skype (IPlug/JUCE/C++)
olilarkin is offline   Reply With Quote
Old 08-25-2011, 10:54 AM   #27
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by olilarkin View Post
there is some code here (didn't try it myself)
http://forum.cockos.com/showthread.p...ghlight=thread

try searching the forum before posting... there is a lot of information here about how to use IPlug, much of it is hidden away in old threads, which are not necessarily on topic
Thanks, I tried to do that, the problem is when you search the word 'thread' you get things referencing forum threads.
A_SN is offline   Reply With Quote
Old 08-25-2011, 12:05 PM   #28
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by olilarkin View Post
you probably need to make at least one IControl, in which you do the drawing.

Code:
class IDrawControl : public IControl 
{
public:
  IDrawControl(IPlugBase* pPlug, IRECT* pR)
  : IControl(pPlug, pR) {}
  
  bool Draw(IGraphics* pGraphics)
  {
    int32_t ix, iy;
    LICE_pixel *fb = pGraphics->GetDrawBitmap()->getBits();
    
    for (iy=0; iy<mRECT.H(); iy++)
      for (ix=0; ix<mRECT.W(); ix++)
        fb[iy*mRECT.W() + ix] = LICE_RGBA(iy, ix*4+iy*3, ix, 255);
    
    return true;
  }
  
  //bool IsDirty() { return true;} // uncomment to redraw every frame ~25fps
};
Code:
IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight);
pGraphics->AttachControl(new IDrawControl(this, &IRECT(0, 0, kWidth, kHeight)));
AttachGraphics(pGraphics);
Excellent thanks! By setting IsDirty() I get about 21 FPS on a 600x400 window, is it the fastest it can refresh or is it slower on purpose? I'm asking because on some kinds of visualisations it might look a bit choppy.
EDIT: Nevermind, I figured how to set the FPS: IGraphics *pGraphics = MakeGraphics(this, kW, kH, 60);

Also, what thread does Draw() get called from? It probably doesn't matter much, I'd just like to know if it blocks anything.

Last edited by A_SN; 08-25-2011 at 12:36 PM.
A_SN is offline   Reply With Quote
Old 08-25-2011, 11:25 PM   #29
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
Also, what thread does Draw() get called from? It probably doesn't matter much, I'd just like to know if it blocks anything.
I guess that depends on the host, but you should assume Draw is called from the (lower-priority) GUI thread.
Tale is offline   Reply With Quote
Old 08-28-2011, 02:10 PM   #30
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

How is colour data written in IBitmap's mData member? I tried casting it to a 32-bit RGBA format but there was a problem with it. See code:

Code:
uint32_t *EQEnv::convert_image(IBitmap bitmap)
{
	uint32_t *image;
	LICE_IBitmap* pSrc = (LICE_IBitmap*) bitmap.mData;
	image = (uint32_t *) pSrc->getBits();
	return image;
}
I'm not sure at what I'm observing in the results, but it seems like the last quarter of each row of pixels is set to a fixed value, and the first 3 quarters seem squeezed. But there's no offset from a row to another, it remains vertically aligned, which is pretty puzzling.

tl;dr how do I properly read data from IBitmap's mData member?
A_SN is offline   Reply With Quote
Old 08-29-2011, 02:37 AM   #31
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
tl;dr how do I properly read data from IBitmap's mData member?
I suggest you have a look at LICE_GetPixel() in lice/lice.cpp.
Tale is offline   Reply With Quote
Old 08-29-2011, 06:17 AM   #32
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by Tale View Post
I suggest you have a look at LICE_GetPixel() in lice/lice.cpp.
Thanks, couldn't find that function. However I tried that along with LICE_GETR/G/B to get individual values, alas the result is the exact same as before. Somehow my PNGs get loaded in a really wrong way.

EDIT: My PNGs were in 8-bit grey, I guess that's why it was weird. I converted them to RGB and these load fine.

Last edited by A_SN; 08-29-2011 at 06:34 AM.
A_SN is offline   Reply With Quote
Old 08-29-2011, 07:18 AM   #33
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Yeah, I have tried grayscale PNGs before, but that didn't work for me either.

Anyway, I had already tried it myself, so (although I guess you don't need it anymore) here is my working example (that incidentally converts a PNG to grayscale):

Code:
IBitmap bitmap = pGraphics->LoadIBitmap(MY_IMAGE_ID, MY_IMAGE_PNG);

LICE_IBitmap* bm = (LICE_IBitmap*)bitmap.mData;
LICE_pixel* bits = bm->getBits();
for (int y = 0; y < bm->getHeight(); ++y)
{
	for (int x = 0; x < bm->getWidth(); ++x)
	{
		LICE_pixel px = bits[y * bm->getRowSpan() + x];
		int gray = (30 * LICE_GETR(px) + 59 * LICE_GETG(px) + 11 * LICE_GETB(px)) / 100;
		px = LICE_RGBA(gray, gray, gray, LICE_GETA(px));
		bits[y * bm->getRowSpan() + x] = px;
	}
}

pGraphics->AttachControl(new IBitmapControl(this, 100, 100, -1, &bitmap));

Last edited by Tale; 08-29-2011 at 07:18 AM. Reason: Typo
Tale is offline   Reply With Quote
Old 09-09-2011, 02:52 PM   #34
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Concerning reporting delay again, I'm not sure I'm doing it right. From a function belonging to my own IPlug class I call this at some point:
Code:
SetLatency(delay_in_samples);    // delay_in_samples == 2048 here
but I'm not sure it does anything and according to a test user they can hear the delay too. Maybe it matters at what point it's called?

Anyway thanks to you guys' help I was able to put together what is at the moment a simple linear-phase 5 band EQ VST, this is my gift back to you http://photosounder.com/misc/EQ5.zip

Last edited by A_SN; 09-09-2011 at 02:57 PM.
A_SN is offline   Reply With Quote
Old 09-12-2011, 02:06 AM   #35
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

The EQ is working great here.

About the latency: If you have defined PLUG_LATENCY as 2048, then SetLatency(2048) will not do anything, beacuse the latency already is 2048. Only if you want to lower the latency later on to e.g. 1024, you call SetLatency(1024) for hosts that support changing the latency on-the-fly.
Tale is offline   Reply With Quote
Old 09-12-2011, 02:12 AM   #36
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by Tale View Post
The EQ is working great here.

About the latency: If you have defined PLUG_LATENCY as 2048, then SetLatency(2048) will not do anything, beacuse the latency already is 2048. Only if you want to lower the latency later on to e.g. 1024, you call SetLatency(1024) for hosts that support changing the latency on-the-fly.
PLUG_LATENCY here is defined as 0. Should I remove the #define? My problem is that the latency depends on many parameters, the main one being the host's sampling rate, so it's hard to start with a good macro for that. Anyway are you saying that you can only lower the latency from what's defined? Or that it can be changed to anything provided the host supports that?

Thanks!
A_SN is offline   Reply With Quote
Old 09-12-2011, 02:48 AM   #37
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,930
Default

Quote:
Originally Posted by A_SN View Post
PLUG_LATENCY here is defined as 0. Should I remove the #define?
No, in your case I think you should define it as 2048.

Quote:
Originally Posted by A_SN View Post
My problem is that the latency depends on many parameters, the main one being the host's sampling rate, so it's hard to start with a good macro for that. Anyway are you saying that you can only lower the latency from what's defined?
Yes, that is what I am saying. Hosts that don't support latency changes after the plug-in has been loaded are stuck with the defined latency. For hosts that do support latency changes you can easily lower the latency, or even increase it again (up to the defined latency).
Tale is offline   Reply With Quote
Old 09-12-2011, 02:57 AM   #38
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Quote:
Originally Posted by Tale View Post
No, in your case I think you should define it as 2048.


Yes, that is what I am saying. Hosts that don't support latency changes after the plug-in has been loaded are stuck with the defined latency. For hosts that do support latency changes you can easily lower the latency, or even increase it again (up to the defined latency).
Wow, that's gonna be a problem, unless the defined latency is set to something huge. Because basically my latency scales up with the sampling rate, so if I set the latency at 2048 (which is the correct latency for a 44.1 kHz rate), then if the host's frequency is 192 kHz (I'm sure some people use that?) then the latency is gonna be something like 10569, a big difference.

How many of the big commercial hosts that everybody uses support latency changes? If enough do maybe I could define it to something like 32768 and then change it to the correct value? Why couldn't it be changed to a value higher than the defined value anyway? That's weird.
A_SN is offline   Reply With Quote
Old 09-14-2011, 08:54 AM   #39
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

OK I figured out everything about the latency I think, which I checked by phase inversion with an identical track that doesn't have my plug on it. And I have PLUG_LATENCY set to 0 yet that's not a problem to set the latency to anything using SetLatency().

Anyway for something unrelated: how do I know when Reset() is being called after the plugin gets unbypassed? Since I'm making an EQ it 'remembers' what it's working on so if you bypass it and unbypass it then it plays what it had left in memory when I should blank it. So how do I know when Reset() is being called for that and not something else? Cause it seems Reset gets called for a lot of things? Or are all those things situations where I'd want to blank the buffers anyway? What do you usually do about that?
A_SN is offline   Reply With Quote
Old 09-16-2011, 10:23 AM   #40
A_SN
Human being with feelings
 
Join Date: Aug 2011
Posts: 89
Default

Is there any way provided by IPlug to measure time taken by a routine? I looked for it but couldn't find anyway. I want a way to measure how long my processing thing takes and display how long it takes so I can make it change some parameters based on CPU performance of each (it's hard to predict which parameters will be the fastest otherwise).
A_SN is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 09:32 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.