Kernel word recovery crack, Mobile themes website for samsung wave 525, Dekha ek khwab sony tv title song, Song zombies on your lawn, Bloody mary nerve endings mp3, Digittrade tv jukebox, Padosan songs mp3, Gold cup series 70 manual, Nieuwste versie van mozilla firefox en, Cant install spotify on mac, Web brute force password cracker, Belkin g peek driver windows 7

Wordbrain solver

July 27th, 2015 by Martijn No comments »

I wrote a little [Wordbrain][wordbrain] brute force game solver to help^H^H^H^H^H^H^H for fun. You can find the [source][source] on my [github][github].

You will need a word list and a C++ compiler with the Qt libs installed to run it.

Here is an example run (in French):

    $ ./wordbrain -d liste_full.tree oeuf niis cmll alba 6 5 5
    Le dictionnaire contient 330761 mots.
    ****************************************************************************
    camion + label + fusil
    o5 e  u  f      |          u  f      |                    |    
    n6 i4 i  s      |          i  s      |             f1     |    
    c1 m3 l  l      |       e4 l1 l      |          u2 s3     |    
    a2 l  b  a      |       l5 b3 a2     |          i4 l5     |    
 
    ****************************************************************************
    camion + balle + fusil
    o5 e  u  f      |          u  f      |                    |    
    n6 i4 i  s      |          i  s      |                    |    
    c1 m3 l  l      |       e5 l4 l3     |          u2 f1     |    
    a2 l  b  a      |       l  b1 a2     |       l5 i4 s3     |    
 
    ****************************************************************************
    camion + balle + fusil
    o5 e  u  f      |          u  f      |                    |    
    n6 i4 i  s      |          i  s      |             f1     |    
    c1 m3 l  l      |       e5 l3 l      |          u2 s3     |    
    a2 l  b  a      |       l4 b1 a2     |          i4 l5     |    
 
    ****************************************************************************
    camion + fusil + label
    o5 e  u  f      |          u2 f1     |                    |    
    n6 i4 i  s      |          i4 s3     |                    |    
    c1 m3 l  l      |       e  l5 l      |       e4    l1     |    
    a2 l  b  a      |       l  b  a      |       l5 b3 a2     |    
 
    ****************************************************************************
    camion + fusil + label
    o5 e  u  f      |          u2 f1     |                    |    
    n6 i4 i  s      |          i4 s3     |                    |    
    c1 m3 l  l      |       e  l  l5     |       e4 l1        |    
    a2 l  b  a      |       l  b  a      |       l5 b3 a2     |    
 
    ****************************************************************************
    camion + fusil + balle
    o5 e  u  f      |          u2 f1     |                    |    
    n6 i4 i  s      |          i4 s3     |                    |    
    c1 m3 l  l      |       e  l  l5     |       e5 l3        |    
    a2 l  b  a      |       l  b  a      |       l4 b1 a2     |    
 
    ****************************************************************************
    camion + label + fusil
    o5 e  u  f      |          u  f      |                    |    
    n6 i4 i  s      |          i  s      |                    |    
    c1 m3 l  l      |       e4 l5 l1     |          u2 f1     |    
    a2 l  b  a      |       l  b3 a2     |       l5 i4 s3     |

[wordbrain]: http://wordbrain.maginteractive.com/
[source]: https://github.com/mvdkwast/wordbrain
[github]: https://github.com/mvdkwast

Github repository

February 14th, 2013 by Martijn No comments »

Added the tool of which displays information about open files to my github.

Duckbox MIDI USB controller

January 28th, 2013 by Martijn No comments »

duckbox

A quick post about an electronics project from 2008. This is a the Duckbox. It’s a simple MIDI controller in an bent and drilled VHS cover, which proved to be more rugged than I expected. As you can see, it’s been mistreated (and spilt on) quite a bit over the past years. It runs software USB on an ATTiny26 AVR microcontroller. It proved to be fairly useful in combination with the FP-4 Manager application.

Unfortunately I seem to have misplaced the schematics, but I’m sharing its firmware in the attachment below in case anyone is interested.

CC Remapper

This is a screenshot of CC-Remapper, the application I wrote to remap the controller numbers that the Duckbox uses so I could use it with software synthesizers with fixed controller numbers. It is also included in the attachment.

More information in the included README files.

Attached Files:

Roland FP-4 Manager

January 21st, 2013 by stilgar 9 comments »

I’ve been the proud player of a Roland FP-4 digital keyboard for about 5 years now, and I have only recently discovered that it contains a quite amazing multi-effects unit. The problem is that only one of the effect parameters at the time is directly adjustable from the keyboard. Fortunately Roland provides a very helpful MIDI implementation reference, prompting me to write the application described here.

As I play in several smalls bands and are a regular at some local jam sessions that can be quite experimental, my objective was to write a tool flexible enough to adjust sounds in a live setting, using a laptop or an external MIDI controller, and that would also be able to sequence sounds in a performance setting. Of course, it should also be robust enough to handle power failures and an accidently disconnected USB cable during a live performance. Finally it should be able to handle additional keyboards and have split and layer functionality beyond the built-in one.

This project runs on Linux and uses the Qt library for its ease of use, clean programming style and GUI system, and Alsa for MIDI I/O. It is currently in a alpha development phase, which means that alhough it is quite usable, there are still some UI aspects I would like to change, some features I would like to add, and some code that I would like to reorganize to have a better base for future extensibility. I plan to release this application as open source after that is done. Currently, the application only targets the Roland FP-4 and FP-7 keyboards, but it would be easy to support other keyboards that are organized in a similar fashion.

Main screen

When you start the application with a connected keyboard, you are greeted by the following screen.

This is the master screen. Here you can choose the instrument for the first channel, ie. the instrument you hear if the splits are set to default. This is also the place to choose the current sound effect (only one can be used at the time), the reverb and chorus settings, as well as some other settings that affect the sound as a whole.

Instrument Selection

The instrument selection part at the top displays buttons that match pseudo-GM2 groups by default, but can be changed to match the instrument buttons on the keyboard by pressing the FP4 button top right. Instruments can be marked as favourite for quick access by checking the box next to the Favourites button on the right.

Sound effects & MIDI Learning

The first dropdown box in the effects part of the screen selects the current effect. When effects are switched using that dropdown, the last settings in use are restored. The preset dropdown allows to load other settings. It always includes a default preset that loads useable parameters for each effect. Every parameter can individually be reset to its default value by clicking the left arrow button next to the effect name, and can be bound to a MIDI controller, including the pedals and pan button of the FP-4. Pressing the chain icon next to the previous button shows a MIDI learn dialog.

When this dialog is displayed, rotate or press any controller to bind it to that parameter. MIDI learning is not limited to the effect parameters, nearly every slider, checkbox and combobox can be be controlled as indicated by the chain icon.

Other global parameters

The other 3 tabs in the main window allow to set the reverb and chorus styles, as well as the master volume and key shift. Reverb and Chorus can either be set to FP-4 built-in macros, or manually adjusted. They apply globally, but the amount of effect can be adjusted for each channel.

The Channels Window

This is a channel mixer. Here you can select an instrument for each channel, select it’s relative volume, select if the global sound effect applies, and whether it is polyphonic or monophonic. The C button gives access to channel controllers like vibrato and resonance, pedals, filters and send levels (to reverb and chorus). The G button gives access to generators that produce controller or note events according to what is played on that channel. For quick navigation, keyboard shortcuts are provided for all functionality.

Channel Parameters

This is were you can adjust controller values, pitch and send levels for a channel. The interesting thing here is that every parameter can be controlled by an external controller. This means that you can adjust the amount of vibrato or the filter frequency with the pan button on the Roland hardware for instance. Note that for the portamento settings to work, the monophonic checkbox needs to be checked in the channels window.

The Defaults button resets every value to its default and should be a good base to start tweaking sounds. The Send All button resends every controller value to the connected keyboard. Notes Off and Sounds Off cut every note resp. every sound and can be used as per channel “panic” buttons.

Generators

These is a somewhat experimental feature that generates controller values and notes based on what is played on a channel. The generated controller values can be used to control any other parameter just like external MIDI controllers.

The channel pressure generator creates a virtual controller whose value varies according to the strength (velocity value) at which notes are played. When average is used, the values evolves gradually. Up Speed and Down Speed indicate how quickly the values changes to a higher resp. lower value. If Decay is set to a non-zero value, the controller value will gradually go to zero when no notes are played. This generator can be used to add more vibrato or distortion (or both!) if notes are played louder for instance.

The controller keys generator makes a range of keys produce controller values. The leftmost key will be assigned to the first controller, the second one to the first controller + 1, and so on. If Key Lock is checked, The leftmost key needs to be pressed in combination with the chosen controller, to prevent accidents. If Continuous is checked the generated value will be equal to the note velocity. If the note is released the generated value will be set to 0, unless ignore release is checked. If Continuous is not checked, the generated values will be 127 (maximum) when a key is pressed or 0 when it is released. This generator could be used for many purposes, such as controlling the volume of a channel with pads, using a keyboard range to navigate between sound presets in performance mode, pressing a key to make the leslie effect “brake”, etc.

The key time generator generates a value that changes with the time since the last note has been pressed. The Transition Time parameter makes it change more rapidly or slowly. This can be used to progressively add more vibrato or mix in another channel if a note or a chord is held. Very cool for old-fashioned 80’s style sounds.

The voicing generator is pretty much work in progress, and is bound to change somewhat in future versions. It creates a chord based on the note that is played. A chord and a reference scale can be chosen so the chord can be transposed intelligently. Choosing the chromatic scale disables that behaviour. Note that the generators can be enabled and disabled by a controller, so the controller keys generator can be used to engage and disengage harmonizing using a key on the FP-4.

Splits and Layers

This is pretty straight-forward. Select the incoming MIDI channel on the right. Every horizontal slider represents and output channel. Drag the handles to select the range in which the incoming notes on the input channel are output to that channel. The sliders can be double-clicked to enable the mapping. You can then choose an octave shift to adjust the output notes’ pitch.

A few more experimental features are available in the Channel Mode dropdown. Forward mode selects basic split / layer behaviour. The Monophonic modes ignore key releases and allow one note at the time, sending note-off events to for each note that is playing when a key is pressed. The Monophonic / Retrigger mode sends a note-off event followed by a note-on event when the last note is repeated. The Monophonic / Toggle mode only send a note-off event when the last note is repeated. The modes can be useful to create bass drone, freeing the left hand for other uses. The Smart mode detects chords and keeps them playing, ignoring note-off events like the monophonic modes, When a new chord or note is played, all currently playing notes are shut off. This is very useful to sound chords of pads or strings keeping two hands free for melody and bass for instance. Portamento mode insert portamento-start MIDI messages after every note. (Only useful when the monophonic option is set for that channel in the channel mixer).

Performances

In this window, settings can be sequenced for a live performance. The dropdown box at the top selects a show. The top-left pane shows a settings browser. The top-right pane shows a color-coded list of songs that can be reordered by drag and drop . The pane at the bottom displays a timeline of settings for each song. Settings can be dragged from the top-left pane to the songs in the timeline. The buttons at the top of the timeline pane jump between timeline frames and load the appropriate settings if Activate Show Mode is checked. They can be bound to keys any external MIDI controller or to keys on the FP-4 keyboard using the Controller Keys Generator from the channel mixer.

Although it is functional, as you will notice, this is very much work in progress on the UI side. Options will be added to load only parts of settings, ie. loading only instruments and their controller settings without split and master settings.

Configuration

Bindings

This window, accessible from the configuration menu, displays all current controller bindings and allows you to edit and delete them. The range for every controller can be adjusted, and the values can be reversed (eg. decrease values as you press a pedal)

External Devices

This configuration window lists MIDI devices other than the FP-4. This is especially useful to connect external controllers to this application so effects can be adjusted more easily. In autoreconnect mode these controllers will connect automatically when the application starts, and reconnect on the fly if they are disconnected.

Conclusion

It’s been nearly a year since I started writing this post. I’m still using this application sometimes, especially to get nicely distorted organs and heavy electric pianos. As I started working on a new more generic sound (and video) tool, I don’t have much interest in updating this application except for myself. If you have any interest in the source code, feel free to ask.

C++11 lambdas

July 1st, 2012 by Martijn No comments »

A small extract from my ongoing project Jam Fabric. C++11’s lamba functions can make code very consise.

bool Workspace::isEquivalentTo(const Workspace *other, bool checkValues) const {
    QList<Unit*> myUnits = findChildren<Unit*>();
    QList<Unit*> otherUnits = other->findChildren<Unit*>();
 
    if (myUnits.size() != otherUnits.size())
        return false;
 
    std::sort(myUnits.begin(), myUnits.end(), [](Unit* a, Unit* b) {
        return a->name() < b->name();
    });
 
    std::sort(otherUnits.begin(), otherUnits.end(), [](Unit* a, Unit* b) {
        return a->name() < b->name();
    });
 
    if (!std::equal(myUnits.begin(), myUnits.end(), otherUnits.begin(), [checkValues](Unit* a, Unit
* b) {
        return a->isEquivalentTo(b, checkValues);
    }))
    {
        return false;
    }
 
    return true;
}

VMValue

June 7th, 2012 by Martijn No comments »

After considering several variant classes for my ongoing project, I decided to roll my own.

Compared to other variant types, it implements:

– Registration of named structured types.
– Registration of type conversions. A conversion doesn’t have to always succeed. For instance a MIDI Channel message may be converted into a MIDI Controller message, but may also be an incompatible MIDI note message.
– Binary (de-)serialization to QDataStream.
– Textual (de-)serialization to QTextStream. There is an unambiguous mode useful for debugging and datatransfer (altough QDataStream is likely to be more appropriate in this case) and a “human” mode useful for displaying values, human input and scripting.

A quick example of basic functionality.

#include <vmvalue.h>
#include <vmtypemanager.h>
#include <QStringList>
 
int main() {
    VMValue a = 3;
    Q_ASSERT(a.intValue() == 3);
    Q_ASSERT(a.type() == VMValue::IntType);
 
    VMValue b = "Hello Mars !";
    Q_ASSERT(b.stringValue() == "Hello Mars !");
    Q_ASSERT(b.type() == VMValue::StringType);
 
    VMValue x;
    Q_ASSERT(!x.isValid());
    x = QStringList({"welcome", "back"});
    Q_ASSERT(x.type() == VMValue::StringListType);
 
    VMValue rect = VMValue::byName("Rect");
    Q_ASSERT(rect.typeName() == "Rect");
    rect.setAttribute("x", 200);
    Q_ASSERT(rect.attribute("x").intValue() == 200);
}

An example of a custom datatypes and a casting function:

VMValue castChannelMessageToControllerMessage(const VMValue& source) {
    if (source.attribute("status") != MIDI_CTL_STATUS)
        return VMValue::Invalid;
    VMValue v = VMValue::byName("ControllerMessage");
    v.setAttribute("channel", source.attribute("channel"));
    v.setAttribute("ctl", source.attribute("data0"));
    v.setAttribute("value", source.attribute("data1"));
    return v;
}
 
int main() {
    VMTypeDef* channelMsgDef = new VMTypeDef;
    channelMsgDef->addAttribute("channel", VMValue::IntType, 0);
    channelMsgDef->addAttribute("status", VMValue::IntType, 0);
    channelMsgDef->addAttribute("data0", VMValue::IntType, 0);
    channelMsgDef->addAttribute("data1", VMValue::IntType, 0);
 
    VMTypeDef* ctlMsgDef = new VMTypeDef;
    ctlMsgDef->addAttribute("channel", VMValue::IntType, 0);
    ctlMsgDef->addAttribute("ctl", VMValue::IntType, 0);
    ctlMsgDef->addAttribute("value", VMValue::IntType, 0);
 
    vmTypeManager()->registerType("ChannelMessage", channelMsgDef);
    vmTypeManager()->registerType("ControllerMessage", ctlMsgDef);
    vmTypeManager()->registerCastFunction("ChannelMessage", "ControllerMessage",
        &castChannelMessageToControllerMessage);
 
    Q_ASSERT(vmTypeManager()->hasType("ChannelMessage");
    VMValue channelMsg = VMValue::byName("ChannelMessage");
    channelMsg.setAttribute("status", MIDI_CTL_STATUS);
    channelMsg.setAttribute("data0", MIDI_DAMPER_CTL);
    channelMsg.setAttribute("data1", 127);
 
    Q_ASSERT(channelMsg.canCastTo("ControllerMessage"));
    VMValue ctlMsg = channelMsg.castTo("ControllerMessage");
    Q_ASSERT(ctlMsg.isValid());
    Q_ASSERT(ctlMsg.attribute("ctl").intValue() == MIDI_DAMPER_CTL);
 
    return 0;
}

Human-readable serialization to QTextStream using VMValueDumper and VMValueParser example:

    VMValueDumper dumper;
    dumper.setPrettyPrint(false);
    dumper.setBareStrings(false);
    dumper.setCompact(true);
    dumper.setOmitDefaults(false);
 
    Q_ASSERT(dumper.dump(5) == "5");
    Q_ASSERT(dumper.dump("hello") == "hello");
    Q_ASSERT(dumper.dump(IntList({1, 2, 3})), "I[1,2,3]");
 
    // ControllerMessage from previous example
    Q_ASSERT(dumper.dump(ctlMsg) == "@ControllerMessage{channel:0,ctl:7,value:127}");
 
    VMValueParser parser;
    VMValue x = parser.parse("\"hello world\"");
    Q_ASSERT(x.stringValue(), "hello world");

The missing part is currently the ability to share a value between VMValues to optimize data transfer between Units in the a graph, especially for streaming nodes (audio, video).

There isn’t much documentation for the code, except the comments inside the source and some design files, but there are unit tests that show the intended use of these classes.

As the API isn’t fully stabilized yet, the source code is available on request.

Jam Fabric – Structure

April 17th, 2012 by Martijn No comments »

Determining an optimal structure for the patches in Jam Fabric has been the
subject of quite some reflexion. The goal to be as conceptually simple as
possible to be easy to understand for potential users had to be balanced
against the goal of having structured classes and keeping everything
synchronized, especially in the optic of multiuser usage.

## Problems to be solved

### Workspace structure

Patches consist of a root *Workspace* that can contains *Units*. Units
themselves may have child workspaces attached to them, that can communicate
with the parent workspace through their parent’s unit inlets and outlets.
Things get interesting when a multiple units must refer to the same workspace
structure. For instance, a workspace implementing a synthesizer could be used
multiple times to create chords. If the synthesizer workspace is modified in
one place, the change should be immediately applied to every other instance.
But only the change in structure, as the values have to be different in each
synthesizer instance since we want to create different notes.

In puredata this is handled by updating every workspace loaded from an
external file every time one instance is saved. This has several drawbacks.
When a workspace is reloaded after another instance is saved, the values
are lost. When changes are made in different instances, the workspaces are
out of sync. Saving one instances looses the changes made in the other. This
is especially problematic for collaborative editing where one user may not be
directly aware of changes made by others.

### Serializing values

Another difficulty with workspaces loaded from external sources or multiple
instances of workspaces is serialization. We may choose to limit workspaces to
having a set of fixed values that don’t vary from instance to instance, and to
send every value that needs to be changed from the default when a patch is
loaded from a (unique) parent workspace. This has a few drawbacks as well.
Imagine an external sequencer workspace, containing a visual grid with and
some controls to manipulate the sequenced events. If we want to save the grid
contents for every sequencer instance, we have to store the values in the
patch. The *easiest* way to implement this would be to have the sequencer
workspaces have the functionality to receive/send the grid contents, and store
the grid data in a datastructure contained in the synthesizer’s parent
workspaces contained in the patch. This has the result of adding units to the
parent workspaces, defeating in part the idea of hiding such details in a
subworkspace. This also requires some kind hook that is triggered when a patch
is saved, so the sequencer workspaces can communicate the grid contents to the
parent.

### Unit names

In some cases, units need to refer to other units by name. For instance, in
the case of audio buffer units (eg. containing wave data loaded from file), it
is impractical to send the contents of the buffer every time a consumer unit
requires it. Instead, the consumer unit refers to the buffer by name. This
poses the problem of namespacing. If all names are global, a mechanism is
required to create unique names for units in different workspaces. Sometimes
units may want to access units in other workspaces, requiring a consistent
naming scheme.

Puredata solves this to some extent using the $0 variable which is guaranteed
to be unique inside each workspace. Array objects can be created using the
concatenation of this variable and a name, eg. $0-buf1. Accessing these array
objects from another workspace requires sending the $0 variable to every
workspace using that array. While this solution is workable, it is also a
somewhat cumbersome as it requires extra units not directly related to the
task to be solved.

### Unit types

Units are created by type name. A type defines the functionality of that unit.
A type can be either a registered C++ object, either internal or loaded
through a plugin, a registered script object, or a named external workspace
(abstraction in puredata). If many type names are declared, some kind of
organization is required to avoid naming conflicts, especially if the
naming scheme is flat. Type resolution is also a source of difficulty. Does
the name *granulator* refer to the internal granulator object, or does it
refer to an external workspace in a file named granulator ? In some cases, it
may also be practical to be able to override existing type names, causing
units using the to use a local version instead of the default one. ForWorkspaces share a common
debugging purposes, one might want to wrap the hypothetical system
*table-lookup* object inside a local *table-lookup* object that would dump the
values sent values to the console.

## Implementation

With these difficulties in mind, we proposed a slightly more complex
structure based on the OO approach that separates classes from instances.
A *Network* may be shared between multiple *Workspaces*. Structural changes
are made to that network and not to the workspace. Client applications are
notified of the changes in the networks, and it is up to them to update the
(visual or not) representation of the workspaces instanciating those networks.

Networks contain *Units*. A unit contains the details of a network object: the
number and nature of its inlets and outlets and its configuration data. For
instance a unit implementing a slider will have one inlet to set its value,
one outlet to send its value on change, and minimum and maximum values. These
details are shared between every workspace that is an instance of the same
network.

Workspaces have a Network, and contain *UnitData* objects that hold values for
every input and output pin for the corresponding Unit object in the workspace’s
network. Changes in values are specific to a workspace, and thus the client is
notified of those on a workspace base.

In this model, Networks and Units correspond to C++ classes. The configuration
variable in units correspond to static class data. Workspaces and UnitData
correspond to C++ objects.

A unit itself is an instance of a type. A type is either a C++ object, a
script object or a network. The C++ Unit class is the base class for every
Unit type. The script object API is still to be defined. The default
implementation will be based on ecmascript, since it is included and
well-integrated into the Qt libraries. Network types can refer either to an
internal or to an external network. The unit that encapsulates this network
has a type name that is equal to the fully qualified name of the network.

### Type names

We chose a hierarchical naming scheme for unit type names, loosely based on
perl packages[^1]. Path components are separated by a double column (::). By
convention path components are capitalized.

    Math::Sin
    Control::ForEach

#### Type resolution order

When a unit is created, the type name is searched in the following order:

– local namespace
– override namespace
– global namespace (C++, script)
– include paths

The “local namespace” location needs some explanation. The type name is first
looked up inside the current workspace *file*. This means that the type names
that are registered in the current file are searched. In the case of the root
workspace or any workspace loaded directly from the patch file, this is the
patch file. In the case of an external workspace this the namespace of
the workspace file.

The override namespaces can be used to tweak or replace the behaviour of units
that should not or cannot be modified, ie. system units and external workspace
created by other users. It uses the “override paths” configuration setting to
load external networks. It can be used to set default values that are more
appropriate to a working style, or to wrap newer versions to reproduce old
behaviour to avoid rewriting all patches[^2]. Override paths is used in a
general sense here, since this includes loading plugins and scripts.

Global types are either builtin types, C++ units, scripted units, or type
names in *required* external workspaces. C++ units are loaded and registered
from plugins. Scripted units registered by loaded scripts. External workspaces
can be required, which causes the names of the subworkspaces they contain to
be made available to the entire patch, instead of being limited to the local
file namespace.

Lastly, type names are searched in the include paths.

If the type is not found, the unit is still created but marked as invalid.
This allows files to be loaded even if an external dependency is missing.
Invalid units are reevaluated when a plugin is loaded or if paths are changed.

#### Loading from file paths.

External networks are loaded by path in the “override paths” and “include
paths” system configuration. The first components of the type name are interpreted
as directories.

    // include_paths contains ~/include and /usr/share/jf/include
 
    // search file named ~/include/Foo/Bar.jfm or /usr/share/jf/include/Foo/Bar.jfm
    rootNetwork->addUnit("Foo::Bar");

#### Forcing registered types

The use of a registered type can be forced by prefixing the type name with a
double column (::). Registered types are builtin types or types that were registered
by a plugin. If the registered type is not found, an invalid is created.

    // create a unit of the builtin Math::Sin type
    network->addUnit("::Math::Sin");
 
    // create a unit that may be a local network that overrides Math::Sin
    network->addUnit("Math::Sin");

#### Naming networks

Inside a file namespace, networks are recursively named. The root network is
always called *ROOT* and may never be instanciated twice.

    // subnet0 has type "Foo"
    Unit* subnet0 = rootNetwork->addUnit("System::Network",
        ConfigMap{ Qpair{ "name", "Foo" } });
 
    // subnet1 has type "Foo::Bar"
    Unit* subnet1 = subnet0->addUnit("System::Network",
        ConfigMap{ QPair{ "name", "Bar" } });
 
    // subnet2 has type "Foo::Baz::Bat". Note this may cause conflicts !
    // Unit* subnet2 = subnet0->addUnit("System::Network",
    //     ConfigMap{ QPair{ "name", "Baz::Bat" } });
 
    // subnet3 has type "Bir"
    Unit* subnet3 = subnet0->addUnit("System::Network",
        ConfigMap{ QPair{ "name", "::Bir" } });
 
    // subnet4 has type "Bir::Boom"
    Unit* subnet4 = subnet0->addUnit("System::Network",
        ConfigMap{ QPair{ "name", "::Bir::Boom" } });

Once declared, these types can be used to create new units sharing the same
network.

    Unit* qux = rootNetwork->addUnit("Foo::Baz::Bat");

In case of conflicting names or recursion (a network including itself, either
directly or through the inclusion of subnetworks) results in its parent unit
being invalid.

##### Anonymous networks

When a network is created without explicit name, its name is set to a reserved
unique anonymous name. This name may be queried, and can be used for debugging
purposes, but cannot not be referenced (for instance by addUnit()). The name
may change everytime the network is loaded.

##### Requiring networks

Instead of being loaded implicitely on unit creation, external networks may
also be *required*. This results in the registration of every named network it
contains into the local namespace.

    // load Foo network from a file in the override paths or include paths.
    rootNetwork->addUnit("System::Require", 
            ConfigMap{ QPair{ "name", "Foo" } });

A unit of type “Foo” may now be added to any existing network. The Foo network
may contain sub networks, for instance “Foo::Bar”, or “::Baz” or even
“::Math::FooFunc”. Note that the latter two are not shown as sub networks of
Foo.

Networks may be hidden from exports by prefixing them with an underscore (\_).
The underscore is part of their name, and they aren’t be accessible outside
the network’s local namespace.

The System::Require type can take the “as” config option to rename the
required network to another prefix. This prefix may be empty.

    rootNetwork->addUnit("System::Require", ConfigMap({
        QPair{ "name", "Foo::Bar"},
        QPair{ "as", "Qux" }));
 
    // We can now create a unit of type Qux loaded from Foo/Bar
    rootNetwork->addUnit("Qux");
 
    // Foo::Bar is not a type
    // rootNetwork->addUnit("Foo::Bar");

It also takes the “override” config option to import the network’s types into
the override namespace instead of the local namespace. This is an option to
use with care, as it means that an imported external network may change the
behaviour of types used inside the patch.

### Object names

In Jam Fabric, every object has a unique name. If no name is specified, a
unique name based on the object type is created. Like type names, object names
are hierarchical. Multiple instance of a same unit in a same workspace will
have different names.

    // implicitely set "display_0" name
    rootNetwork->addUnit("IO::Display");
 
    // explicitely set "dumper"
    rootNetwork->addUnit("IO::Display", "dumper");
 
    // assuming a foobarNetwork created earlier
    foobarNetwork->addUnit("Math::Sin", "sin");
    rootNetwork->addUnit("System::Network", "net1",
        ConfigMap{ QPair{"name", "Foo::Bar"} });
    rootNetwork->addUnit("System::Network", "net2", 
        ConfigMap{ QPair{"name", "Foo::Bar"} });
 
    // We now have two units called "net1.sin" and "net2.sin".

This is especially useful in a scripting context, in which the concept of
classes and objects is hidden behind a simpler facade.

    var obj = patch.findObject("net2.sin");
    obj.setInput("input", 3.14);

It is also useful to refer to other units, for instance to access an audio
buffer. Like directory names object paths can be absolute or relative.
Absolute object paths start with a dot (.), relative paths either with a
column (:) or with a name. Each column represent a parent unit.

    fooNet->addUnit("Audio::Buffer", "lady_gaga");
 
    // access local "lady_gaga" buffer
    fooNet->addUnit("Audio::Player", "player", 
        ConfigMap{ QPair{ "buffer", "lady_gaga" } });
 
    // access "lady_gaga" object in other workspace using absolute path
    barNet->addUnit("Audio::Player", "player", 
        ConfigMap{ QPair{ "buffer", ".foo.lady_gaga" } });
 
    // access "lady_gaga" object in grand parent workspace using relative path
    quxNet->addUnit("Audio::Player", "player",
        ConfigMap{ QPair{ "buffer", "::foo.lady_gaga" } });

Wireless communication (inside or between workspaces) is implemented through
System::Bus objects. They are normally not handled directly by the user, but
implicitely created by System::Send objects. Bus objects have names like any
other object, and so listening objects may refer to them using their object
name.

    // send to "schoolbus"
    root.addUnit("System::Send", { bus: "schoolbus" });
 
    // listen to "schoolbus" in local (root) workspace
    root.addUnit("System::Receive", { "bus: "schoolbus" });
 
    // listen to "schoolbus" in root workspace from bar workspace 
    // using absolute path
    bar.addUnit("System::Receive", { "bus": ".schoolbus" });

## Conclusions

This organisation offers the required expressivity that is required to do more
structured programming than what is usually available in visual programming
languages. The added complexity can be hidden in the scripting interface and
in visual client applications. Sharing datastructures saves some memory at the
expense of slightly more indirection and object lifetime management. (With
great power comes great responsability!)

This is work in progress, and some details may change (especially the code
examples). The big missing part here is graph serialization, and how the
values of external networks are saved in patch files. This will be addressed
in the next design document.

If you read all this, you may as well leave me your opinion ! Thanks !

[^1]: Only the sane parts, many aspects can’t be applied to graph-based
programming anyway.
[^2]: Not that authors should break backward compatibility, but in practice it
is good to have a way to handle this.

Test Monkey

February 28th, 2012 by Martijn No comments »

To test my ongoing projects, or rather to do some test based development, I wrote some simple C++ classes and macros that emulate the Qt testing framework with some differences.

– Testing functions don’t need to be in a Q_OBJECT but are normal C-style functions.
– More information about the location of a failed test, debug/warning/error messages and segmentation faults.
– A QLOGCOMPARE macro that displays a diff of two lists of strings that can be populated by a MonkeyLogger stream.

To illustrate how this works, let me show you a short example.

#include <QCoreApplication>
#include <QStringList>
 
#define MONKEY_TESTS
#include "testmonkey.h"
#include "monkeylogger.h"
 
INIT_MONKEY_TESTS
 
void raiseWarning() {
    qWarning("Warning: do not call me !");
}
 
void raiseFault() {
    struct Foo { int bar; };
    Foo* foo = 0;
    foo->bar++;
}
 
MONKEY_TEST(myTest) {
    int a = 5;
    int b = 4;
    QVERIFY(a < 0);
    QCOMPARE(a, b);
 
    MonkeyLogger result;
    MonkeyLogger expected;
 
    expected() << "line1";
    expected() << "line2";
    expected() << "line3";
    result() << "line1";
    result() << "bogus";
    result() << "line3";
    QLOGCOMPARE(result.entries(), expected.entries());
 
    raiseWarning();
//  raiseFault();
 
    QVERIFY(1 > 0);
}
 
MONKEY_TEST(allOk) {
    int a = 0;
    int b = 1;
    QVERIFY(a < b);
    QVERIFY(!a);
}
 
int main(int argc, char *argv[]) {
    QCoreApplication(argc, argv);
    TestMonkey::run();
    return 0;
}

Running this examples yields the following output:

     Test failed at main.cpp:24:
        Expression: a < 0
     Comparison failed at main.cpp:25
        Expression: a
          Expected: "4"
               Got: 5
    Log comparison failed at main.cpp:36
  RESULT                                       EXPECTED                                    
  line1                                        line1                                       
* bogus                                        line2                                       
  line3                                        line3                                       
     -> after main.cpp:36 in test myTest (outside a test macro):
        WARNING: main.cpp:11, void raiseWarning()
            Warning: do not call me !
FAIL myTest (1/4)
OK   allOk
 
1/2 TESTS SUCCEEDED. (3/6 tests)

If raiseFault() line in the myTest method were to be uncommented, the program would stop with the following message:

     -> after main.cpp:36 in test myTest (outside a test macro):
        SEGFAULT caught
Aborted

Some random notes:

– In this example the logging functionality is kind of stupid. In reality it is useful to log signals. A monitor object is create that connects to the signals that are to be monitored and logs a textual representation of the signal to a MonkeyLogger. Another MonkeyLogger object is created in the test function, and logs stores the expected signal representations.
– When debug/warning message and segfaults are caught, the last known location in a test function is displayed. This is the location of the last test macro (QCOMPARE, QVERIFY, QLOGCOMPARE) that was called. If the message was not the result of a call from one of these macros, the displayed message is “after file.cpp:line in test Test (outside a test macro)”, which means the error occurred anywhere between that location and the next test macro or the end of the test function.
– The MONKEY_TEST macro registers a function with the TestMonkey framework using a static TestMonkey object. While this is quick and dirty, it also means that registration order is undetermined if you use multiple object files containing testing functions. This can be a source of errors if they use other global objects, so remember to have everything initialized before calling TestMonkey::run().
– As my current projects use C++11 and this testing framework is mostly for myself (but feel free to use), TestMonkey requires C++11.
– The Qt testing macros that handle data sets are not implemented.

Attached Files:

Jam Fabric (Working title)

January 12th, 2012 by Martijn No comments »

I’ve been influenced a lot by the [puredata][pd] and [vvvv][vvvv] visual environments during the last years, and to a lesser extent by [SuperCollider][sc] and [ChucK][chuck], and now I’m starting work on my own take at a realtime multimedia performance framework. The focus is on collaborative distributed patching. Of course, there is a _scratch my own itch_ and _not invented here (NIH)_ component to this, and some may argue that I should contribute to any of the aforementionned projets instead, but it is my ambition to write something fresh and new from the ground up, starting with the experience gathered in similar projects. The goal here is to create a robust and well-defined platform, that is (relatively) easy to learn and to use, and that combines traditional imperative programming constructs with puredata style message passing.

I’m aiming for a few objectives:

– Modular hardware/library agnostic approach: JF will not be tied to any audio or video library in particular, but is extensible by “engine” plugins. This makes portablility that much easier.
– A well-defined API bridges client code and the processing engine, processing happens in its own memory space. This makes it possible to develop different client types, and provides maximum stability for live performances.
– Graphical programming of patches through a patcher-style user interface. The graphical client may run remotely.
– Programmatic programming of patches and processing objects, either through C++ or Javascript. It should be easy and fun to create new objects, with a minimum amount of setup code required.
– Multi-user collaborative editing and performances.
– Lightweight core: the engine must run on cheap low-performance hardware. A graphical client can connect remotely.
– A standard library of control, math, audio, video, openGL objects. The control objects must cover the same functionality as a modern scripting language does out of the box.
– Typed/Structured ports and connections with automatic conversion. Less wires and in the case of graphical patching, and generally less opportunities for errors. The automatic type conversion make interoperability easier.
– Coherent tree-based naming of objects and object definitions, combining concepts from DOM-trees and [Perl][perl][^1] modules.
– Self-contained documentation: the framework encourages developers of new objects to add documention strings. The graphical front-end uses this information as tooltips. Objects can be searched by name, tag or description. All this to make learning the environment easier.
– Test based development.

I’m using the [Qt][qt] toolkit as it supports much of the basic functionality (UI, network, XML, data structures) that I require, it is portable, and because in my opinion it is beautifully written.

I’ll try to detail each of these points in my next posts.

[^1]: You read this right. Perl. Perl can be as ugly as you want, but its module system and namespaces work great in practice. Just see [CPAN][cpan] !

[cpan]: http://www.cpan.org/
[perl]: http://www.perl.org/
[pd]: http://puredata.info/
[vvvv]: http://vvvv.org/
[sc]: http://supercollider.sourceforge.net/
[chuck]: http://chuck.cs.princeton.edu/
[qt]: http://qt-project.org/

Tool to encode, tag and rename audio files

March 16th, 2011 by Martijn 1 comment »

Wanting to put some order in my collections of band rehearsals, I dug up an old tool I once wrote to automatically tag mp3 files, and extended it to also automatically convert and rename them.

It runs under Linux, and needs a few perl modules and external programs depending on what you want it to do. (MP3::Tag, vorbiscomment, oggenc, lame, mplayer, String::Approx). Modules are loaded dynamically, so you need all of them.

Because some examples say more than…

# Tag and rename all files in current directory using fuzzy match
# against info.txt
$mytagtool
 
# Tag all mp3 files using info.txt, assuming the filename starts 
# with the track number and -
$mytagtool --match "%n - " *.mp3
 
# Encode all wav files to ogg, and tag using files.txt
$mytagtool -o ogg --info-file files.txt *.wav
 
# Recode all ogg files as mp3, and rename them using a pattern.
$mytagtool -o mp3 --force -n "%track:02d%. %album% (%year%) - %title%" *.ogg

An info file would look like this:

artist: Urban Caravan
album: Répèt du 8 mars
year: 2011
 
1. Smoke & Whiskey
2. A'Prova
3. Urban Caravan

Voilà. This script is pretty much untested, so if you want to try it, I would advise you to use the –simulate and –verbose options to see what happens.

Use the perldoc for much more information.

Attached Files: