Tuesday, November 8, 2011

Installing Marsyas on Windows 7 using Visual Studio Express 10


This post is similar to the previous one about installing Marsyas on Ubuntu with the Python bindings. The process is relatively involved but it is worth the effort as having the Python bindings makes prototyping really nice and easier. The instructions are similar to the ones provided in the manual for Windows XP with a few minor changes. First you need to install the necessary tools (cmake, subversion and Visual Studio Express)
  1.  Download the CMake 2.8 windows installer and install. 
  2.  Download the TortoiseSVN graphical user interface client to subversion using either the 32-bit or 64-bit installer depending on your system configuration (I like to tick the box for installing the command-line tools but that's an optional step)
  3. Download Microsoft Visual Studio Express C++ 2010 and install 
  4. Download the latest DirectX SDK and install 

Checkout the latest version of Marsyas from the svn repository by right-clicking on your desktop, selecting svn checkout (Tortoise-svn integrates with Windows and provides this option) and pointing to the
Marsyas svn repository at Sourceforge:
https://svn.code.sf.net/p/marsyas/code

Here is how it looks on my computer:




You can specify where you want the Marsyas source code to be extracted. In my case I selected
to extract on my desktop: C:\Users\gtzan\Desktop\marsyas.

The next step is to run CMake to configure Marsyas and generate the Visual Studio Express 10 solution file.
After installing CMake there should be an colored triangle icon on your desktop labeled CMake (cmake-gui). When you first run CMake make sure you change the generator to Visual Studio 10 and select use native compilers. This is how it should look:




Click on it and Browse Source and Build to specify where the source code resides and where to build the command-line tools. In my case I selected C:/Users/gtzan/Desktop/marsyas/src and C:/Users/gtzan/Desktop/marsyas/build. This is how it looks on my screen:




Click on configure and if everything worked ok. You should see all the pink colored options turn to grey. A common problem is failure to find the DirectX directories. By clicking on the Advanced toggle button you can display all the configuration variables that CMake uses. If the DirectX directories can not be found then you might need to manually specify them by clicking on the button with the three dots next to DSOUND_INCLUDE and DSOUND_LIBRARY. This is how it looks on my screen:



If all the entries are grey now you can generate the Visual Studio C++ 10 solution file by clicking on Generate.

Now you are ready to compile Marsyas using Visual Studio C++ Express 10. (The process is pretty much identical if you have the full version of Visual Studio). Open the marsyas.sln file in the build directory:









 Change the Solution configuration to Release and now finally compile by either clicking F7 or by selecting Debug/Build Solution from the top menu. Wait for a while. If everything went well compilation will fininsh with some warnings but no errors.

You can now check the Marsyas command-line tools that should reside in build/bin/Release (in my case
C:\Users\gtzan\Desktop\marsyas\build\bin\Release). Using the Visual Studio Command Prompt navigate
to the right directory and run:

mudbox -t sine

 


and you should hear a sine wave playing through the speakers. Press ctrl-c to exit. CONGRATULATIONS - Marsyas is installed - happy hacking.


In my next post I will describe how to install Python with NumPy and Matplotlib, swig and how to configure/compile/install the Python bindings for Marsyas. 







Thursday, September 22, 2011

Installing Marsyas with Python bindings on Ubuntu 11.04 Natty Narwhal - 32 bits


Combining the Marsyas python bindings with the matplotlib library for plotting in Python creates a great environment for prototyping. In the past few months I have done a lot of Marsyas work using this approach and really enjoy it. It gives a lot of the expressive power and prototyping of MATLAB while retaining the data-flow model and efficient processing of Marsyas. Unfortunately getting everything installed and setup for the first time takes some effort.

I recently did an installation on a fresh copy of Ubuntu 11.04 - Natty Narwhal - 32 bits and in this blog post I will share the steps I had to take. As usual the exact details change over time so the instructions are slightly different from previous versions of Ubuntu. These instructions can also be found in the Marsyas User Manual as part of the installation instructions for specific systems.

The first step is to get subversion and cmake installed. I did all the package installation directly using apt-get but you can also use the Synaptic package manager for that purpose. Lines that start with $ are to be typed in the terminal. The others are simply comments describing the steps.

$ sudo apt-get install subversion
$ sudo apt-get install cmake
$ sudo apt-get install cmake-curses-gui
$ sudo apt-get install libasound2-dev

Now we are ready to get the latest Marsyas from svn, configure and compile.

$ svn co https://svn.code.sf.net/p/marsyas/code
$ cd marsyas
$ mkdir build
$ cd build
$ ccmake ../src
(Press [c] to continue and [g] to generate the Makefile)
$ make -j 3 (or higher if you have more cores)


When the compilation is finished you can check that the command-line Marsyas tools were compiled.

$ cd bin
$ ./helloWorld
(Press ctrl-c to stop the sine wave from playing)
$ cd ..

If everything worked you will hear a sine wave playing on your speakers.

Now we are ready to get the Python/SWIG bindings going.

$ sudo apt-get install swig
$ sudo apt-get install python-dev
(the python headers)
$ sudo apt-get install python-matplotlib
$ sudo apt-get install ipython

Now we need to reconfigure/compile Marsyas to use Swig to create the python bindings.

$ ccmake ../src
(enable the WITH_SWIG option)
$ make -j 3
$ sudo make install
(install the Marsyas python bindings so that Python can find them)
$ sudo ldconfig /usr/local/lib
(add /usr/local/lib to the path searched for libraries)

If everything has worked you can now combine Marsyas and matplotlib. To check try:

$ cd src/marsyas_python
$ python windowing.py
$ ipython --pylab windowing.py



After running these commands you should be able to see a nice generated figure looking like the image above this paragraph. If you look at the code of windowing.py you will see that the comlputation of the figure data is done through Marsyas. All you need to do is import marsyas at the top of your Python source code. In a future post I will show some utilities that making plotting data from Marsyas networks easy and save you time.






Tuesday, June 21, 2011

Specifying a network using the Swig/Python bindings


The implicit patching model of Marsyas allows the specification of networks at run-time as recursively nested trees. Most of the readers of this blog are familiar with the cumbersome C++ syntax of using a combination of create and addMarSystem. When this run-time mechanism is coupled with a language with reasonable syntax for nested lists such as Python it is easy to use a much more concise syntax. In this post I show how by writing a short simple function this syntax can be enabled in Python. As a further bonus it is easy to serialize the network specification. First let's see how it looks. This example shows a simple filterbank that will take as input a mono sound file, filter it with two different filters and write a stereo sound file where each channel corresponds to the output of each filter. Readers not familiar with the basic composite topologies such as Series and Fanout should read the corresponding sections in the user manual.

net = ["Series/net",
        ["SoundFileSource/src",
        ["Fanout/fanout",
             ["Filter/f1", "Filter/f2"]],
        "Gain/gain",
        "SoundFileSink/dest"]]


It is easy to convert this representation (basically a nested list of strings) into various forms. For example using the json module it is straightforward to convert it to json.

print json.dumps(net)

To get the actual network we need to write a function that converts this representation
to the actual Marsyas commands to create the network. Then we can do something like:

msys = create(net)
print msys.toStringShort()
# typically after creating the network you would 
# update a couple of controls and then start ticking 

Writing such a function in C++ is not trivial but thanks to a little bit of functional magic it is relatively straightforward to write in Python. Here is the create function in Python:

# create a MarSystem from a recursive list specification
def create(net):
  composite = msm.create("Gain/id") # will be overwritten
  if (len(net) == 2):
    composite = msm.create(net[0])
    msyslist = map(create,net[1])
    msyslist = map(composite.addMarSystem,msyslist)
  else:
    composite = msm.create(net)
  return composite

For those unfamiliar with functional programming the map function applies the function specified in it's first argument to each item of the list specified in its second argument and returns a list with the results of each function application. The if statement differentiates composites from basic MarSystems. Basic MarSystems are simply created. For Composites first the composite MarSystem is created, then all of its children are created (recursively by calling the create function as they can also be Composites) and then added to the parent MarSystem.

I hope this post motivates you to try out the Python bindings of Marsyas as well as explore the wonderful ideas of functional programming. Running code can be found under the src/marsyas_python directory of the svn trunk.




Wednesday, April 13, 2011

Lean and Mean Marsyas by Graham Percival

Marsyas can (sometimes with some modifications) be used to write very efficient code that consumes little resources. It has been used in embedded systems and some mutant versions are even running on guitar effect pedals. The following text was provided by Graham Percival and describes how to avoid the startup cost of the MarSystemManager (a factory for creating MarSystems at run-time). This is also important in web application in which the same processing might be initiated every time there is a request and the startup cost needs to be minimized. This initial startup cost is typically not improtant in batch processing applications as it only takes place at the start of processing.

We all know that "premature optimization is the root of all evil"and the old "1. make it work, 2. make it right, 3. make it fast". But sometimes -- very occasionally, but sometimes -- optimization is not premature. Or else you just feel like being naughty. :) On a more serious note, if you are trying to use Marsyas on a system with limited resources such as an embedded system or mobile phone, it may necessary to optimize before deployment. Most Marsyas examples begin with:

MarSystemManager mng;
This initializes one copy of every MarSystem in Marsyas. This "caching" can save resources if you need to create many copies of certain MarSystems, but if you only need a few MarSystems, it means that your program needs to create (and store) a bunch of unnecessary data. Here's a simple example, contrasting the MarSystemManager way to the "lean and mean" way: you can create individual MarSystems as needed, avoiding the MarSystemManager entirely. Note that you need to include the headers you need yourself! The "lean and mean" technique is particularly useful if you want to statically link your application. You can easily contrast the two methods by commenting out the #define.

------------
#define LEAN

#ifndef LEAN
#include "marsyas/MarSystemManager.h"
#else
#include "marsyas/Series.h"
#include "marsyas/SoundFileSource.h"
#include "marsyas/Rms.h"
#include "marsyas/Annotator.h"
#include "marsyas/WekaSink.h"
#endif

using namespace Marsyas;

int main() {
#ifndef LEAN
 MarSystemManager mng;
 MarSystem *net =  mng.create("Series", "extract");
 net->addMarSystem(mng.create("SoundFileSource", "src"));
 net->addMarSystem(mng.create("Rms", "rms"));
 net->addMarSystem(mng.create("Annotator", "annotate"));
 net->addMarSystem(mng.create("WekaSink", "dest"));
#else
 MarSystem *net =   new Series("extract");
 net->addMarSystem( new SoundFileSource("src"));
 net->addMarSystem( new Rms("rms"));
 net->addMarSystem( new Annotator("annotate"));
 net->addMarSystem( new WekaSink("dest"));
#endif

// update controls and run the process loop 
}