Joys of graph processing

Last night I decided it was time to rethink how my CDP (Composer’s Desktop Project) frontend works. I smashed up a graph data structure and then a GUI for that.

aaa

 

 

 

 

 

 

 

 

 

This works in all sorts of ways better than the previous system.

edit : More fun with nodes that autoconnect in proximity to other nodes :

ggg

Posted in Uncategorized | 4 Comments

Just a quick update

So long since the last blog post…Happy New Year to everyone!

As a quick update :

-I am still working on the Composer’s Desktop Project front end plugin for Reaper (I’ll probably post a build of the standalone app too at some point)

-There’s no news about HourGlass :(

-I’ve been looking into Lua programming because that’s what a certain DAW will have for scripting in the near future ;)

-As a very random side project, I’ve looked into reimplementing the CMask program (for Csound score generation) with C++ and Juce and with also the eye to making it generate events compatible with other scenarios too. It might be though that I will just look into doing this in Lua instead…

Posted in Uncategorized | 13 Comments

Concurrency in C++, the cross platform way

My blogging activity has been low recently, so here’s some C++ musings on concurrency/parallelism.

std::async woes

C++11 introduced low level threading facilities into the standard library, but also a potentially handy higher level function, std::async, that can run callables in other threads. Unfortunately the C++ standard left open how that should be implemented. Microsoft uses a task based implementation  for it since Visual Studio 2012 but C++ standard libraries from other vendors unfortunately use a threading based implementation. That means that the following code will likely launch 1000 threads with the non-Microsoft implementations :

void do_lots_of_stuff()
{
  for (int i=0;i<1000;++i)
    std::async(std::launch::any,[](){ //...suitably heavy processing here... });
  // Since we don't wait here for the threads to finish, this'll crash...
  // But this is example code, so just imagine here's something that waits
}

That is definitely something we don’t want, 1000 threads would have a considerable overhead. The Microsoft implementation on the other hand will attempt to use a more balanced number of threads, passing the work to be done via tasks into its Concurrency Runtime. (The Microsoft implementation doesn’t necessarily throttle the number of threads at maximum to be the number of CPU cores in the system, but it will likely be way less than 1000 threads with the code example above.)

Apple of course has its Grand Central Dispatch, aka libdispatch, that is designed to allow running code concurrently using a higher level API and which uses an optimized number of threads. Unfortunately, their C++ library does not take advantage of that for std::async. I can only speculate why : they simply don’t like developers using C++ and try to make it as unattractive as possible to use the C++ language on their precious elitist platforms. Making std::async not use Grand Central Dispatch could be considered one subtle way how they are nudging developers towards using Objective-C and Cocoa, which are not cross platform in any real world sense.

Fortunately, Sean Parent presented a replacement for std::async that uses Grand Central Dispatch on OS-X. The code is a bit hairy, but compiles and runs as expected. (The code seen in his slides in the “C++ seasoning” talk has an error, but the corrected version I got from Sean is given here.)

#include "dispatch/dispatch.h"
template <typename F, typename ...Args>
auto async(F&& f, Args&&... args)
-> std::future<typename std::result_of<F (Args...)>::type>
{
    using result_type = typename std::result_of<F (Args...)>::type;
    using packaged_type = std::packaged_task<result_type ()>;

    auto p = new packaged_type(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
    auto result = p->get_future();
    dispatch_async_f(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
                     p, [](void* f_) {
        packaged_type* f = static_cast<packaged_type*>(f_);
        (*f)();
        delete f;
    });

    return result;
}

For Windows, we can have a simple wrapper for std::async, so we can write code that calls async the same way on both Windows and OS-X and get the desired behavior where the number of threads doesn’t explode :

template <typename F, typename ...Args>
auto async(F&& f, Args&&... args)
-> std::future<typename std::result_of<F (Args...)>::type>
{
    return std::async(std::launch::any,std::forward<F>(f),std::forward<Args>(args)...);
}

std::parallel_for_e…Oh crap, it doesn’t exist!

The C++ standards committee didn’t add even the simplest parallel algorithms for the C++11 standard library and they are not going to be seen in C++14, either. If we could have at least a parallel for loop that goes over a container and could do something with the elements, things would be a bit more happy…

Microsoft offers this in its Parallel Patterns Library, PPL. Use is rather simple since PPL is a proper C++ library, so it can use templates, iterators and lambdas :

#include "ppl.h"
void foo()
{
  std::vector<object_t> data(1000);
  Concurrency::parallel_for_each(data.begin(), data.end(), [](object_t& e) { // manipulate e });
}

Now, of course it’s not so great having to use a Microsoft specific library in our client code…And what about OS-X? Again, Apple’s Grand Central Dispatch also has a function that is similar to this, dispatch_apply_f. However, that is not only an Apple-specific API but also C, which is a language we don’t want to deal with directly in our client code.

So, I put on my thinking cap and was able to come up with a C++ function template, that uses the GCD/libdispatch API…(Someone probably has already done a better version of this but I wanted to see if I could manage to do it myself.)

#include "dispatch/dispatch.h"
template<typename It, typename F>
inline void parallel_for_each(It a, It b, F&& f)
{
    size_t count=std::distance(a,b);
    using data_t=std::pair<It,F>;
    data_t helper=data_t(a,std::forward<F>(f));
    dispatch_apply_f(count, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &helper, [](void* ctx,size_t cnt)
    {
        data_t* d=static_cast<data_t*>(ctx);
        auto elem_it=std::next(d->first,cnt);
        (*d).second(*(elem_it));
    });
}

Again, some rather nasty looking code there, but anything goes as long as it’s in the bowels of library code!

Like for async(), we can do a simple wrapper function for Windows which calls PPL’s Concurrency::parallel_for_each :

#include "ppl.h"
template<typename It, typename F>
inline void parallel_for_each(It a, It b, F&& f)
{
    Concurrency::parallel_for_each(a,b,std::forward<F>(f));
}

Hopefully someone finds these code snippets interesting/useful. They are not guaranteed to be error-free or as efficient as possible. They rather serve as examples how Microsoft’s PPL and Apple’s Grand Central Dispatch/libdispatch can be wrapped into library C++ functions that can be used in a cross-platform manner in client code. (Mentioning Linux was omitted here but I believe the libdispatch stuff should work on it too, I just didn’t investigate and test that.)

Posted in Uncategorized | Tagged , , , , , | Leave a comment

HourGlass 1.4.5 for OSX

Here is finally a new build for OS-X :

http://ge.tt/5lffqOq1/v/0?c

It is based on the same code as the last public Windows release. So there isn’t anything new, Windows users need not worry that they are left out on anything. Future plans for HourGlass are still open. I am not going to develop the 1.x series further, I will only do fixes for bad bugs on OS-X.

It requires at least OS-X 10.7. (10.6 simply isn’t something I am willing to deal with anymore, so don’t ask about that.) It may contain new bugs compared to the last OS-X build, but if anyone reports them, there’s a chance they may get fixed…It might not even run at all since I didn’t exactly remember the procedure I used last year when I did the OS-X builds…But please do report any problems, so I can look if they are fixable.

Posted in Uncategorized | 1 Comment

How’s HourGlass? Do I now drink JUCE? Qt no longer so cute?

I haven’t worked on HourGlass at all for a few months. Now that I’ve gotten more familiar with JUCE, it seems there could be a possibility I might rewrite HourGlass in some form using JUCE. That would have the benefit that making a plugin version would finally feasibly be possible. The recently released CDP front-end plugin is actually mostly developed as a standalone application (binaries of that have not been publicly available yet), which I every now and then build and test in the Reaper plugin mode. With JUCE based code it’s quite transparent to switch between a standalone application and a plugin with the same code base.

I am not sure yet what I am going to do with HourGlass. I feel very tempted to just drop the Qt based version completely. While Qt is an excellent framework, I’ve found it to become less and less relevant for myself. It’s very bad for doing plugins of any kind, except plugins for host applications that themselves are written with Qt. (And even then, there are the problems of C++ ABI compatibility and so on…) Qt no longer develops the traditional Qt Widgets module. They instead prefer to develop their Qml based GUI system, which isn’t very attractive for me. (Qml has a TON of runtime dependencies, it’s not C++ etc…) They nudge people towards using Qml in new code and I don’t like that.

One possibility how I might proceed is that I could extract and adapt the HourGlass audio processing code from the current Qt-based HourGlass code base and integrate that code into the CDP front-end code. The CDP programs offer all kinds of granular sound processing algorithms, but none of the CDP programs do granular processing exactly like HourGlass. (At least as far as I’ve found…) So having the HourGlass granulation/fragmentation processing available in the CDP front-end could make sense. I might need to rename the CDP front-end to something else then, though…

JUCE is not without its own problems, of course. But I’ve started to feel like it is the more appropriate thing for me to use.

I guess these were just random ramblings…

Posted in Uncategorized | 2 Comments

Oh noes, there could be a null pointer!

It’s been some time since I wrote anything about C++ programming, so here’s something. Sorry for users of HourGlass and other softwares of mine if this isn’t of much interest. ;) (I will probably start a separate blog specifically about programming later this year.)

Ideally one’s C++ code would never attempt to use an object via a null pointer, but in some cases having the possibility of a null pointer is just convenient to have. Maybe it’d be too tiresome to write an object that has some well defined null/empty/do-nothing state or whatever.

Class whose methods will be called in the examples :

class MyObject
{
public:
    double m_x=0.5;
    double foo() { m_x+=0.1; return sin(m_x)+cos(m_x); }
    void not_much() { }
    double borken_sum(double a, double b) { return m_x+a+b; }
    std::string mangle(std::string a)
    {
        std::reverse(a.begin(),a.end());
        return std::to_string(m_x)+a;
    }
};

The usual way to deal with a pointer that can be either null or valid is something like :

// MyObject* m_object ends up as nullptr or a valid pointer
// in some way before this code is run
// foo() of valid object should return a double
if (m_object!=nullptr)
  return m_object->foo(); 
else
  return 0.0; 

Or, more tersely with the terrible ternary operator :

return m_object!=nullptr ? m_object->foo() : 0.0;

I today came up(*) with an alternative solution that involves quite a hairy helper function but I kind of like this solution, assuming it actually works properly in most scenarios. (I didn’t extensively test this yet. There could be cases where the compiler gives an error or maybe the performance of making an object method call this way is horribly bad. Maybe Clang and GCC totally hate this. This was tested with the Visual Studio 2013 C++ compiler.)

The helper function in all its insanity :

template<typename U,typename F,typename... Args>
auto safe_call(U* ptr,F f,Args... args) -> decltype(std::mem_fn(f)(ptr,args...))
{
    if (ptr!=nullptr)
        return std::mem_fn(f)(ptr,args...);
    return decltype(std::mem_fn(f)(ptr,args...))();
}

Usage in client code :

return safe_call(m_object,&MyObject::foo);

In this version, no annoying additional control flow needs to be written, “nullptr” doesn’t need to be written, “m_object” doesn’t need to be written twice and the fallback value of 0.0 will be default constructed from the type the MyObject::foo() method returns.

Due to the variadic template, member functions with 1 or more arguments can also be used. The auto return type in the helper function also works for member functions that don’t return a value.

Additional usage examples :

double a=safe_call(m_object,&MyObject::borken_sum,2.0,1.0);
std::cout << safe_call(m_object,&MyObject::mangle,"Cat Attack") << "\n";
safe_call(m_object,&MyObject::not_much);

The downside is having to write the names of the class and the method with the &ClassName::MethodName notation.

Of course the safe_call-style technique doesn’t buy much if several methods of an object need to be called in a row. The following usual solution will work just fine and expresses the intent :

if (m_object!=nullptr)
{
  double a=m_object->foo();
  m_object->not_much();
  auto r=m_object->mangle("ooF");
} 

(*) No doubt this has been invented by someone else before me but I wanted to see if I could write it myself.

Posted in C++, Programming | Leave a comment

CDP frontend Reaper extension plugin

edit 9th February 2015 : Pre 7. Notable changes :

-Presets system. Handled via the button on the top right of the plugin GUI and the drop down box to the left of it. (There are no factory presets.)

-GUI scale can be changed via the Settings button menu. (That is, the sizes of the texts, buttons etc can be changed, instead of just being able to resize the plugin window.) This may be useful for example for Macs with Retina displays since smaller GUI elements can still be usable and have legible text on them.

-Preview playback looping can be turned on/off via the Settings button menu.

-Item import shortcut key was changed to Left Arrow, since the Insert key or equivalent doesn’t exist on Mac keyboards/JUCE’s keyboard handling code.

-Various tweaks and fixes.

edit 16th January 2015 : Pre 6 for Windows and OS-X. Notable changes :

-Thanks to Reaper’s AudioAccessor API, most types of audio items in Reaper can now be processed. This includes items with mp3, FLAC or similar audio files as the source file, as well as items with the loop options or realtime reverse turned on. This might also make the processing a notch faster since more preprocessing steps can be done at the same time.

-Spectral processors now have comboboxes for the FFT size and FFT overlap instead of the sliders

-The upper waveform can be made to fill most of the plugin, for more precise edits, by pressing PageDown. (On OS-X laptops this should be Fn+DownArrow)

-Right clicking on the upper waveform when it’s in the envelope mode, shows a context menu to switch to an available envelope

-Support for Spectral Stretch CDP processor was added

-Unfortunately for now, the feature to automatically follow the selected item in Reaper has been removed. The Import button no longer opens a menu, and rather directly imports the currently selected item in Reaper. (The reasons for this are messy, hopefully the feature can be readded later.)

edit 10th November 2014 : Pre 5 for Windows and OS-X. Notable changes :

-Envelope segments can be curved by Alt+dragging the segments.
-CDP processings which require doing the processing by splitting stereo files into mono files are now processed in parallel, hopefully resulting in speedups
-The plugin adds another action “Xenakios : Reset CDP front-end”, which hopefully will reset the plugin to a fresh state if it ends up not working, without having to restart Reaper.
-OSX version should now display more errors when appropriate, instead of just setting a non-existing file on the output waveform. (This is still not working completely…)

edit 22nd August 2014 : Pre 4 for Windows and OS-X. Preliminary support for processing stereo files with CDP programs that don’t support stereo directly. (Such as all the spectral processors and the processors in the “Distort” group.) Some other tweaks and fixes.

edit 3rd August 2014 : Pre 3 for Windows and OS-X. Modify Speed processor was added. (For resampled pitch/time processing.) More parameters of the Texture Simple processor can be automated. Some misc fixes. OS-X build now only has the 64 bit version.

edit 31st July 2014 : Preliminary OS-X build uploaded. I was able to make the plugin GUI only work so that it stays on top of everything, which is very annoying, but less annoying than it disappearing behind Reaper’s window when clicking outside the plugin GUI…Hopefully that problem can be solved at some point.

edit 29th July 2014 : pre2 builds uploaded. Contains various fixes and the ability to zoom and scroll the input sound waveform. (The zoomscroll-bar is between the input and output waveforms.)

I am finally making the first public release of the C++/Juce based CDP frontend I’ve worked on for the last 5 weeks or so. Thanks to Oli Larkin for working on the OS-X build! (Unfortunately it didn’t materialize for this first release, though.)

If you don’t already know what the Composer’s Desktop Project is, please read before trying to use the plugin to decide if this something you would likely be interested in trying to test :

http://www.composersdesktop.com/

To use this, you must have the Composer’s Desktop Project installed, available from :

http://www.unstablesound.net/cdp.html

-The plugin allows you to bypass setting the CDP_SOUND_EXT environment variable which is mentioned somewhere in the CDP documentation that it must be set for things to work. (If the environment variable is not set, the plugin sets it temporarily.)

-The plugin will on first run ask you to locate the CDP binaries location. This is the folder with files such as “pvoc.exe”, “modify.exe” and “distort.exe” within the CDP installation.

-The plugin adds one new action into Reaper : “Xenakios : Show/hide CDP front-end” which you should find from the Reaper actions window. The action is not added to any menu in Reaper or given a default keyboard shortcut.

-When the plugin window has focus, the following keyboard shortcuts are active :

Insert-key : Import the selected Reaper media item
Home-key : Toggle automatic rendering after settings (parameter sliders, automation envelopes, the time waveform time selection) have been altered. You might want to have this turned off when you know you want to alter several settings/automation points and the rendering delay is too short to reach the desired GUI elements before the automatic rendering is triggered.
Delete-key : Removes the selected area from the sound file or envelope points of the selected area. (Depending on whether the Waveform or Envelope button in the top left is active.)

Please use this plugin with Reaper 4.7 or newer only! Reaper versions before 4.7 have a bug that crashes during the realtime preview.

The front end has various omissions, quirks and defects at this point, but I hope it will be somewhat useful already. Some of the things are quite tricky to implement ideally because everything works by running command line programs in the background, after all…But I hope I will be able to later implement better solutions to some of the issues.

It only has a limited selection of the CDP processing programs available at this point, as some of them require much more complicated GUIs and logic than is currently implemented. (And some of the suitable programs I just haven’t added yet.)

Many of the CDP programs only process mono files. This has been worked around since Pre 4 by splitting stereo files into mono files, then processing them separately with the mono-only programs and then joining the mono files back to a stereo file. This can in some cases cause the channels to become completely decorrelated and the original stereo image will be lost. But since this workaround is the only possible, it’s provided in the hopes it will be useful/interesting in some situations.

64 bit plugin : (Windows 7 or newer) :

http://ge.tt/8DPHpAA2/v/0?c

32 bit plugin : (Windows 7 or newer) :

http://ge.tt/3ofypAA2/v/0?c

64 bit OS-X plugin : (Tested only on OS-X 10.9.5, 64 bit. Might work on 10.7 or 10.8 or 10.10. Don’t ask for 10.6 support, that won’t happen.) :

http://ge.tt/8ZuUoAA2/v/0?c

To comply with the Juce licensing model, the source code is GPL-licensed and is available from the following link :

https://bitbucket.org/xenakios/reaper-cdp-frontend-extension-plugin/src

Posted in Uncategorized | 8 Comments