Music2Light (M2L)

   Print  Previous  Next

Introduction

Sound2Light effects are really nice, but an even more interesting feature of MADRIX is the ability to analyze music regarding music theoretical aspects. Tonality, scale or intervals are only some examples of the data that can be retrieved by the sound analysis. This chapter describes how to retrieve the data provided by MADRIX. However, it does not describe any music theory.

 

Using Tonality Ánd Scale

Let us start with tonality and scale of a chord. The two be retrieved via the functions GetTonality and GetToneScale, respectively. The exemplary sample source code below uses tonality and  scale to select a color and the alpha value will be the background color. Please remember: an audio input signal is needed.

const color g_colorTable[] = {

            {255, 0, 0, 0},         //C

            {255, 128, 128, 128},   //C#

            {0,  255, 0, 0},        //D

            {128, 255,128,128},     //D#

            {0,  0,   255,0},       //E

            {255, 255, 0, 0},       //F

            {255, 255, 128, 128},   //F#

            {255, 0, 255, 0},       //G

            {255, 128,255,128},     //G#

            {255, 128, 0, 0},       //A

            {255, 100, 100, 100},   //A#

            {255, 255, 255, 128}    //H

                             };

void InitEffect()

{

}

 

void RenderEffect()

{

    int idx=GetTonality();

    if (idx>=0 && idx<=11) ClearColor(g_colorTable[idx]);

    else ClearColor(BLACK);

    int alpha = (255 / (1 + GetToneScale()));

    ClearAlpha(alpha);

}

 

Explanation:

The first thing is to create a color table in which each entry equals a tonality. If the tonality is undetermined, the function GetTonality results in -1. Therefore, we have to check if the value is a valid field index and eventually draw a black matrix. You could use the function IsTonality to check if the tonality was set or not.

 

Using Notes

MADRIX is able to identify the notes played in a song. The lowest note that can be evaluated is the C with 8.25 Hz. The highest note is an A with 14.08 kHz. There are two functions available to get information about the identified notes. GetNoteValue retrieves the volume of the given note and IsNote returns true if the given note has been detected, otherwise false. There is the function GetAllNoteValues, which fills an field with the volume of each note. Using this method for a lot of notes is much faster then calling GetNoteValue. An overview over which index corresponds to which note is given by the list of notes.

The next example uses played notes to fill the matrix with different colors. It uses only the values of three frequencies of C.

void InitEffect()

{

}

 

void RenderEffect()

{

    float val[];

    //C with 528Hz

    val[0] = (float)GetNoteValue(72) / 127.0;

    //C with 1.056KHz

    val[1] = (float)GetNoteValue(84) / 127.0;

    //C with 2.112KHz

    val[2] = (float)GetNoteValue(96) / 127.0;

 

    color c;

    c.r = (int)(255.0 * val[0]);

    c.g = (int)(255.0 * val[1]);

    c.b = (int)(255.0 * val[2]);

 

    Clear(c);

}

 

Explanation:

First, the levels of the notes are retrieved and normalized to the range of 0.0 to 1.0. Hereby, only three C notes are used. Then, a color is initialized and the matrix is filled.

Deprecated Functions
Deprecated functions are outdated functions and should not be used anymore.

Please note: The old functions GetValue and GetAllValues still exist, but have been declared as deprecated and should not be used anymore. They may be removed in coming versions of MADRIX Script. Use GetNoteValue and GetAllNoteValues instead.

 

Using Intervals

There are similar functions to get information about the intervals indexed from 0 (small second interval) to 10 (large seventh interval). The function IsInterval returns true if the specified interval  could be analyzed, otherwise false. Again, the function GetAllIntervals fills an field rapidly, each element with either true (interval was analyzed) or false (interval was not analyzed). The following short example clarifies the usage of GetAllIntervals:

const int middle=GetMatrixHeight()/2;

int buf[];

int xStep;

 

void InitEffect()

{

    GetAllIntervals(buf);

    xStep=max(GetMatrixWidth()/buf.length,1);

}

 

void RenderEffect()

{

    ClearAlpha(255);

    GetAllIntervals(buf);

    for (int i=0;i<buf.length;i++)

    {

        DrawPixelLine(WHITE,i*xStep,!buf[i]*middle,i*xStep,(1+!buf[i])*middle);

    }

}

 

 

Explanation:

At first, in InitEffect the buffer buf is filled once, just in order to get the buffer length. With the buffer length, a horizontal distance xStep is calculated to separate some lines equally later on. Using the function max, the distance is at least 1.

Calling RenderEffect the buffer buf is filled with the current interval appearances. Then, a vertical line is drawn for every interval, either from the middle to the top of the matrix (if the interval was analyzed) or from middle to bottom (if not).

 

Using Other Tone Theoretical Parameters

There is lots of other data which may be used to create effects, e.g. the sound level or the note of the currently lowest note (bass tone). The handling is similar to the functions described above. Further details are given by the List of Functions.