0

I'm not sure whether SuperCollider can deliver moons on sticks, but I'd really like to be able to specify values in my Pbind that are interpreted in the same way as midinote or degree: i.e. converted automatically to a frequency.

So, an excerpt of such a Pbind, which produces a TB-303-style slide from one frequency to another:

b = Pbind(*[
    out: 0,
    instrument: \acid,
    stepsPerOctave: 19,
    scale: [0, 3, 5, 8, 11, 14, 17],
    octave: 3,
    degree: Pseq([0, \, 3, 3, 4, 4, 9, 4, 4]),
    prevFreq: Pseq([\, \, 0, 3, 3, 4, 4, 9, 4]),
    dur: Pseq([0.4, 0.4, 0.1, 0.1, 0.1, 0.1, 0.2, 0.1, 0.1]),
]);

...it would be super-duper if prevFreq were interpreted as containing degree values in the same way as degree.

In the absence of some kind of automatic conversion, I assume I need to do some kind of calculation within the synth itself in order to convert my values from a degree-type value to an actual frequency. I'm aware I can use foo.midicps to convert midinote-type values to a frequency, but is there a similar convenience function to convert degree-type values to a frequency (presumably also using the current scale and octave values)?

David
  • 15,750
  • 22
  • 90
  • 150

1 Answers1

1

If you look at the helpfile for Event, you can see how it computes the frequency from the degree and scale:

note: #{    // note is the note in halftone steps from the root
    (~degree + ~mtranspose).degreeToKey(~scale, ~stepsPerOctave);
}
midinote: #{    // midinote is the midinote (continuous intermediate values)
    ((~note.value + ~gtranspose + ~root) / ~stepsPerOctave + ~octave) * 12.0;
}
freq: #{
    (~midinote.value + ~ctranspose).midicps * ~harmonic;
}
detunedFreq: #{    // finally sent as "freq" to the synth as a parameter, if given
    ~freq.value + ~detune
}

Event is an associative array and those ~variables can also be used as keys to the array (something which will hopefully become clear in a moment. It's also possible to get access to the events in a Pbind, by using a Pfunc. Let's say we want to calculate the current frequency for your Pbind:

b = Pbind(*[
    out: 0,
    instrument: \default,
    stepsPerOctave: 19,
    scale: [0, 3, 5, 8, 11, 14, 17],
    octave: 3,
    degree: Pseq([0, \, 3, 3, 4, 4, 9, 4, 4]),
    dur: Pseq([0.4, 0.4, 0.1, 0.1, 0.1, 0.1, 0.2, 0.1, 0.1]),
    foo: Pfunc({|evt|
        var note, midinote, freq, detuned, result;
        note = (evt[\degree] + evt[\mtranspose]).degreeToKey(evt[\scale], evt[\stepsPerOctave]);
        midinote = ((note + evt[\gtranspose] + evt[\root]) / evt[\stepsPerOctave] + evt[\octave]) * 12.0;
        freq =  (midinote + evt[\ctranspose]).midicps * evt[\harmonic];
        detuned = freq + evt[\detune];
        detuned.postln;
    })
]).play

Those calculations for note, midinote, freq and detuned freq are the same calculations we saw in the event helpfile. Therefore, this Pbind will now print out the frequency that you are currently playing.

What you actually want is the frequency you were previously playing, which we could figure out from your array of previous degrees. Or we could just keep track of the previous frequency in a variable. This will be a lot easier to keep track of!

(

var prev;

b = Pbind(*[
    out: 0,
    instrument: \default,
    stepsPerOctave: 19,
    scale: [0, 3, 5, 8, 11, 14, 17],
    octave: 3,
    degree: Pseq([0, \rest, 3, 3, 4, 4, 9, 4, 4]),
    dur: Pseq([0.4, 0.4, 0.1, 0.1, 0.1, 0.1, 0.2, 0.1, 0.1]),
    prevFreq: Pfunc({|evt|
        var note, midinote, freq, detuned, result;

        if (evt[\degree] == \rest, { detuned = \rest} , {
            note = (evt[\degree] + evt[\mtranspose]).degreeToKey(evt[\scale], evt[\stepsPerOctave]);
            midinote = ((note + evt[\gtranspose] + evt[\root]) / evt[\stepsPerOctave] + evt[\octave]) * 12.0;
            freq =  (midinote + evt[\ctranspose]).midicps * evt[\harmonic];
            detuned = freq + evt[\detune];
        });

        //detuned.postln;

        if (prev.isNil(), { 
            result = \rest;
            } , 
            {
                result = prev;
        });

        prev = detuned

    })
]).play
)
les_h
  • 347
  • 1
  • 8