Archive for December, 2009

Creating a Plasma effect for the Arduino and the Sparkfun LED tile

Posted in Programming, real-time video on December 26th, 2009 by admin – Be the first to comment

After having discovered the Arduino and before attacking the network extension I wanted to create something fun with the board and the 8 by 8 LED tile.

So I came with the idea of using one old school plasma effect of ArKaos VJ and porting it to the Arduino.

Here is the result:

Basically there are 2 textures pre-computed at startup. They are moved on a circular motion.

The 2 textures are moved and summed and you obtain an height value for each pixel. To get a nice effect you then go through a color table that is also pre-computed at startup.

To have a nice rotation effect you shift the color table at each generation of a new image.

At the end of the video you have another simple loop I did to test my setup.

Here is the plasma code for the Arduino:

//
// Plasma generation for the Arduino and a RGB Serial Backpack Matrix from SparkFun Electronics
// Marco Hinic, built on top of the code of Ryan Owens
//

//Define the SPI Pin Numbers
#define DATAOUT 11//MOSI
#define DATAIN 12//MISO
#define SPICLOCK 13//sck
#define SLAVESELECT 10//ss

void LED_Setup()
{
//SPI Bus setup
SPCR = (1<

//Set the pin modes for the RGB matrix
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);

//Make sure the RGB matrix is deactivated
digitalWrite(SLAVESELECT,HIGH);
}

//
// tables for plasma
//
// 8 by 8 -> 64 bytes
// 16 by 16 -> 256 bytes
// color table 256 bytes
//

#define PLASMA_W 8
#define PLASMA_H 8

#define TABLE_W 16
#define TABLE_H 16

unsigned char gPlasma[PLASMA_W*PLASMA_H];
unsigned char gTable1[TABLE_W*TABLE_H];
unsigned char gTable2[TABLE_W*TABLE_H];
unsigned char gColorTable[256];
float gCircle1, gCircle2, gCircle3, gCircle4, gCircle5, gCircle6, gCircle7, gCircle8;
int gRoll;

void Plasma_CalcTable1 ()
{
for (int i=0; i< TABLE_H; i++)
{
for (int j=0; j< TABLE_W; j++)
{
int index = (i*TABLE_W)+j;
gTable1[index] = (unsigned char) ((sqrt(16.0+(PLASMA_H-i)*(PLASMA_H-i)+(PLASMA_W-j)*(PLASMA_W-j))-4) *5 );
}
}
}

void Plasma_CalcTable2 ()
{
for (int i=0; i< TABLE_H; i++)
{
for (int j=0; j< TABLE_W; j++)
{
int index = (i*TABLE_W)+j;
float temp = sqrt(16.0+(PLASMA_H-i)*(PLASMA_H-i)+(PLASMA_W-j)*(PLASMA_W-j))-4;
gTable2[index] = (sin(temp/9.5)+1)*90;
}
}
}

void Plasma_SetColor (int index, unsigned char red, unsigned char green, unsigned char blue)
{
unsigned char new_color = (red & 0xE0) + ((green & 0xE0) >> 3) + ((blue & 0xC0) >> 6);
gColorTable [index] = new_color;
}

double gRed, gGreen, gBlue;

#define color(u,a) (cos((u)+(a))+1)*127

void BuildColorTable()
{
double u;
int i;
for (i=0; i<256; i++)
{
u=2*PI/256*i;
Plasma_SetColor(i,color(u,gRed),color(u,gGreen),color(u,gBlue));
}

gRed+=0.05;
gGreen-=0.05;
gBlue+=0.1;
}

void Plasma_Setup ()
{
gCircle1 = 0;
gCircle2 = 0;
gCircle3 = 0;
gCircle4 = 0;
gCircle5 = 0;
gCircle6 = 0;
gCircle7 = 0;
gCircle8 = 0;
gRoll = 0;

for (int i=0; i gPlasma[i] = 0;

Plasma_CalcTable1 ();
Plasma_CalcTable2 ();

gRed=1.0/6.0*PI;
gGreen=3.0/6.0*PI;
gBlue=5.0/6.0*PI;

BuildColorTable ();
}

void setup()
{
LED_Setup ();
Plasma_Setup ();
}

void ComputePlasma (int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int roll)
{
int i, j;

for (i=0; i< PLASMA_H; i++)
{
for (j=0; j< PLASMA_W; j++)
{
int index = (i*PLASMA_W)+j;

unsigned int new_height = gTable1[TABLE_W*(i+y1)+j+x1];
new_height = new_height + roll;
new_height = new_height + gTable2[TABLE_W*(i+y2)+j+x2];
new_height = new_height + gTable2[TABLE_W*(i+y3)+j+x3]; // + gTable2[TABLE_W*(i+y4)+j+x4];

new_height = new_height & 0xFF;

new_height = gColorTable[new_height];

gPlasma[index] = new_height;
}
}
}

char SendOneChar (volatile char data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1< {
};
return SPDR; // return the received byte
}

void SendToLEDs ()
{
int i;
//Activate the RGB Matrix
digitalWrite(SLAVESELECT, LOW);
//Send the color buffer to the RGB Matrix
for(i=0; i {
SendOneChar((char)gPlasma[i]);
}
//Deactivate the RGB matrix.
digitalWrite(SLAVESELECT, HIGH);
}

void loop()
{
int x1,y1,x2,y2,x3,y3,x4,y4;

float ratio = 2;

gCircle1 = gCircle1 + (ratio * 0.085/6);
gCircle2 = gCircle2 – (ratio * 0.1/6);
gCircle3 = gCircle3 + (ratio * 0.3/6);
gCircle4 = gCircle4 – (ratio * 0.2/6);
gCircle5 = gCircle5 + (ratio * 0.4/6);
gCircle6 = gCircle6 – (ratio * 0.15/6);
gCircle7 = gCircle7 + (ratio * 0.35/6);
gCircle8 = gCircle8 – (ratio * 0.05/6);

x2=(PLASMA_W/2)+(PLASMA_W/2)*sin(gCircle1);
y2=(PLASMA_H/2)+(PLASMA_H/2)*cos(gCircle2);

x1=(PLASMA_W/2)+(PLASMA_W/2)*cos(gCircle3);
y1=(PLASMA_H/2)+(PLASMA_H/2)*sin(gCircle4);

x3=(PLASMA_W/2)+(PLASMA_W/2)*cos(gCircle5);
y3=(PLASMA_H/2)+(PLASMA_H/2)*sin(gCircle6);

x4=(PLASMA_W/2)+(PLASMA_W/2)*cos(gCircle7);
y4=(PLASMA_H/2)+(PLASMA_H/2)*sin(gCircle8);

ComputePlasma(x1,y1,x2,y2,x3,y3,x4,y4,gRoll);

gRoll = gRoll + 1;

SendToLEDs();

delay (20);
}

Sleepy Sun in concert December 14 2009

Posted in Music, Music Video on December 25th, 2009 by admin – Be the first to comment

I saw Sleepy Sun in concert december 14 in Brussels at “Le Botanique”. It was a magical evening with my princess.

It was in the very cool “rotonde”, it’s a circular arena and it’s magical, you can be very close to the band.

La Rotonde - Botanique

La Rotonde - Botanique

Here is the encore of the concert, they did a cover of “The Chain”. The whole concert was perfect! The song were a little bit longer than the original tracks.

The light show was minimal but it was giving a nice mood to the event. Here is the band at the end of the concert:

Sleepy Sun - Le Botanique - December 14 2009

Sleepy Sun - Le Botanique - December 14 2009

First contact with the Arduino

Posted in Programming, real-time video on December 19th, 2009 by admin – Be the first to comment

I bought a small Arduino board that has a small CPU to prototype some ideas about driving LEDs.

Here is the first test, it’s was quick to have something blinking!

I want to use that as a prototyping platform to develop a protocol to drive LEDs in a simpler way.

Today you drive LED or with DMX or with video converters. DMX is cool and inexpensive but difficult to setup and video converters are very expansive.

There should be a way to connect LEDs to a computer and having them recognized automatically by a VJ software…

If you are curious to see on how simple the code is, here it is:

// Writing to the RGB Serial Backpack Matrix from SparkFun Electronics
// Marco Hinic, built on top of the code of Ryan Owens
//

//Define the SPI Pin Numbers
#define DATAOUT 11//MOSI
#define DATAIN 12//MISO
#define SPICLOCK 13//sck
#define SLAVESELECT 10//ss

//Define the variables we’ll need later in the program
char color_buffer [64];

void setup()
{
//SPI Bus setup
SPCR = (1<

//Set the pin modes for the RGB matrix
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);

//Make sure the RGB matrix is deactivated
digitalWrite(SLAVESELECT,HIGH);

}

void SendToLEEDs ()
{
//Activate the RGB Matrix
digitalWrite(SLAVESELECT, LOW);
//Send the color buffer to the RGB Matrix
for(int LED=0; LED<64; LED++){
spi_transfer(color_buffer[LED]);
}
//Deactivate the RGB matrix.
digitalWrite(SLAVESELECT, HIGH);
}

void loop()
{

char color = 0;
while(1)
{
for (int i=0; i<64; i++)
{
color_buffer[i] = color + i;
}

color = color+1;

SendToLEEDs ();

delay (100);

}
}

//Use this command to send a single color value to the RGB matrix.
//NOTE: You must send 64 color values to the RGB matrix before it displays an image!
char spi_transfer(volatile char data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1< {
};
return SPDR; // return the received byte
}

Using the right decompression engine with ArKaos GrandVJ and MediaMaster

Posted in ArKaos, Article, real-time video on December 10th, 2009 by admin – Be the first to comment
Animation Facilities

Animation Facilities

One of the thing we did master after more than 10 years of learning the various API that can be used on Mac and Windows to decompress video is that not all facilities are equal.

We believe that you should be able to use almost any kind of medias with the ArKaos software and we will make our best to get the best performances on the platforms we support.

Practically we can open media thought those facilities : QuickTime, FFmpeg, Flash plugin, Quartz Composer and Windows Media.

Currently as december 2009 we don’t give the choice to the use to decide through what facility a media will be decoded, we try to take the best decision automatically based on our experience of doing that since so many years.

Several video codecs such as mpeg 4 can be read by QuickTime, FFmpeg and Windows Media. Based on our experience and tests we prefer to first try to handle those codecs with FFmpeg and we invite our users to trust us in our judgment.

Sadly QuickTime has become today almost obsolete and is just used to decompress the codecs needed by the iPods. Most codecs are not properly multi threaded and this is a big problem for us. With GrandVJ or MediaMaster you can use a multi core machine and make sure that each cores will be used to decompress the video layers you are mixing, this is only true if you are not playing videos that absolutely need the QuickTime support.

Windows Media is a wonderful technology but it’s architecture is completely incompatible with the sophisticated engine we use to do frame blending and frame prediction in the latest version of GrandVJ and MediaMaster.

Flash animations and Quartz Composer are unique in the sense that nothing else than the flash plugin or Quartz composer will handle their files.

So the conclusion of this introduction is that to get the best multi threaded performance and be sure that GrandVJ or MediaMaster can perform frame blending you should make sure that your content is played through FFmpeg. Once you open a media file your content can go through various roads and it’s important to understand that.

ArKaos Animation Processing

ArKaos Animation Processing

On the windows side it’s pretty simple because the software first try to play a file with the FFmpeg facility and then fall back to the other if needed.

On the Mac it’s more complicated because some files that could be played by FFmpeg may be rejected just because they are not saved in the right way. Many QuickTime files are created in a way that make them compatible with Mac OS X but also it’s old ancestor Mac OS 9 and 8 and 7 and … Those files used what is called a resource fork. When Apple introduced the Macintosh they decided that a file would indeed be really 2 files, the classical data file with an optional resource file. Many softwares used that resource files to store additional data. This is the case for many .mov files created many years ago and still today some application that were born under the Mac OS 9 time generate QuickTime .mov files that have a resource fork. This is a problem for us because we can’t handle those file with the FFmpeg facilities and we fall back to QuickTime that has a very bad multi core support for very common codecs such as photo jpeg. A very bad side effect of this resource fork is that most of the time when you copy a movie file that has a resource fork on a Windows or Linux machine it will simply not work because that tiny information in the resource fork is vital to play the content.

Here is a QuickTime file that has a resource fork, it’s opened with a programming utility called Resorcerer:

Slow Rain With Resource

Slow Rain With Resource

And here is the same file that has been flattened:

Slow Rain With Flattened

Slow Rain With Flattened

Hopefully it’s very easy to save a QuickTime file that has a resource fork in a way that will remove that annoying hidden data. The process is called flattening a file. You simply use the QuickTime player and save as your content.

But first here is how you can see what player is used by the ArKaos engine when processing a file, you simply leave your mouse over the cell that has the loop and you see the contextual help popping, here is for the video file with a resource fork that will be played through QuickTime:

GrandVJ playing a file through QuickTime

GrandVJ playing a file through QuickTime

And here is what you see once your video is flattened with the QuickTime player and goes through the FFmpeg path:

GrandVJ playing through FFmpeg

GrandVJ playing through FFmpeg

To flatten the file you simply open it with the QuickTime player, the pro version is not needed, and you save as:

QuickTime Save as

QuickTime Save as

And enter a new name:

QuickTime enter name

QuickTime enter name

This process is very fast and will not re-compress your movie, this is very important to avoid re-compressing when possible.

You will only need to do that if your file was created on a Mac, the free version of the QuickTime player is enough to do this. This manipulation work on all the versions of Mac OS X up to Snow Leopard with the latest new QuickTime player.

During the introduction of our new audio engine based on FFmpeg some users have complained that some old .mov files were not playing correctly audio with the beta version, this should fix this problem. More than that flattening your file will make them cross platform.

This should give some lights on what is happening when you drop a file on GrandVJ or MediaMaster, as you can see a lot of work is being done under the hood.