tag:blogger.com,1999:blog-64260558749002922982024-03-18T20:12:03.707-07:00harryhaarenA blog dedicated to Linux Audio. Some Programming tutorials will be posted, some howTo articles for using certain features of a program, or just my own thoughts/options on any topic.Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.comBlogger62125tag:blogger.com,1999:blog-6426055874900292298.post-24273322418671274312013-12-30T15:56:00.000-08:002014-10-12T04:46:37.484-07:00Blog Status : Moved, not dead!Hi all,<br />
<br />
Once upon a time I posted on this blog (somewhat) regularly. Currently I dont. Why? I'm running OpenAV Productions, and that is where the updates are!<br />
<br />
If you're still interested in Linux audio, C++ programming or software in general, checkout the site:<br />
<a href="http://www.openavproductions.com/">www.openavproductions.com</a><br />
<br />
Developers may have particular interest in the developer topics like <a href="http://www.openavproductions.com/nsm/">implementing NSM</a> or <a href="http://www.openavproductions.com/rtmem/">dealing with memory in real-time</a>.<br />
<br />
Audio programming folks, checkout some articles that I've written on the topics of real-time programming, memory management, implementing NSM and more:<br />
<a href="http://openavproductions.com/conferences/">http://openavproductions.com/conferences</a>.<br />
<br />
I probably won't post here for another long time, so bye for now! -HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.comtag:blogger.com,1999:blog-6426055874900292298.post-63610193825129117672013-06-22T16:59:00.000-07:002013-06-22T17:01:25.762-07:00Real time audio programming languages<h2>
Introduction </h2>
Over the last couple of years I've written various real-time audio programs. Its difficult to adhere to real-time regulations: you've got to get threading and memory management right.<br />
<br />
C++ is the often concidered the obvious choice language for large real-time audio programs: its a compiled language, and is deterministic in time if used carefully. This is necessary for real time (RT) work, and rules out VM based languages like Python for any low-latency work. <br />
<br />
In C++ there's many a way to achieve real-time, one of which I have detailed here: <a href="https://github.com/harryhaaren/fypRealtimeCppPrograming">https://github.com/harryhaaren/fypRealtimeCppPrograming</a><br />
<br />
<h2>
Other languages</h2>
C++ is one way to go, but in recent times there are various other programming languages which are becoming increasingly attractive to the real-time audio programmer. Particularly these two languages have caught my eye recently:<br />
<br />
Rust : <a href="http://www.rust-lang.org/">http://www.rust-lang.org</a><br />
Iolanguage: <a href="http://iolanguage.org/">http://iolanguage.org</a><br />
<br />
Both of these languages have certain characteristics which make them possible candidates for RT programming.<br />
<br />
<h2>
Rust</h2>
<h4>
Language Overview</h4>
Rust is a language that focuses on "blocks", using boundaries. Integrity, availability and concurrency are its main goals. It uses lightweight tasks with message passing for concurrency, no shared memory.<br />
<br />
<h4>
The Interesting Stuff</h4>
I'm most intrigued by the memory management of the language: everything is static unless declared "mut" (or "mutable"), and ownership of objects is very strict. This means that managing resources in a real-time safe way is well defined, and hence the code will be maintainable.<br />
<br />
Three different "pointer" types exist, as well as new concepts like owned boxes and managed boxes... these new concepts may aid memory allocation troubles, but perhaps it complicates them too, I don't have much experience yet with it, so only time will tell...<br />
<br />
<h4>
Learning It</h4>
Most of what I know comes straight from their homepage or tutorial:<br />
Homepage: <a href="http://www.rust-lang.org/">www.rust-lang.org</a><br />
Tutorial: <a href="http://static.rust-lang.org/doc/0.6/tutorial.html">http://static.rust-lang.org/doc/0.6/tutorial.html</a><br />
<h4>
</h4>
<h4>
Conclusion</h4>
A cool language, and if the memory concepts prove useful, it could be an awesome new language to learn for the audio-programming enthusiast. <br />
<h3>
</h3>
<h2>
IOlanguage</h2>
<h4>
Language Overview</h4>
This is a smalltalk inspired language, while also incorporating various different elements from other languages together. Actors based concurrency is used (a la <a href="http://web.media.mit.edu/~lieber/Lieberary/OOP/Act-1/Concurrent-OOP-in-Act-1.html">Act1</a>), while it is also kept small for embeddable purposes. Runs in a small VM.<br />
<br />
<h4>
The Interesting Stuff </h4>
Intensive inspecting of object instances / program state (like LISP) aids debugging significantly. Extensive concurrency possibilities: co-routines, actors, futures and yield statements allow for flexible "time" programming.<br />
<h4>
</h4>
<h4>
Learning It </h4>
Extensive documentation and example code here: <br />
<a href="http://iolanguage.org/scm/io/docs/IoGuide.html#Introduction">http://iolanguage.org/scm/io/docs/IoGuide.html#Introduction</a><br />
<br />
<h4>
Conclusion</h4>
Cool language, unfortunately probably not fully real-time safe / deterministic due to running in a VM.<br />
<br />
<h2>
Sum Up</h2>
"So what language will I use for my next project?" I hear you ask: well I'm staying with the tried and tested C++ for a while. I've dabbled with Vala previously ( see <a href="https://github.com/harryhaaren/ValaLooper">ValaLooper</a> and <a href="https://github.com/harryhaaren/prehear">Prehear</a> ), but they're not quite suitable to RT work in my opinion.<br />
<br />
Although its nice to work with a slightly higher level language, its hard to determine if the generated code is genuinely real-time safe.<br />
<br />
The perfect real-time safe code for me is code that is so simple, that proving its real-time safe under any conditions is trivial. Then the code is maintainable and readable.<br />
<br />
Know of any RT capable language I've left out? Get in touch: I'm interested in hearing about it!<br />
<br />Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-19854050753643618352013-02-10T13:45:00.001-08:002014-06-29T02:42:29.469-07:00LV2 and Atom communication<b>EDIT:</b> There are now better resources to learn LV2 Atom programming: please use them!<br />
<span id="bc_0_2b+seedhOUpD" kind="d"><a href="http://www.lv2plug.in/book">www.lv2plug.in/book</a></span><br />
<span id="bc_0_2b+seedhOUpD" kind="d"><a href="http://lac.linuxaudio.org/2014/video.php?id=24">http://lac.linuxaudio.org/2014/video.php?id=24</a></span><br />
<b>/EDIT</b><br />
<br />
<br />
Situation: You're trying to write a synth or effect, and you need to communicate between your UI and the DSP parts of the plugin, and MIDI doesn't cut it: enter Atom events. I found them difficult to get to grips with, and hope that this guide eases the process of using them to achieve communication.<br />
<h2>
<span style="font-size: large;"> </span></h2>
<h2>
<span style="font-size: large;">Starting out </span></h2>
I advise you to first read this : http://lv2plug.in/ns/ext/atom/<br />
It is the official documentation on the Atom spec. Just read the <br />
description. It gives a good general overview of these things called Atoms.<br />
<br />
This is "message passing": we send an Atom event from the UI to the DSP part of the plugin. This message needs to be safe to use in a real-time context.<br />
<br />
(Note it is assumed that the concepts of URIDs is familiar to you. If they're not, go back and read this article: <a href="http://harryhaaren.blogspot.ie/2012/06/writing-lv2-plugins-lv2-overview.html">http://harryhaaren.blogspot.ie/2012/06/writing-lv2-plugins-lv2-overview.html</a> ) <br />
<br />
Step 1: Set up an LV2_Atom_Forge. The lv2_atom_forge_* functions are how you build these events.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">LV2_Atom_Forge forge;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">lv2_atom_forge_init( &forge, map ); // map = LV2_URID_Map feature</span><br />
<h2>
</h2>
<h3>
<span style="font-size: large;">Atoms</span></h3>
<span style="font-family: inherit;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">Atoms are<span style="font-size: small;"> "plain old data" or P<span style="font-size: small;">OD</span></span></span></span></span></span><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">. They're a sequenc<span style="font-size: small;">e of by<span style="font-size: small;">tes written<span style="font-size: small;"> in a <span style="font-size: small;">contiguous</span> part of memory.</span></span></span></span></span> Moving them around is possible with a single memcpy() call.<br />
<h2>
<span style="font-size: large;"> </span></h2>
<h2>
<span style="font-size: large;">Writing Atoms</span></h2>
<h3>
<span style="font-family: "Courier New",Courier,monospace;">Understanding the URID naming convention</span></h3>
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">// we need URID's to represent functionality: There's a naming scheme here, and its *essential* to understand it. Say the functionality we want to represent is a name of a Cat (similar to the <a href="http://lv2plug.in/doc/html/forge_8h.html#a9d44677f4f5611ad91779ff5da293e8a">official atom example</a>). Here <b>eg_Cat</b> represents the "noun" or "item" we are sending an Atom about. <b>eg_name</b> represents something about the <b>eg_Cat</b>.</span></span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">something_Something represents an noun or item, while something_something (note the missing capital letter) is represents an aspect of the noun.</span></span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">LV2_URID eg_Cat;<br />LV2_URID eg_name; </span></span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-size: small;"><span style="font-size: small;">In short c</span>lasses and types are Capi</span>talized, and nothing else is.</span></span><br />
<br />
<h3>
<span style="font-family: "Courier New",Courier,monospace;">Code to write message<span style="font-family: inherit;">s</span></span></h3>
<span style="font-family: "Courier New",Courier,monospace;">// A frame is essentially a "holder" for data. So we put our event into a LV2_Atom_Forge_Frame. These frames allow the "appending" or adding in of data.</span><br />
<span style="font-family: "Courier New",Courier,monospace;">LV2_Atom_Forge_Frame frame;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br />// Here we write a "blank" atom, which contains nothing (yet). We're going to fill that blank in with some data in a minute.<span style="font-size: small;"> A blank is a dictionary of <span style="font-size: small;">key:<span style="font-size: small;">value pairs<span style="font-size: small;">. The property_head is the key, and the value comes after that.<span style="font-size: small;"> </span></span></span></span></span></span>Note that the last parameter to this function represents the noun or type of item the Atom is about.<br />
<span style="font-family: "Courier New",Courier,monospace;">LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_blank(<br /> &forge, &frame, 1, uris.eg_Cat );</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">// then we write a "property_head": this uses a URID to describe the next bit of data coming up, which will form the value of the key:value dictionary pair.<br />lv2_atom_forge_property_head(&forge, uris.eg_name, 0);<br /> </span><br />
<span style="font-family: "Courier New",Courier,monospace;">// now we write the data, note the call to forge_string(), we're writing string data here! There's a forge_int() forge_float() etc too!</span><br />
<span style="font-family: "Courier New",Courier,monospace;">lv2_atom_forge_string(&forge, "nameOfCat", strlen("nameOfCat") );</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br />// Popping the frame is like a closing } of a function. Its a finished event, there's nothing more to write into it. </span><br />
<span style="font-family: "Courier New",Courier,monospace;">lv2_atom_forge_pop( &forge, &frame);</span><br />
<h3>
<span style="font-family: "Courier New",Courier,monospace;"> </span></h3>
<h3>
<span style="font-family: "Courier New",Courier,monospace;">From the UI</span></h3>
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">// To write messages, we set up a buffer:</span> </span><br />
<span style="font-family: "Courier New",Courier,monospace;">uint8_t obj_buf[1024];</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br />// Then we tell the forge to use that buffer </span><br />
<span style="font-family: "Courier New",Courier,monospace;">lv2_atom_forge_set_buffer(&forge, obj_buf, 1024);</span><span style="font-family: "Courier New",Courier,monospace;"><br /></span><br />
<span style="font-family: "Courier New",Courier,monospace;">// now check the "Code to write messages" heading above, that code goes here, where you write the event.</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;">// We have a write_function (from the instantiate() call) and a controller. These are used to send Atoms back. Note that the type of event is atom_eventTransfer: This means the host should pass it directly the the input port of the plugin, and not interpret it. </span><span style="font-family: "Courier New",Courier,monospace;">write_function(controller, CONTROL_</span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">PORT_NUMBER</span>,</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> lv2_atom_total_size(msg),<br /> uris.atom_eventTransfer, msg);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<br />
<h3>
<span style="font-family: "Courier New",Courier,monospace;">From the DSP</span></h3>
<span style="font-family: "Courier New",Courier,monospace;">// Set up forge to write directly to notify output port. This means that when we create an Atom in the DSP part, we don't allocate memory, we write the Atom directly into the notify port.</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">const uint32_t notify_capacity = self->notify_port->atom.size;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">lv2_atom_forge_set_buffer(&self->forge,<br /> (uint8_t*)self->notify_port,<br /> notify_capacity);<br /> </span><br />
<span style="font-family: "Courier New",Courier,monospace;">// Start a sequence in the notify output port </span><br />
<span style="font-family: "Courier New",Courier,monospace;">lv2_atom_forge_sequence_head(&self->forge,</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> &self->notify_frame, 0);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;">Now look back at the "Code to write messages" section. that's it, write the event into the Notify atom port, and done.</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<br />
<h2>
<span style="font-size: large;">Reading Atoms</span></h2>
<br />
<span style="font-family: "Courier New",Courier,monospace;">// Read incoming events directly from control_port, the Atom input port</span><br />
<span style="font-family: "Courier New",Courier,monospace;">LV2_ATOM_SEQUENCE_FOREACH(self->control_port, ev)<br />{</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> // check if the type of the Atom is eg_Cat<br /> if (ev->body.type == self->uris.eg_Cat)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> // get the object representing the rest of the data<br /> const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body;<br /> </span><br />
<span style="font-family: "Courier New",Courier,monospace;"> </span><span style="font-family: "Courier New",Courier,monospace;"> // check if the type of the data is eg_name</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> if ( obj->body.otype == self->uris.eg_name )<br /> {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> // get the data from the body<br /> const LV2_Atom_Object* body = NULL;<br /> lv2_atom_object_get(obj, self->uris.</span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">eg_name</span>,</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> &body, 0);<br /> </span><br />
<span style="font-family: "Courier New",Courier,monospace;"> // convert it to the type it is, and use it<br /> string s = (char*)LV2_ATOM_BODY(body);<br /> cout << "Cat's name property is " << s << endl;<br /> }<br /> }<br />}</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<br />
<h2>
<span style="font-size: large;">C<span style="font-size: large;">onclusion</span></span></h2>
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">That's it. Its not hard. It just takes getting used to. Its actually a very powerful and easy way of designing a program / plugin, as it *demands* separation between the threads, which is a really good thing.</span></span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">Questions or comments, let me know :) -Harry</span></span>Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com3tag:blogger.com,1999:blog-6426055874900292298.post-47622525486632486802013-01-17T09:11:00.004-08:002013-01-17T09:28:31.085-08:00MlTutorial: Working with the MediaLovinToolkitHi!<br />
<br />
I've been interested in doing some video coding for a while now, but never really got into it yet. Until today, when I re-attempted (yes, I'd tried before :) to achieve some simple functionality with <a href="http://www.mltframework.org/">MLT</a>. <br />
<br />
Initially I found it very difficult to find any resources as to how one can use the MLT framework from C++, but some googling led me to various resources scattered around the internet.<br />
<br />
The MLT github repo as a super-simple example (which although informative doesn't scale up to the use of filters or any advanced functionality):<br />
<a href="https://github.com/mltframework/mlt/blob/master/src/examples/play.cpp">https://github.com/mltframework/mlt/blob/master/src/examples/play.cpp</a><br />
<br />
A search around the net showed me this post on a forum <a href="http://ubuntuforums.org/showthread.php?p=7370184">http://ubuntuforums.org/showthread.php?p=7370184</a><br />
This seemed to be more along the lines of what I had hoped for, however the code segfaults upon running...<br />
<br />
Finally the "tests" subdir in the MLT tarball provide some test program code, but its difficult to understand (IMO) as its not commented for learning purposes: <a href="https://github.com/mltframework/mlt/tree/master/src/tests">https://github.com/mltframework/mlt/tree/master/src/tests</a><br />
<br />
So between these resources I've decided to bunch together some examples of how to use MLT using C++. The code is online on github, and may be useful to others hoping to learn to use the MLT framework.<br />
<br />
There's currently two "playback" tutorials, and one "filter" tutorial. Reading them will show the rough design of the MLT library, and how to use it. Advanced functionality tutorials will be added as I learn it myself :)<br />
<a href="https://github.com/harryhaaren/mltutorial">https://github.com/harryhaaren/mltutorial</a><br />
<br />
Welcoming issues / merge requests from MLT users / devs / anybody!<br />
Cheers, -HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-57011034189087217782012-12-11T20:15:00.003-08:002013-01-25T12:17:05.764-08:00Getting to grips with GanvSo you want to create a "Graph" based program? Use Ganv! It looks awesome, and David Robillard has already done the hard parts :)<br />
<br />
<h3>
Starting Out: </h3>
We're just doing a single file, proof of concept right now. Nothing fancy yet.<br />
So you'll need to install:<br />
ganv<br />
gtkmm<br />
<br />
Easiest way to do this is just checkout Drobilla's svn:<br />
svn co http://svn.drobilla.net/lad/trunk drobillad<br />
<br />
./waf configure --prefix=/usr<br />
./waf<br />
./waf install<br />
<h3>
What next:</h3>
Install ganv system wide. Download this tutorial's code from here: <a href="https://github.com/harryhaaren/openAudioProgrammingTutorials/blob/master/flowCanvas/flowcanvas.cpp">https://github.com/harryhaaren/openAudioProgrammingTutorials/blob/master/flowCanvas/flowcanvas.cpp</a><br />
<br />
Read the code, its pretty self explanatory.<br />
<br />
<h3>
Then what?</h3>
Its a good idea to get to grips with how all this works together:<br />
<br />
Ganv: is the way you interface with the whole<br />
FlowCanvas: is the canvas itself, behind the scenes.<br />
GTKmm: is your window, and you do what you like with it.<br />
<br />
So the final structure is somewhat like this:<br />
Gtk window<br />
Ganv Canvas<br />
Ganv Module<br />
Ganv Port<br />
Ganv Edge (connects ports)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmfX5fosgLBbQYKLP0_vx3a5q-Davt3xqDWjmZLy1Fc5jjsGyWYjdMiQXkt084NH2708Ok72yrex4pTgwYpgwGBRhL_0yRIA9oH5Fdd4cj-WZLDTwQNpezPRPHVYC-lKweveRNUn5sKxG1/s1600/flowCanvas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmfX5fosgLBbQYKLP0_vx3a5q-Davt3xqDWjmZLy1Fc5jjsGyWYjdMiQXkt084NH2708Ok72yrex4pTgwYpgwGBRhL_0yRIA9oH5Fdd4cj-WZLDTwQNpezPRPHVYC-lKweveRNUn5sKxG1/s1600/flowCanvas.png" /></a></div>
<br />
<br />
That's all for now, hope I saved you a bit of time and effort! -HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com1tag:blogger.com,1999:blog-6426055874900292298.post-71728634733407669222012-11-19T16:58:00.000-08:002012-11-19T16:58:50.605-08:00Luppp: Status as of Nov '12?Hey everybody,<br />
<br />
I'm writing to let you all know that the Luppp project is not dead. I've not posted here about Luppp since May, and also haven't pushed code to the <a href="https://github.com/harryhaaren/Luppp">repo at github</a> for 6 months. So what is the status?<br />
<br />
Luppp is "taking the back seat" for a while. I mean that real-life has currently taken over, and with my <a href="http://www.csis.ul.ie/currentcourse/LM114/">final year of college</a> and projects on, I don't see myself spending a lot of time on Luppp before the next LAC (that's the middle of May).<br />
<br />
Don't worry, the reason for not pushing code recently is only partly due to time, the other reason is that during the summer I started doing (another...) total re-write. This time I'm confident that the code is a lot more maintainable. I hope :)<br />
<br />
Till next, -HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com2tag:blogger.com,1999:blog-6426055874900292298.post-53585027958804771092012-07-09T05:47:00.001-07:002012-07-09T05:57:27.431-07:00Writing Lv2 GUI's: Making it look snazzy<h2>
</h2>
So we know how to build a basic "amp" plugin, but there's no GUI. We like shiny gui's right? Of course we do :) This tutorial will explain how to make one.<br />
<br />
<h2>
<span style="font-size: large;">Gooeys - Or GUI's:</span></h2>
The GUI part of a plugin can be viewed as a totally separate entity to the "DSP" or audio part of the plugin. We will call these the "halves" of our plugin. Theres a little bit of theory to cover before we start looking at code. The next communication section describes how the DSP and GUI parts of the plugin can inform eachother about whats going on.<br />
<br />
<h2>
<span style="font-size: large;">Communication:</span></h2>
So the GUI runs in the "GUI" part of the host program, and the DSP runs in the audio part of the host program. We can't communicate directly between the halves due to details that don't really concern us. (<strike>threading and thread safety if you must know</strike>..)<br />
<br />
How it works: The two parts of our plugin are loaded into the two parts of the host program. How we communicate between the two "halves" of our plugin is by using Lv2 ports. These ports send communicate data between the host and the plugin. The host can then use that same data to update the GUI.<br />
<br />
Similarly the GUI can write data, which will then be sent to the audio half by the host. That's all there is to it!<br />
<br />
<h2>
<span style="font-size: large;">Choosing a toolkit</span></h2>
So there's a lot of GUI toolkits out there. The most prominent open-source ones are GTK and QT. This tutorial will explain how to create a custom GTK interface for an Lv2 plugin. My reason for choosing GTK? Its what I know. I also like it. If somebody would contribute code for doing the same in QT, I will gladly link to it from here.<br />
<br />
Please note that I'm using the C++ wrapper around GTK (called GTKmm), and I use version 2, not the new stable GTK 3. I know that GTKmm 2 works, and have no reason to update to GTKmm 3.<br />
<br />
Side note (skip if you want to get hands-on GUI writing): The loading of GUI plugins into hosts is done using the <a href="http://www.google.ie/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&ved=0CGUQFjAD&url=http%3A%2F%2Fdrobilla.net%2Fsoftware%2Fsuil%2F&ei=-7b6T7zrI4PftAa_xYy7BQ&usg=AFQjCNEYfrupUjJxOGF6JG-zwoatERcukQ" target="_blank">SUIL library</a>. It is useful to know that it has certain toolkits that it supports, currently X11, GTK2 and QT. If you want to use a different toolkit please read the <a href="http://drobilla.net/software/suil/" target="_blank">SUIL library page</a>.<br />
<br />
<h2>
<span style="font-size: large;">Making a GUI</span></h2>
So what do we actually do to get a GUI for an Lv2? We write a widget. If you're not at all familiar with GUI programming, I will suggest you look at the GTKmm2 Drawing Area tutorial code: <a href="http://developer.gnome.org/gtkmm-tutorial/2.24/chapter-drawingarea.html.en" target="_blank">Drawing a custom widget using a GTK::DrawingArea</a>. When we have a widget created, we need to pass that widget to the Lv2 host, which will display it for us.<br />
<br />
<h2>
<span style="font-size: large;">Code</span></h2>
Yes. Where is it? There is a copy of the Lv2 repo on my Github, where I will publish the code for this tutorial. Chances are that these tutorials will be merged into the main Lv2 examples from the Github page.<br />
<br />
<h2>
<span style="font-size: large;">Communication in code</span></h2>
So we talked about the theory of communication between the halves, but how do we actually do that in code? The Lv2 UI extension that we use to load the GUI gives us two "things" that we need to write port events from the GUI to the host. What these things represent is not really important: we just need to use them. (<strike>if you must know: <b>LV2UI_Controller</b> is a pointer to the host's own stuff, and <b>LV2UI_Write_Function</b> is a function pointer that will do the work</strike>)<br />
<br />
<a href="https://github.com/harryhaaren/lv2/tree/dce275045d609625f4ffa5f4ae5e4c9f55093edf/plugins/eg-sinsynth.lv2">Github Lv2 repo: SinSynth folder at commit while writing this tutorial</a><br />
<br />
<br />
<h2>
<span style="font-size: large;">Writing port events in the GUI</span></h2>
So we have these two things: <b>LV2UI_Controller</b> and <b>LV2UI_Write_Function</b>, how do we use them? More theory first. Events happen in the Widget, ie: if the user clicks, our Widget gets a function called. That function must decide what to do, and then call the write_function().<br />
<br />
What this means in practical terms, is that the Widget class needs access to the <b>LV2UI_Controller</b> and <b>LV2UI_Write_Function</b>.<br />
<br />
The way that I solve that, is by adding the <b>LV2UI_Controller</b> and <b>LV2UI_Write_Function</b> to the Widget class. Some people might say this is ugly design: but its simple and works well.<br />
<br />
Look at Widget::on_button_press_event to see the code in action.<br />
<h2>
</h2>
<h2>
<span style="font-size: large;"> </span></h2>
<h2>
<span style="font-size: large;">Testing the plugin</span></h2>
<span style="font-size: large;"><span style="font-size: small;">There's a program called Jalv, which is a great little host to test out your Lv2 plugins with: I've used it to develop this tutorial and the GUI for the tutorial. Grab it here: <a href="http://drobilla.net/software/jalv/">http://drobilla.net/software/jalv/</a></span></span><br />
<span style="font-size: large;"><br /></span><br />
<span style="font-size: large;"><span style="font-size: small;">Running <b>jalv.gtk http://lv2plug.in/plugins/eg-sinsynth</b></span></span><br />
<span style="font-size: large;"><span style="font-size: small;">gives me this<b> </b>screenshot<b>, </b>clicking it will change the frequency!</span></span><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqqla5w019azuv0ixkp7CMp-ZX18RPBBY9hLPDKffT7sB5UlWuoGDgrPmbvHViLbitod2FeMuLlM67tKxqFWZTsigCa6oQ33jKQfFF5nEOvActQ3qziAk1enIaaUT0qdDntA8V4DEMToMd/s1600/sinsynth.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqqla5w019azuv0ixkp7CMp-ZX18RPBBY9hLPDKffT7sB5UlWuoGDgrPmbvHViLbitod2FeMuLlM67tKxqFWZTsigCa6oQ33jKQfFF5nEOvActQ3qziAk1enIaaUT0qdDntA8V4DEMToMd/s1600/sinsynth.png" /></a></div>
<span style="font-size: large;"><span style="font-size: small;"><b><br /></b></span></span><br />
<span style="font-size: large;"><span style="font-size: small;"><b> </b></span> <span style="font-size: small;"><br /></span></span><br />
<h2>
<span style="font-size: large;">That's all!</span></h2>
You'<span style="font-size: large;"><span style="font-size: small;">ve now made a custom GUI, that should work as a Lv2 plugin gui. Sure its not UI artwork yet, but I'll leave you to explore Cairo and its cool graphics functions on your own for a while ;)</span></span>Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-85781357053829273802012-06-11T17:50:00.001-07:002012-06-12T06:24:42.746-07:00Writing Lv2 plugins : An Lv2 Overview<h2>
</h2>
Although I'm relatively aware of what Lv2 is, and also relatively aware of how it works, and relatively know how to <a href="https://github.com/harryhaaren/Lv2Host" target="_blank">write a "host" class</a>: what's inside an Lv2 plugin???<br />
<br />
Starters: I'm assuming you know a bit of C/C++, you know what a plugin is, and you're well able to use a terminal. I'm <u>not</u> assuming you know much about plugin specs, Lv2 URI's, manifest files, or Turtle RDF. These things will become apparent as we go along.<br />
<br />
For this tutorial, I'm going to talk us trough the "eg-amp" code, that comes with the lv2 source code. If you don't have it yet, grab it <a href="http://lv2plug.in/spec/lv2-1.0.0.tar.bz2" target="_blank">now</a>. Extract, and <span style="font-family: "Courier New",Courier,monospace;">/plugins/eg-amp.lv2/</span> shows you the sources.<br />
<br />
<h2>
<span style="font-size: large;">Introduction:</span></h2>
Lv2 works by defining URI's. A URI means *nothing*. It is a string, that contains a unique identifyer for *stuff*. Usually it is in the form of a http:// address, and that web link will show you more info on the plugin. Don't fret about details, just remember this:<br />
<div style="text-align: center;">
<b>A URI IS AN IDENTIFIER FOR THINGS</b></div>
<br />
Lv2 plugins come in "bundles". A bundle contains one or more plugins. For simplicity, this example contains only one plugin. A bundle is just a directory, with three files inside:<br />
<ol>
<li>manifest.ttl</li>
<li><pluginName>.ttl</li>
<li><pluginName>.so</li>
</ol>
The other files (waf and wscript) are only to compile the source code into the binary plugin, and install them. Of course any other build system can be used to compile Lv2 plugins too!<br />
<br />
<h2>
<span style="font-size: large;">Walk trough of the files:</span></h2>
<h4>
Manifest.ttl</h4>
This file lists all plugins that can be found in the bundle. For this example, there's only one. The file has various different bits of information about the bundle its contained in, and this information defines the plugin.<br />
<br />
The eg-amp manifest contains this:<br />
<span style="font-size: x-small;"><b><span style="font-family: Arial,Helvetica,sans-serif;">@prefix lv2: <http://lv2plug.in/ns/lv2core#> .</span><br style="font-family: Arial,Helvetica,sans-serif;" /><span style="font-family: Arial,Helvetica,sans-serif;">@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .</span><br style="font-family: Arial,Helvetica,sans-serif;" /><br style="font-family: Arial,Helvetica,sans-serif;" /><span style="font-family: Arial,Helvetica,sans-serif;"><http://lv2plug.in/plugins/eg-amp></span><br style="font-family: Arial,Helvetica,sans-serif;" /><span style="font-family: Arial,Helvetica,sans-serif;"> a lv2:Plugin ;</span><br style="font-family: Arial,Helvetica,sans-serif;" /><span style="font-family: Arial,Helvetica,sans-serif;"> lv2:binary <amp.so> ;</span><br style="font-family: Arial,Helvetica,sans-serif;" /><span style="font-family: Arial,Helvetica,sans-serif;"> rdfs:seeAlso <amp.ttl> .</span></b></span><br />
<br />
<span style="font-size: small;">First of all</span> two "convenience" prefix' are defined. The core Lv2 URI, and the RDF scheme URI.<br />
<br />
Next we declare a URI. It is the <b>unique</b> string, that when used always means exactly this object. Afterwards, some details about the "resource" are added:<br />
The resource <span style="font-size: x-small;"><b><span style="font-family: Arial,Helvetica,sans-serif;"><http://lv2plug.in/plugins/eg-amp> </span></b><span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-size: small;">has the property</span></span><b><span style="font-family: Arial,Helvetica,sans-serif;"> </span><span style="font-family: Arial,Helvetica,sans-serif;"> </span><span style="font-family: Arial,Helvetica,sans-serif;">lv2:Plugin, </span></b><span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-family: inherit; font-size: small;">the property</span></span><b><span style="font-family: Arial,Helvetica,sans-serif;"> lv2:binary </span></b><span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-size: small;"><span style="font-family: inherit;">and for more info look at <b><span style="font-family: Arial,Helvetica,sans-serif; font-size: x-small;"><amp.ttl></span></b></span></span></span></span>.<br />
<h4>
<br /><PluginName>.ttl</h4>
This file contains all the details about the plugin: think "Who what when how where"?. I won't paste the code here,the 85 lines would clog up this post. I'll talk you through it though, dont' worry!<br />
<br />
First section after the license (lines 17-21):<br />
One can declare some RDF data to show the "author" of a plugin. This can point to your own website, or else a company website.<br />
<br />
The next section (lines 29-87) contain the implementation details of the plugin: things like the Maintainer of the plugin, the name of the plugin, the license, the plugins "features", and what "ports" it exposes.<br />
<br />
<h4>
<PluginName>.so</h4>
Finally: the binary file, that a host will load, and use to do whatever the plugin does. Not much more to say really!<br />
<br />
<h2>
<span style="font-size: large;">Lv2 Extensions </span></h2>
An extension is a definition of some extra functionality, that isn't contained in the core lv2 spec. These definitions have their own unique URI, and each has its own .ttl and C header files. <br />
<br />
Since Lv2 is a "modular" or "extensible" format, anybody can write a Lv2 Feature, and then write plugins or hosts to use that feature. Note that not all hosts support every feature, so using "rare" features may mean you plugin can't be used in a host somebody else wrote. <br />
<br />
<h2>
<span style="font-size: large;">Lv2 Ports</span></h2>
(If you are familiar with LADSPA ports, skip this section: they're pretty similar)<br />
Ports are a way to transfer data between the plugin and the host. There are various types of ports, some built into the "lv2-core" spec (always available in every host) and some that are "feature" ports, (ie contained in a feature extension to lv2, and perhaps not every host supports it).<br />
<br />
Most ports send float values around, like in the eg-amp:<br />
<div style="font-family: Arial,Helvetica,sans-serif;">
<span style="font-size: x-small;"><b>lv2:port [<br /> a lv2:InputPort ,<br /> lv2:ControlPort ;<br /> lv2:index 0 ;<br /> lv2:symbol "gain" ;<br /> lv2:name "Gain";<br /> lv2:default 0.0 ;<br /> lv2:minimum -90.0 ;<br /> lv2:maximum 24.0 ;</b></span></div>
<span style="font-size: x-small;"><b style="font-family: Arial,Helvetica,sans-serif;"> ]</b></span><br />
<br />
<span style="font-size: small;">The above RDF snipped defines a port, its an input port (to the plugin), its a </span>control rate port (not audio), its index is 0, and it changes the "Gain" parameter of the plugin. Pretty readable right? I'll leave the rest to you! :D<br />
<br />
<h2>
<span style="font-size: large;">Compiling eg-amp</span></h2>
So to get the eg-amp lv2 bundle compiled and running you've a couple of steps to take:<br />
./waf configure will setup Waf so it knows how to build<br />
./waf will compile & link the files<br />
./waf install moves the .lv2 bundle to /usr/local/lib/lv2/ (by default)<br />
<br />
Note that doing a<br />
./waf configure --strict --debug --prefix=/usr<br />
will enable strict compiler checks, a debug build, and install in /usr/lib/lv2/<br />
<br />
Test the plugin using any Lv2 host, Ardour, QTractor, Jalv, lv2rack, zynjacku : they should all work, assuming they're up to date!<br />
<br />
<h2>
<span style="font-size: large;">Finished!</span></h2>
That's most of the main topics of Lv2 covered: you now have a decent understanding of what is necessary to write Lv2 plugins. In a future post I hope to cover the details of eg-amp.lv2, and the C code it consits of. Also intended is to post about how to implement extra features; both for hosts and plugins. But that'll remain for another day.<br />
<br />
PS: Comments and changes welcomed: I'm new to writing Lv2 plugins myself, and I'm sure that improvements can be made on this post!Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com6tag:blogger.com,1999:blog-6426055874900292298.post-90409342311630723842012-05-02T02:11:00.000-07:002012-05-02T02:11:02.607-07:00Luppp milestone: Timestretch!Although its been a relatively quite period for development (due to lots of deadlines) today one of Luppp's long term goals has been reached: on-the-fly time stretching per track.<br />
<br />
For the non-techie: This means that you can play a melody loop, and slow it down or speed it up, and the audio will remain in the same key! (No turntable RPM effect? Nope :)<br />
<br />
Mandatory examples:<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/wZElxE7vTwk?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/QJBjl3XlxDE?feature=player_embedded' frameborder='0'></iframe></div>
Although I'd call the quality "passable" is obviously not fantastic but there's some parameters in the algorithm that are available to tweak, so I hope to be able to improve it a bit a least :)<br />
<br />
So when is a beta release?? Don't hold your breath, sorry. There's still some work to be done before Luppp will be ready for prime-time, but until then feel free to test it if you're interested!<br />
<br />
Will keep you posted, -HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com3tag:blogger.com,1999:blog-6426055874900292298.post-78776264949076968842012-04-15T11:12:00.002-07:002012-04-15T11:12:45.539-07:00LAC performanceHey All,<br />
<br />
With the LAC on at the moment, its a prime time to do some extra development on features that need some finishing before being fully useful. That has been going on, and now the AutoMove feature allows the changing of the length of the fade. Currently the mapping to change the length is set to right click, that needs to be changed as we can only cycle up in length. Current options for beat lengths are 2, 4, 8, 16, and 32.<br />
<br />
Also fixed was the "Master Beat Indicator", (the moving widget <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1GidX0GI4XipSBzUE-vXXegYABom9iHA9hnXb_4GZopvgVkQaP8HDZMkTlbY6YJaqpQ7avLhIqLyRVkaD387AEvfoGnQmHBP6Qg9ckwOQ0-I0sRR4oh6DKB-ziXbZjnxvll8GVeOz1mg1/s400/progress.gif" target="_blank">here</a>). It now just syncs to JACK tempo, and will display which of the beats between 1 and 4 we're on. Since the AutoMove function is triggered on a downbeat (every 4th beat) the tempo indicator shows when the AutoMove fade will come into effect.<br />
<br />
The current git head (master branch) is the exact version of Luppp that I used for the performance at the LAC Sound Night yesterday. Many thanks to <a href="http://www.louigiverona.ru/" target="_blank">Luigi Verona</a> for his <a href="http://www.louigiverona.ru/?page=projects&s=music&t=droning" target="_blank">droning series</a> which was the basis for the piece.<br />
<br />
Greetings from the LAC, -HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-6863212701604430102012-04-11T18:28:00.001-07:002012-04-11T18:28:30.134-07:00Luppp : Scopes and SendsNew features have arrived in the devel branch:<br />
-Interaction with the sends & return widgets<br />
-Scope that displays the master output_W channel<br />
<br />
Various code improvements have also been pushed along the way, be it that the headphones volume dial now goes up when you move up, or that that post-fade send now adhere's to the Mute status of the track.<br />
<br />
Its another small step along the way! Mandatory screeny:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbVz65ZADQ_rMfc3sdsSXBVMSWTRYl-JGTeA0K-ZqAoloqC9BoPu8gBsME0xnT24_b2I4m2HutC5sxmstgTQCykhy9Q-362jhLjyGRjggeZIOy803ngxwSL97wiYbHIzA4YnhisQLCY1IK/s1600/newui.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbVz65ZADQ_rMfc3sdsSXBVMSWTRYl-JGTeA0K-ZqAoloqC9BoPu8gBsME0xnT24_b2I4m2HutC5sxmstgTQCykhy9Q-362jhLjyGRjggeZIOy803ngxwSL97wiYbHIzA4YnhisQLCY1IK/s320/newui.png" width="320" /></a></div>
<br />Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-65246881037707382462012-03-21T17:19:00.002-07:002012-03-21T17:20:19.460-07:00Luppp: New Feature! AutoMoveOver the last days a new feature was designed & implemented: AutoMove.<br />
<br />
The idea is simple; in a live situation you just don't have time to write automation lines, not even simple ones! You also don't have a hand free to turn up your reverb during the next 16 bars, so what do you do? AutoMove it!<br />
<br />
The following GIF animation of screenshots gives it all away:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKofefc1kvAj_Enuqwy4nvMzygquL9HdhdCdpf7fBhV_KiyUBRJtsAikt6p7XcE_JM-96fY88Wk9aAaJ0ocGGqhfFrHX6TZaKbHX-n6xjs0dyN6nIzU0YEyMc0FfnmQ__1810XjjLa8Giy/s1600/lupppAutoMove.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="321" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKofefc1kvAj_Enuqwy4nvMzygquL9HdhdCdpf7fBhV_KiyUBRJtsAikt6p7XcE_JM-96fY88Wk9aAaJ0ocGGqhfFrHX6TZaKbHX-n6xjs0dyN6nIzU0YEyMc0FfnmQ__1810XjjLa8Giy/s400/lupppAutoMove.gif" width="400" /></a></div>
<br />
There are preset automation lines, and widgets that are active get scaled by the AutoMove's value. You press one button, and it does the rest. Now we're making music :)<br />
<br />
Available in the master branch as of right now!Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-9321694784097769692012-03-16T19:36:00.000-07:002012-03-16T19:36:37.177-07:00Luppp: Alpha 1<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRxkBoc8GedRKibXbB67sLWetElM1BEwtKqU0e2zh1_K_ZrIMqJ6ZLHptk0hb03xkoKuYsbSBWOq3jVy6ISougozIx4ZuDNPP_mx_yrz7DeX8VudfJYmF4ht4Oc7oKw8nCsmFyk1q3X39h/s1600/alpha1closed.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="78" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRxkBoc8GedRKibXbB67sLWetElM1BEwtKqU0e2zh1_K_ZrIMqJ6ZLHptk0hb03xkoKuYsbSBWOq3jVy6ISougozIx4ZuDNPP_mx_yrz7DeX8VudfJYmF4ht4Oc7oKw8nCsmFyk1q3X39h/s400/alpha1closed.png" width="400" /></a></div>
<br />
Alpha 1 status: <br />
100% - Closed<br />
<br />
<br />
<br />
Today the last bug on the Alpha1 milestone has been closed, hence also the alpha1 release of Luppp 2.0. In a way this is a big occasion, its the first official release!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7GDdgC3lOC9qahKg6xCgJVDNHDZq742wsCD4yRv0dBr-uJFzd_mYpP_59HI1dqWVOEpaxNZ2mPWaGCaVfdqb7jWgf0zNJez0E_qyGuj6PnmjeaxH-hrApzsS9GSet9YsinmalDjlwYNQi/s1600/lupppAlpha1.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7GDdgC3lOC9qahKg6xCgJVDNHDZq742wsCD4yRv0dBr-uJFzd_mYpP_59HI1dqWVOEpaxNZ2mPWaGCaVfdqb7jWgf0zNJez0E_qyGuj6PnmjeaxH-hrApzsS9GSet9YsinmalDjlwYNQi/s400/lupppAlpha1.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Alpha1 in action, with various effects and clips!</td></tr>
</tbody></table>
<br />
<br />
On the other hand, there's still a bucket load of work to be done before Luppp will be comfortable to use without various hardware controllers. I'm aware that there's lots of half-finished, half broken as well as broken stuff! Hey its still alpha!<br />
<br />
Current milestone: <a href="https://github.com/harryhaaren/Luppp/issues?sort=created&direction=desc&state=open&page=1&milestone=3" target="_blank">Alpha2</a><br />
There's already a list of bugs / feature requests up! There's also many GUI issues that are known and NOT there, but I'd prefer fix them than waste time posting a bug report.<br />
<br />
Welcoming (adventurous alpha) testers, any issues will be dealt with as promptly as possible! Please file bug reports here: <a href="https://github.com/harryhaaren/Luppp/issues/new">https://github.com/harryhaaren/Luppp/issues/new</a>Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com1tag:blogger.com,1999:blog-6426055874900292298.post-21537971573843048232012-03-07T10:01:00.001-08:002012-03-07T10:02:19.968-08:00Luppp: New Effects interfaceAfter a "push" quiet period, I've just pushed up a couple of branches changes: <br />
-Luppp's GUI has had a bit of work<br />
-Effect control from the APC40 has been revamped<br />
-Effects sends have been implemented<br />
<br />
-The GUI now shows the effects under the track, in a small widget: reasons? Now you can always see the state of all your effects, not just the ones on your currently selected track. Better for live situations!<br />
<br />
-The APC40 has 8 buttons under the Device controls, they now each map to Effect on/off. They're labelled for a different purpose, but I find this use quite intuitive.<br />
<br />
-Post fader sends are implemented, including widget representing the state. The GUI widget doesn't work yet (ie won't change the value) but it does update upon a controller change.<br />
<br />
I've pushed the changes to devel, but also the master branch, AFAIK its stable.<br />
<br />
<br />
Screeny:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN6aa_M_QNFzgDd91IAljOw-60_NCg1NPmQpiHHBKhGrfex1xMJeryZyc9Ci52bh-Reb6PZ8DJlADXo7doMBz1r-Vh3NSxFsG2XFH8osYVMqArMcWielotj3dLmlYA5SN-FWGUL_kuD_3c/s1600/newSendsAndEffects.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN6aa_M_QNFzgDd91IAljOw-60_NCg1NPmQpiHHBKhGrfex1xMJeryZyc9Ci52bh-Reb6PZ8DJlADXo7doMBz1r-Vh3NSxFsG2XFH8osYVMqArMcWielotj3dLmlYA5SN-FWGUL_kuD_3c/s1600/newSendsAndEffects.jpg" /></a></div>
<br />
<br />
<br />Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com3tag:blogger.com,1999:blog-6426055874900292298.post-46095359324995579042012-01-17T16:28:00.000-08:002012-01-17T17:00:16.795-08:00Luppp: Settling into GithubIn the last couple of days the Luppp repo has made a new home on github, now complete with issue tracker & wiki.<br />
<br />
The "manual" for Luppp will be constructed slowly in the Wiki part of github:<br />
<a href="https://github.com/harryhaaren/Luppp/wiki">https://github.com/harryhaaren/Luppp/wiki</a><br />
<br />
It currently contains some info on how to download & build:<br />
<a href="http://wiki.github.com/harryhaaren/Luppp/downloading-building-installing">http://wiki.github.com/harryhaaren/Luppp/downloading-building-installing</a><br />
<br />
as well as a basic overview of what does what in the GUI:<br />
<a href="https://github.com/harryhaaren/Luppp/wiki/Interface-Overview">https://github.com/harryhaaren/Luppp/wiki/Interface-Overview</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1GidX0GI4XipSBzUE-vXXegYABom9iHA9hnXb_4GZopvgVkQaP8HDZMkTlbY6YJaqpQ7avLhIqLyRVkaD387AEvfoGnQmHBP6Qg9ckwOQ0-I0sRR4oh6DKB-ziXbZjnxvll8GVeOz1mg1/s1600/progress.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1GidX0GI4XipSBzUE-vXXegYABom9iHA9hnXb_4GZopvgVkQaP8HDZMkTlbY6YJaqpQ7avLhIqLyRVkaD387AEvfoGnQmHBP6Qg9ckwOQ0-I0sRR4oh6DKB-ziXbZjnxvll8GVeOz1mg1/s400/progress.gif" width="271" /></a></div>
<br />
<br />
<br />
Also new: A master "progress" widget that shows time into your 4 bars, or time till the next "4th queue" process, ie: Event quantization.<br />
<br />
Read "<b>When it goes from red to green, your Scene will change."</b><br />
<br />
Fancy GUI suggestions welcomed, I don't really know how to spice this one up yet...<b><br /></b><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
Hopefully in the next couple of days I can update it some more, and fix a couple of critical bugs that really hinder the use of scenes. More news soon!Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-18395968833785838872012-01-14T08:22:00.000-08:002012-01-17T16:24:09.950-08:00Luppp : Source opened, but still pre-alpha!Hi All!<br />
<br />
With recent changes in the world of live looping software I've decided to open my private repo of Luppp.<br />
<br />
The Luppp project has been one of my main occupations over the last
couple of years, and I've tought myself C++ programming while working on
it. Its a live looping instrument with similar features to the well
known software Ableton Live, and more recently Bitwig studio. I feel the
live workflow available with such programs is something the Linux Audio
community would also benefit from, and hence it will be released under
the GPL license, version 3.<br />
<br />
Its current state is that most "basic" functionality is in place:
Loading, playing back & recording of loops works, effects can be
added to these audio streams, and later they are mixed. A basic config
file is used to store information about loops, and hence Luppp can make
more informed decisions how to use loops.<br />
<br />
This is pre-alpha software, as not all features to fullfill alpha state
are implemented. On the other side, most features currently available
are quite stable (on my local machine anyway :)<br />
<br />
I would like to announce that I will continue to work on the Luppp project myself, but that I do also welcome input / testing / help from other developers. I am aware that there are some basic enough flaws in the program in its current state, however these are also the primary items on my TODO list.<br />
<br />
Remember its <b>pre-alpha</b>, please keep that in mind :)<br />
Git source repo: <a href="https://github.com/harryhaaren/Luppp">https://github.com/harryhaaren/Luppp</a><br />
ZIP of master branch: <a href="https://github.com/harryhaaren/Luppp/zipball/master">https://github.com/harryhaaren/Luppp/zipball/master</a><br />
<br />
If you're intrested in working on Luppp, have a feature request, have ideas, time, or want to build Luppp a website, feel free to get in contact!!<br />
Cheers, -Harry<br />
<br />
Mandatory screenshot (note your GTK theme will influence its looks, this is on the todo! ):<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3m2FKlf7Tc7AhO_UrYiKwwqLyaXWE606pnj8xco9dqiodZArslbjFLtuKK7OD0pynw64I57E4_XYiCSve6suleqd_oFpkL2gQVZHFmFQnhwUDwPuC_C_JUbB76cuLP9Xf61jyZyVBwbLw/s1600/lupppFileRecordMaster.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3m2FKlf7Tc7AhO_UrYiKwwqLyaXWE606pnj8xco9dqiodZArslbjFLtuKK7OD0pynw64I57E4_XYiCSve6suleqd_oFpkL2gQVZHFmFQnhwUDwPuC_C_JUbB76cuLP9Xf61jyZyVBwbLw/s400/lupppFileRecordMaster.png" width="400" /></a></div>
<br />Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com13tag:blogger.com,1999:blog-6426055874900292298.post-38580903027301320882011-12-19T18:29:00.001-08:002011-12-19T18:31:07.240-08:00Tutorial: Load & Loop SamplesHey all,<br />
<br />
This tutorial will show you how to load a sample into memory, and
then play it back trough a JACK port, continually looping. There's not
really that much to it, just a bit of thinking of the order things
happen, and arrays.<br />
<br />
If you've read the "Writing a sample" tutorial,
you'll already be familiar with LibSndFile, the library we use to read /
write samples, so there's nothing too hard to handle :)
<br />
<br />
Check out the source here: <a href="https://github.com/harryhaaren/Linux-Audio-Programming-Documentation/blob/master/loopedSample/loopedSample.cpp">https://github.com/harryhaaren/Linux-Audio-Programming-Documentation/blob/master/loopedSample/loopedSample.cpp</a>
<br />
<br />
Any queries / suggestions, you know how to get to me :) -HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-43061482735730043952011-12-17T08:43:00.000-08:002011-12-17T08:43:42.934-08:00Arch Linux : The quest for a minimal system with maximal RT performanceHey All,<br />
<br />
My install of TangoStudio is getting old, and its repos are getting polluted with conflicts & nastiness, that means a reinstall! So a quick bit of searching for a minimal yet configurable, RT capable and rock-solid led to some intresting distro choices.<br />
<br />
TangoStudio - Worked well enough ( 30ms lowest lat on stock kernel )<br />
64Studio - a touch oudated by now, but it was always very good<br />
Pure::Dyne - personal favorite for a while, also gone a touch out of date<br />
Gentoo - probably not good for a non-kernel hacker type... but then<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://d11xdyzr0div58.cloudfront.net/main-20111101/media/logos/archlinux-logo-dark-90dpi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="105" src="http://d11xdyzr0div58.cloudfront.net/main-20111101/media/logos/archlinux-logo-dark-90dpi.png" width="320" /></a></div>
<br />
Arch has been a distro I've tried a couple of times because I love the sound of it:<br />
<blockquote class="tr_bq">
<b>Arch Linux</b>, a
lightweight and flexible Linux® distribution that tries to Keep It
Simple.</blockquote>
However any time I tried it I had been put off by its "initial configuration" that needs doing before you can get yourself online to look at some forums / wiki's for help!<br />
<br />
So off I went, download the <b>380mb</b> ISO, install it on a seperate partition, get going. You get a minimal system that drops to a root prompt on install, and "startx" isn't going to help much untill you install you video driver packages etc. Note this can be done during install but I opted not to, as I wanted the control to select only needed packages.<br />
<br />
So after a bit of haggling with the X server, reading some <a href="https://wiki.archlinux.org/index.php/Official_Installation_Guide">wiki entries</a> using the text only webbroswer <b>links</b>, and installing the "slim" display manager, messing with <b>/etc/inittab</b> and <b>~/.xinitrc</b> there's a system up and running, straight to a graphical logic screen (with awesome "darch-white" theme") and then to a barebones <b>LXDE</b> desktop with <b>OpenBox</b> as WM.<br />
<br />
The speed of the menu's & actions in unreal, it feels like its there before you clicked. Some small issues with ugly themes and nasty font's were quickly ironed out using <b>lxapperance</b>.<br />
<b> </b><br />
Couple of "nasty" little things:<br />
-Hotkeys: <a href="https://wiki.archlinux.org/index.php/Xbindkeys">https://wiki.archlinux.org/index.php/Xbindkeys</a><br />
-Keymap: <a href="https://wiki.archlinux.org/index.php/Beginners%27_Guide#LOCALIZATION_section">https://wiki.archlinux.org/index.php/loadkeys</a><br />
-Touchpad: <a href="https://wiki.archlinux.org/index.php/Touchpad_Synaptics">https://wiki.archlinux.org/index.php/Touchpad</a> <br />
<br />
Then on to the audio side of things:<br />
There's a project called <b>ArchAudio</b>, who are maintaining lots of up to date software for audio / multimedia purposes, you'll want to install that repo:<br />
<a href="http://archaudio.org/packages/">http://archaudio.org/packages/</a> has all the info you'll need!<br />
<br />
I'm a JACK1 user, so first thing I wanted to do was install that:<br />
the "Extra" repository has a build of 0.121.3, so a simple <b>pacman -S extra/jack1</b> done the trick. <b>FFADO</b> installation for my Echo AudioFire was quick and painless: <b>pacman -S libffado</b> That installs your needed library, the ffado-mixer, ffado-test etc programs, and sets up the privelidges so that you can run JACK in RT mode. <br />
<br />
If you want to use this install as your "daily", you'll need to install a mountain of stuff, things like gtkmm,flashplayers, media players, codecs, etc. But if you want to run audio... no need. Actually you'd be better off without that stuff. <br />
<br />
The end result:<br />
A system that will run JACK @ 4ms latency, 192kHz samplerate, with a *non-RT* kernel. That's currently still compiling, and I'm hoping to squeeze another ms or 2 off the RT_PREEMPT & IRQ tuning (& IRQ threading.. but that's dangerous territory AFAIK!) <br />
<br />
So far I'm very satisfied with Arch and its <b>amazing</b> documentation :)<br />
Will keep this up to date with the RT kernel progress & latency tuning,<br />
-Harry<br />
<br />Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com1tag:blogger.com,1999:blog-6426055874900292298.post-53106818991416230402011-11-16T10:41:00.001-08:002011-11-16T11:12:13.083-08:00Tutorial: JACK RingbuffersHey All,<br />
<br />
A quick tutorial on basic Jack ringbuffer usage. Ringbuffers are an easy way to exchange data from one thread to another in a realtime safe way. This means that no thread will block when reading or writing, and hence you use ringbuffers in a real-time thread.<br />
<br />
For this tutorial I'll be using the "standard" linux audio ringbuffer that comes with JACK. Its docs are available here: http://jackaudio.org/files/docs/html/ringbuffer_8h.html<br />
<br />
So what were going to do is:<br />
1. Setup a ring buffer<br />
2. Register a JACK client, and give it a process callback<br />
3. Write data in the "local" thread, ie: our main()<br />
4. Make JACK print out any data it recieves in its RT thread<br />
<br />
Note that here the JACK thread is our READ thread , and the main() thread is the WRITE thread. This is important, because a ringbuffer like the JACK one will only work in ONE direction.<br />
<br />
Find the well commented source here: <a href="https://sites.google.com/site/harryhaaren/Home/main.cpp">https://sites.google.com/site/harryhaaren/Home/main.cpp</a><br />
<br />
Note the compile command is: <b>g++ main.cpp `pkg-config --cflags --libs jack` </b>(its also in the source.. but just to make sure <span style="font-family: "Courier New",Courier,monospace;">:)</span><br />
<br />
Responses welcome, -Harry<br />
<br />
PS: Note there are many different implementations of ringbuffers, all with benefits of their own. The JACK ringbuffer is a simple and IMO easily usable one, and that's the reason I like it. I don't want a fancy impossible multi-read multi-write templated 13 class derived special oval ringbuffer, just something that does what it says on the tin <span style="font-family: "Courier New",Courier,monospace;">:)</span>Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com5tag:blogger.com,1999:blog-6426055874900292298.post-74700322806356181012011-09-21T03:42:00.000-07:002011-09-21T03:42:32.569-07:00Luppp : 30,000 locSomewhere yesterday Luppp passed the 30 k lines mark, currently on 30, 255. There's been quite some UI work going on, as well as some (essential) features being implemented in the engine... full update soon :)Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-64851496138537617662011-09-05T14:39:00.000-07:002011-09-05T14:40:21.149-07:00Project Piano<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSEdjdjTR_jdRyVwV0KHYYNYwy22E1P-Hd97lKqGRC4KxWId4JaeR1LPggTOdp1HHqBfnDEvTular4yiDphxm2WV9J_DdH2UtW5Fib46AD379kVH5i1IBu2gxrb2seqQdPVcX99oQ1Ms97/s1600/broadwood.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSEdjdjTR_jdRyVwV0KHYYNYwy22E1P-Hd97lKqGRC4KxWId4JaeR1LPggTOdp1HHqBfnDEvTular4yiDphxm2WV9J_DdH2UtW5Fib46AD379kVH5i1IBu2gxrb2seqQdPVcX99oQ1Ms97/s400/broadwood.jpg" width="400" /></a></div>
A couple of days ago a piano popped up on Adverts.ie, "free to take away". Since I've been wanting to try my hand at some piano tuning without detuing a piano playable, this was the opportunity to get cracking with that. So we picked up the piano from Clonmel, Co. Tipp on Sunday, and took it back home.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNZMo8HyrJO0cn3CjOYUWFrTvLDxSJggcq9X-A7UAARnVfxWFO9kcIx-S2uCjhPfdTBsOv6jMEkMybAi4upXgEWxqMDPXL_fgtej38MUvlB8YRGXRmMqKn7_yJ6mudAxFfHjC7MXAOG94W/s1600/serial.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNZMo8HyrJO0cn3CjOYUWFrTvLDxSJggcq9X-A7UAARnVfxWFO9kcIx-S2uCjhPfdTBsOv6jMEkMybAi4upXgEWxqMDPXL_fgtej38MUvlB8YRGXRmMqKn7_yJ6mudAxFfHjC7MXAOG94W/s400/serial.jpg" width="400" /></a></div>
<br />
After a bit of googling and checking websites I found one that had all the <a href="http://www.piano-tuners.org/broadwood/serial_numbers.html">Broadwood serial numbers</a>, and I checked up what its approximate build year was: 1907. That makes her 104 years old :) It seems that the convent in Clonmel bought the piano new, and used it there until they were recently donated new Roland digital pianos, hence this was being thrown out. Some kind folks took it home instead of letting it be thrown in the skip, and they popped it up on adverts which took her to Co Clare.<br />
<br />
Everybody that tuned the piano seems to have signed a key: perhaps this is a trait like a mechanic marking when the timing-belt has been done ;)<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfNQI2VuTXreJNJ3juiM_l0I-nd2xk3j6TWneB4d_pmCNjmePDeKjFszwWsxJk_-45g6kN1iI9uiOrMAcAwz5i4u-OgbBNmEUU_xyyF2caSXctAXV0TCx8yAc_am2KG2pCPkH95ytz5S9w/s1600/signatures.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfNQI2VuTXreJNJ3juiM_l0I-nd2xk3j6TWneB4d_pmCNjmePDeKjFszwWsxJk_-45g6kN1iI9uiOrMAcAwz5i4u-OgbBNmEUU_xyyF2caSXctAXV0TCx8yAc_am2KG2pCPkH95ytz5S9w/s400/signatures.jpg" width="400" /></a></div>
<br />
<br />
Today was spent just cleaning it up a bit: there was quite some dust, some spiders, spiderwebs etc, that's all gone. Next up was to take off the action, and the remove the keys.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9LgsXwhJf73_iNzsrXyztbBKdf5gclmMFC5A-Sygd47mvkSxjmOkgXfcbvL3OiZL1X_pvSAMvTeK1s5JQ1709ghZBaNRqFpxiE2P-O9742MRpn4n7A2sPzK41VCdLLPRIsJB78D2fiO2W/s1600/action.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="112" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9LgsXwhJf73_iNzsrXyztbBKdf5gclmMFC5A-Sygd47mvkSxjmOkgXfcbvL3OiZL1X_pvSAMvTeK1s5JQ1709ghZBaNRqFpxiE2P-O9742MRpn4n7A2sPzK41VCdLLPRIsJB78D2fiO2W/s400/action.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxeRQ2GT_VU0xxq8wsD9423Y3d1dfPhasa5cSCKo5prLVCV3HGMezfml7HVBJs8bT4qu3h1TgRK74DlCNwcqhM-HippgO8k2zBi2BvDS8S93BXNZZFRWUpJQgb8j_Nmkpav8qA5wmZHN62/s1600/action_keys_gone.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxeRQ2GT_VU0xxq8wsD9423Y3d1dfPhasa5cSCKo5prLVCV3HGMezfml7HVBJs8bT4qu3h1TgRK74DlCNwcqhM-HippgO8k2zBi2BvDS8S93BXNZZFRWUpJQgb8j_Nmkpav8qA5wmZHN62/s400/action_keys_gone.jpg" width="400" /></a></div>
<br />
<br />
Each key got a good cleaning with some ivory-friendly cleaning agent, and was then allowed dry off.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_XWYR0HJqV2TXOAjDuBCcoEFcufXPr6NfiIKNFq24s2J65BFPn0ABb4E4t6oG6NmoDHdTIcBEqWgMdzHlnqXJ6Uw_nDJzk7mJOJfhLMxLCljLc2W0Bw7b0odfI6B19l6rALV4ZVnFIZqN/s1600/keys.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="126" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_XWYR0HJqV2TXOAjDuBCcoEFcufXPr6NfiIKNFq24s2J65BFPn0ABb4E4t6oG6NmoDHdTIcBEqWgMdzHlnqXJ6Uw_nDJzk7mJOJfhLMxLCljLc2W0Bw7b0odfI6B19l6rALV4ZVnFIZqN/s400/keys.jpg" width="400" /></a></div>
Got a good look at the case under the keys didn't show any signs of the wood being worn, so there isn't any need for structural woodworking. Delighted: restoring the action case would have been quite some work.<br />
<br />
Then to putting the keys back on, and making them all sit right. A
couple of the keys action wasn't smooth enough to lift the key once the
hammer's pressure was on it, so some of the pins were bent back into
place, a coulpe of others needed a bit of a twist to make it fit. <br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkRaFFE1Ms1ISfIeVr5uFnTGYjj2jq-S-IrD-X3P1zOEIpgQrh2QddBJ4FeEs4SZhK8NvDO0VemvqrX17ZUuoCoo3i2NRcJqRFaydrHmxxg8EOQL3SsZtpjP2eQ6UqZSPuo3N0gyXj4Txx/s1600/keysCleaned.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkRaFFE1Ms1ISfIeVr5uFnTGYjj2jq-S-IrD-X3P1zOEIpgQrh2QddBJ4FeEs4SZhK8NvDO0VemvqrX17ZUuoCoo3i2NRcJqRFaydrHmxxg8EOQL3SsZtpjP2eQ6UqZSPuo3N0gyXj4Txx/s400/keysCleaned.JPG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
Once all back in place, it was time to get the tuning gear, and get going. By then end of the day the A's and G's were pretty ok.. even though when I'm next at it, it will probably have sagged enough to not notice much.<br />
<br />
That's all for now!Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-42083129983097153002011-08-21T16:02:00.000-07:002011-08-22T04:58:26.704-07:00Luppp: Progress, demo song & video<script src="http://googlepage.googlepages.com/player.js" type="text/javascript">
</script>
Hey,<br />
<br />
The past while has seen quite some work being done, on various parts that needed attention: the UI, some internal effects &amp;amp;amp; support for instruments, and better LV2 support. Also there's a "scene" thing come into play...<br />
<br />
UI wise there's a mechanism in place that will "Osc Blob" send the nessisary information from the Engine, and it plots the wave shape on screen.<br />
<br />
For instruments &amp;amp;amp; effects we can now load PureData patches, and communicate with them using the JACK MIDI port. There isn't a lot of "routing" available, its all hard coded CC values at the moment, but that's on a todo list somewhere...<br />
<br />
The Lv2 side of things has seen some changes, like a system whereby the Engine dynamically updates the UI of which plugin is loaded where, as well as where it can find the binary files to instantiate the corresponding plugin UI.<br />
<br />
Finally the "Scene" thing, basically its a way to organize a song or structure audio clips into groupings that can be played back simultaneously.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheVlZ7MlEEN0UohSPYD2-rRkWwey0KXNK0QZ4XEOtLCuORskBuDFR0Ftqsg2zMF88gydC53P7we4pMb2Li13XmAoDr70w4OQSqfsLDoar59HuR0kn8fffbK_VZWTAOzI6qsDRD0984AOAP/s1600/lupppSceneSelector.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheVlZ7MlEEN0UohSPYD2-rRkWwey0KXNK0QZ4XEOtLCuORskBuDFR0Ftqsg2zMF88gydC53P7we4pMb2Li13XmAoDr70w4OQSqfsLDoar59HuR0kn8fffbK_VZWTAOzI6qsDRD0984AOAP/s400/lupppSceneSelector.png" width="400" /></a></div>
<br />
<br />
So here we have a blank session with 5 "tracks" or "loopers", each track complete with plugin slots, solo mute buttons, a pitch slider (left), and a volume slider (right) and 2D ambisonic panner.<br />
<br />
In the scene selector we see each buffer is currently green (play mode, not queued to change). Clicking on the Looper (purple thingy up top) will start recording to that buffer from the JACK audio input. A right-click -&amp;amp;gt; load will let you load a sample into that buffer.<br />
<br />
<br />
During the loading process (in a non-realtime thread :) the buffer is automatically time-stretched to match the current playback speed to seamlessly loop. All buffers that are recorded using JACK are automatically quantized to the current playback speed, so it all stays in sync.<br />
<br />
Up in the top you'll see the new "Global Scene" entrybox, typing a number there will trigger all the buffers to start playing the scene ID that you type in. Some work needs to be done there to make that more user freindly, but for now it provides access to scene changes in a semi-useable way.<br />
<br />
<a href="https://sites.google.com/site/harryhaaren/Home/lupppSession1.mp3">Luppp Session 1: Dubstep-y drum N bass-ish track</a><br />
Note the heavy synth is a PureData patch, the drums were loaded from samples, and the Synth is recorded from the XV-3080 using the JACK audio input. Global scenes are used to switch between the different parts of the song.<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dytD3bseGbOLAZGKJLQRGYlaVeE4WevS4hoxREbWTGtkkx9teANKdgMyl5bdtGeZFpSvaTRnVSru5qth86xOw' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
Here a screencast of the "Global Scene" feature, and some of the Lv2 features. Excuse the rubbish quality, I'm only getting used to exporting from OpenShot at the moment :) <br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
That's all for now, till next time <br />
-HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-6646501416579591572011-08-17T08:45:00.000-07:002011-08-20T03:50:28.247-07:00Ambisonics & Linux, resources & quick tootsHey,<br />
<br />
I've recently been asked how I do Ambisonics on Linux using open-source tools, so here's a very quick rundown of how it all works:<br />
<ol>
<li>Get a linux install, preferably "<a href="http://www.bandshed.net/AVLinux.html">AVLinux</a>" or "<a href="http://tangostudio.tuxfamily.org/en/tangostudio">TangoStudio</a>". I have experience with both of those and know they work well, and I'm not telling you to abandon your distro of choice here, just for people who are wondering what distro to choose for a new install</li>
<li>Run "sudo apt get install jackd ardour2 amb-plugins" in a terminal to grab the big programs your going to need (if you don't have them already)</li>
<li> Go to <a href="http://kokkinizita.linuxaudio.org/linuxaudio/downloads/index.html">http://kokkinizita.linuxaudio.org/linuxaudio/downloads/index.html</a></li>
<li> Download <a href="http://kokkinizita.linuxaudio.org/linuxaudio/downloads/clthreads-2.4.0.tar.bz2">clthreads</a>, <a href="http://kokkinizita.linuxaudio.org/linuxaudio/downloads/clxclient-3.6.1.tar.bz2">clxclient</a>, and <a href="http://kokkinizita.linuxaudio.org/linuxaudio/downloads/ambdec-0.4.4.tar.bz2">ambdec</a>. Perhaps also get the <a href="http://kokkinizita.linuxaudio.org/linuxaudio/downloads/ambdec-manual.pdf">ambdec manual</a>..</li>
<li>Build the 3 just downloaded bits of software, in the following order: cltreads, clxclient, then ambdec. Ambdec needs the other libraries on your system to compile! It should be easy after that &amp; there should be a readme / install file, but just in case:</li>
<ol>
<li>extract the contents</li>
<li>cd to the new folder (with extracted contents in it) </li>
<li>open a terminal and type "make" &amp; hit enter</li>
<li>now do "sudo make install" </li>
</ol>
<li>Software is ready, so now read this: <a href="http://ardour.org/node/2804">http://ardour.org/node/2804</a></li>
<li>Give it a go</li>
</ol>
Any questions about the setup feel free to get in touch :)<br />
-HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-44563424129995420032011-06-23T15:51:00.000-07:002011-06-23T15:51:16.285-07:00Luppp: Midi MappingHi,<br />
<br />
Today was a productive day, Luppp can now take a MIDI CC, and map it to almost parameter you'd care to mention. Currently if an unknown MIDI CC comes in, it auto-maps that to the last used parameter, but I want to create a nice interface that allows one to change the mappings manually, and of course create presets & such.<br />
<br />
No screenshot, its functionality that you'll find in the engine! Perhaps a little demo clip at one point.. who knows. Later!Harry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com0tag:blogger.com,1999:blog-6426055874900292298.post-87521188249503305162011-06-07T07:23:00.000-07:002011-06-07T07:24:40.782-07:00Luppp: 20,000 loc Lv2 support & a CSound displayHey hey,<br />
<br />
20,000 lines of code, some LV2 support, and the beginnings of a CSound haul-over.<br />
For now a quick post, with the mandatory screenshots, later some more info on how its intended to support some of the (fancy) LV2 features like the instance access, and some others :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiLN2yqmwJ-u7T64a4F0YNXZBn322X7sA9wubNXj8FT0QL5qgfKBXrhqk76LCflSu0S5w6nONh2RZYJ7iL2rirPwXLRbdhJtpehmP-UBtqghHGnspkZxdBtLKKige0CvuZ4w-Ta8JPVVXQ/s1600/Screenshot-4.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiLN2yqmwJ-u7T64a4F0YNXZBn322X7sA9wubNXj8FT0QL5qgfKBXrhqk76LCflSu0S5w6nONh2RZYJ7iL2rirPwXLRbdhJtpehmP-UBtqghHGnspkZxdBtLKKige0CvuZ4w-Ta8JPVVXQ/s400/Screenshot-4.png" width="400" /></a></div><br />
<br />
<br />
<br />
<br />
Embedding LV2 gui's into the Luppp ui. Pop out windows will be supported too at some point :)<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ6XsWxRJcMxq2LSuVi6C1630BZzlSq9BxrWVdZofOTG5JnemAOU3Iw2x4TUGTnS6aa2QWL6jMNygzyTCWyHo7KADxXyRiQizk-b1klbSD4uxogSnKnOgnf-XPfzfXvZKycEGtd69tQVQI/s1600/Screenshot-5.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="311" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ6XsWxRJcMxq2LSuVi6C1630BZzlSq9BxrWVdZofOTG5JnemAOU3Iw2x4TUGTnS6aa2QWL6jMNygzyTCWyHo7KADxXyRiQizk-b1klbSD4uxogSnKnOgnf-XPfzfXvZKycEGtd69tQVQI/s400/Screenshot-5.png" width="400" /></a></div>And a CSound text editor based on Gtk Source View, a csound.lang file must be created to syntax highlight all the opcodes & that <br />
<br />
<br />
Till next! -HarryHarry van Haarenhttp://www.blogger.com/profile/07224643902643484992noreply@blogger.com1