Cmajor?

Voorbeeldje om te zien hoe code zich laat lezen.

Code:
/*
    Cmajor Freeverb Example
    =======================

    Yes folks, it's yet another implementation of that classic Freeverb algorithm
    that we all know and love!

    Big shout out to Jezar, the original author of Freeverb :)
*/

graph Freeverb   [[ main ]]
{
    input stream float audioIn;
    output stream float<2> audioOut;

    input parameterScaler.roomSize  [[ name: "Room Size",       min: 0, max: 100, init:  80, text: "Tiny|Small|Medium|Large|Hall" ]];
    input parameterScaler.damping   [[ name: "Damping Factor",  min: 0, max: 100, init:  50, unit: "%",  step: 1 ]];
    input parameterScaler.width     [[ name: "Width",           min: 0, max: 100, init: 100, unit: "%",  step: 1 ]];
    input parameterScaler.wetLevel  [[ name: "Wet Level",       min: 0, max: 100, init:  33, unit: "%",  step: 1 ]];
    input parameterScaler.dryLevel  [[ name: "Dry Level",       min: 0, max: 100, init:  40, unit: "%",  step: 1 ]];

    //==============================================================================
    node parameterScaler   = ParameterScaler;
    node wetGainSmoother   = std::smoothing::SmoothedValueStream (0.02f);
    node dryGainSmoother   = std::smoothing::SmoothedValueStream (0.02f);
    node widthSmoother     = std::smoothing::SmoothedValueStream (0.02f);
    node dampingSmoother   = std::smoothing::SmoothedValueStream (0.02f);
    node feedbackSmoother  = std::smoothing::SmoothedValueStream (0.02f);

    node reverbL = MonoReverb (0);
    node reverbR = MonoReverb (23);

    node mixer = WetDryMixer;

    connection
    {
        audioIn -> mixer.audioInDry;
        audioIn -> reverbL.audioIn; reverbL -> mixer.audioInWetL;
        audioIn -> reverbR.audioIn; reverbR -> mixer.audioInWetR;

        parameterScaler.wetGainOut  -> wetGainSmoother  -> mixer.wetGain;
        parameterScaler.dryGainOut  -> dryGainSmoother  -> mixer.dryGain;
        parameterScaler.widthOut    -> widthSmoother    -> mixer.width;
        parameterScaler.dampingOut  -> dampingSmoother  -> reverbL.damping, reverbR.damping;
        parameterScaler.feedbackOut -> feedbackSmoother -> reverbL.feedback, reverbR.feedback;

        mixer -> audioOut;
    }
}

//==============================================================================
// This processor intercepts incoming parameter events and rescales them to the correct range
processor ParameterScaler
{
    input event float roomSize, damping, wetLevel, dryLevel, width;
    output event float wetGainOut, dryGainOut, widthOut, dampingOut, feedbackOut;

    let wetScaleFactor  = 1.5f;
    let dryScaleFactor  = 2.0f;
    let roomScaleFactor = 0.28f;
    let roomOffset      = 0.7f;
    let dampScaleFactor = 0.4f;

    event roomSize (float newValue)    { feedbackOut <- newValue * roomScaleFactor / 100.0f + roomOffset; }
    event damping  (float newValue)    { dampingOut  <- newValue * dampScaleFactor / 100.0f; }
    event dryLevel (float newValue)    { dryGainOut  <- newValue * dryScaleFactor / 100.0f; }
    event wetLevel (float newValue)    { wetGainOut  <- newValue * wetScaleFactor / 100.0f; }
    event width    (float newValue)    { widthOut    <- newValue / 100.0f; }
}

//==============================================================================
processor WetDryMixer
{
    output stream float<2> out;

    input stream float audioInDry, audioInWetL, audioInWetR;
    input stream float width, wetGain, dryGain;

    void main()
    {
        loop
        {
            let wetGain1 = wetGain * (1.0f + width);
            let wetGain2 = wetGain * (1.0f - width);

            let wet = float<2> (audioInWetL * wetGain1 + audioInWetR * wetGain2,
                                audioInWetR * wetGain1 + audioInWetL * wetGain2);

            out <- wet + dryGain * audioInDry;
            advance();
        }
    }
}

//==============================================================================
graph MonoReverb (int offset)
{
    input stream float audioIn, damping, feedback;
    output stream float audioOut;

    node comb1 = CombFilter (float, offset + 1116);
    node comb2 = CombFilter (float, offset + 1188);
    node comb3 = CombFilter (float, offset + 1277);
    node comb4 = CombFilter (float, offset + 1356);
    node comb5 = CombFilter (float, offset + 1422);
    node comb6 = CombFilter (float, offset + 1491);
    node comb7 = CombFilter (float, offset + 1557);
    node comb8 = CombFilter (float, offset + 1617);

    node allpass1 = AllpassFilter (float, offset + 225);
    node allpass2 = AllpassFilter (float, offset + 341);
    node allpass3 = AllpassFilter (float, offset + 441);
    node allpass4 = AllpassFilter (float, offset + 556);

    connection
    {
        audioIn -> comb1.in,
                   comb2.in,
                   comb3.in,
                   comb4.in,
                   comb5.in,
                   comb6.in,
                   comb7.in,
                   comb8.in;

        damping -> comb1.damping,
                   comb2.damping,
                   comb3.damping,
                   comb4.damping,
                   comb5.damping,
                   comb6.damping,
                   comb7.damping,
                   comb8.damping;

        feedback -> comb1.feedback,
                    comb2.feedback,
                    comb3.feedback,
                    comb4.feedback,
                    comb5.feedback,
                    comb6.feedback,
                    comb7.feedback,
                    comb8.feedback;

        comb1,
        comb2,
        comb3,
        comb4,
        comb5,
        comb6,
        comb7,
        comb8  -> allpass1 -> allpass2 -> allpass3 -> allpass4  -> audioOut;
    }
}

//==============================================================================
processor AllpassFilter (using FrameType, int delayLength)
{
    input  stream FrameType in;
    output stream FrameType out;

    FrameType[delayLength] buffer;
    wrap<delayLength> index;

    void main()
    {
        loop
        {
            let newValue = in;
            let delayedValue = buffer[index];
            buffer[index] = newValue + (delayedValue * FrameType (0.5));
            out <- delayedValue - newValue;
            ++index;
            advance();
        }
    }
}

//==============================================================================
processor CombFilter (using FrameType, int delayLength)
{
    input  stream FrameType in;
    output stream FrameType out;
    input  stream float damping, feedback;

    FrameType[delayLength] buffer;
    wrap<delayLength> index;
    FrameType last;
    let gain = 0.015f;

    void main()
    {
        loop
        {
            let delayedValue = buffer[index];
            out <- delayedValue;
            last = last * damping + delayedValue * (1.0f - damping);
            buffer[index] = last * feedback + gain * in;
            ++index;
            advance();
        }
    }
}
 
Dat ziet er niet heel ingewikkeld uit, althans niet ingewikkelder dan Faust. Maar ik wacht tot het wat verder uitontwikkeld is (en de bugs en kinderziektes eruit zijn) voor ik het zelf probeer.
 
Heb de indruk dat bij veel van dit soort projecten het eigenlijk nooit tot dat punt komt, helaas.

Dat ligt eraan of de nieuwe programmeertaal aanslaat. Zo ja - dan krijg je vanzelf een community die zich daarvoor gaat inzetten, maar zo nee - dan bloedt het dood. Op zich lijkt mij een simpele op audio toegespitste versie van C++ wat Cmajor wil zijn, wel een zinnige toevoeging aan wat er al bestaat.
 
Dat ligt eraan of de nieuwe programmeertaal aanslaat. Zo ja - dan krijg je vanzelf een community die zich daarvoor gaat inzetten, maar zo nee - dan bloedt het dood. Op zich lijkt mij een simpele op audio toegespitste versie van C++ wat Cmajor wil zijn, wel een zinnige toevoeging aan wat er al bestaat.
Ik vermoed dat deze wel eens aan de kinderziekten zal ontsnappen. Soundstacks maakt deel uit van Native Instruments en een van de programmeurs is diegene die het JUCE framework geschreven heeft. Sinds Native Instruments in-house niet meer met Reaktor werkt, vraag ik me af of dit hun nieuwe technology is.
 
Laatst gewijzigd:
Net gezien dat je met de online Faust IDE Faust programma's als cmajor-progjes kunt exporteren.
 
Back
Top