Mutable Instruments Braids(& other) UGen SC ports frequency input instead of midi

Hello there,
the Mi-Braids UGen accepts only midinotes as input,
since I’m working in ET53 & other non standard tunings,with 432 Hz as reference freq
I realized using \midinotes in Pbinds will give me 440Hz as reference freq

now, converting with cpsmidi / midicps , which are based on ET12 , won"t work either …

Would someone be willing to change the input in the open source code of Mutable Instruments
to frequency & port it to SC? Or can you comment on how complex/easy that would be for a novice in cpp or c …

In all other SynthDefs that just use frequency as input, i use this (if i would have to be using midi, i prefer, degrees, freqs):

|midinote|
freq = 432 * (2 ** ((midinote - 69) / 53));
    sig = SinOsc.ar(freq, 0, amp)!2;

to have my reference freq 432 as midi note 69 … which works brilliantly
but in this MI-Ugen case it won’t work for obvious reasons: 432 as midinote = a NO-GO ! :poop:

I realise there is a stepsPerOctave arg in the Pbind class
but i’m not sure how that relates to midinotes (i think that’s of no influence)
& that it’s more related with degrees, scale , tuning … which again is of no influence on midiinput
by Mi-Braids UGen , i guess …

== apart from Mi-Ugens with midi input,
is there someone who knows exactly how
to manage/surf in ET53 with steps per octave, degrees, notes, scale, tuning ?
in Pbinds … i’m actually trying to build some scales from pitch class intervals
as suggested by acreil in his comments of his youtube EDO xxx compositions …

" the idea = a computational search for consonant n- note scales, which can then be connected into scale networks (as in Dmitri Tymoczko’s work). I wrote a number of Octave scripts to do this. First, all possible scales are found, then most are eliminated based on step size constraints and calculated total dissonance. The idea is to find the “useful” scales that can be made in any arbitrary equal temperament. Here I’m using 568 scales out of a total of 433160. "

acreil edo compositions

no idea how to do a computational elimination (well, i wrote a little Python script to find all possible
n-note scales in ET53, based on pitch class intervals) & obtain a scale network that endlessly navigates on the waves of bliss frequencies _ _ _ :surfing_woman:

Dmitri Tymoczko

1 Like

Did I miss something? With that you can get started.

Post << Scale.chromatic(tuning: 'et53');
(
s.waitForBoot({
	a  = Scale.chromatic(tuning: 'et53');

    p = Pbind(
		\degree, Pseq( (0..52), inf),
        \scale, Pfunc({ a }, inf),
		\dur,  Pfunc({ rrand(0.01,0.3 )}, inf)
    );

    q = p.play;
})
)

From help:

“Creates a Scale from scratch. degrees should be an array of Integers or scale name. If pitchesPerOctave is nil, will guess the most appropriate number based on degrees. tuning can be an instance of Tuning or a symbol; if nil, will be equal temperament of pitchesPerOctave. Specify descDegrees if the Scale should play differently when descending than when ascending; otherwise it should be nil.”

2 Likes

It is a no-go if you are using classical 7-bit MIDI to transmit note numbers.

SC uses 32-bit floats to transmit numbers, so we are not subject to the integer note-number limitation.

If I do this:

(
SynthDef(\braids, { |midinote = 60, gate = 1, amp = 0.1, out = 0|
	var sig = MiBraids.ar(midinote);
	var eg = EnvGen.kr(Env.adsr(0.01, 0.3, 0.6, 0.1), gate, doneAction: 2);
	Out.ar(out, (sig * eg * amp).dup)
}).add;
)

(instrument: \braids, midinote: 60, sustain: 2).play;

(instrument: \braids, midinote: 60.5, sustain: 2).play;

… I clearly hear the quarter-tone difference. It is definitely not quantized to a semitone.

I think this may be a non-problem, then? mi-UGens/projects/MiBraids/MiBraids.cpp at 28bdfd9bb486083f54f1a687b85625a7b5f74d11 · v7b1/mi-UGens · GitHub shows that the incoming float pitch is being converted to 14 bits, which will certainly give better than semitone pitch resolution.

hjh

2 Likes

8 octaves … 53 notes/ octave = 424 notes … not sure, i tried to map 424 frequencies into 128 midinotes
it worked out + - …
midinotes.txt (7.3 KB)

(
// Open a file for writing
var file = File("/Your-very-own-Black-Midi-Path/midinotes.txt".standardizePath, "w");

// Define the number of MIDI note numbers
~numMIDINoteNumbers = 128;

// Define the number of frequencies in the ET53 scale
~numET53Frequencies = 424;

// Calculate the step size for mapping ET53 frequencies to MIDI note numbers
~stepSize = ~numMIDINoteNumbers / ~numET53Frequencies;

// Map ET53 frequencies to decimal MIDI note numbers
~et53ToMIDIMap = (0..(~numET53Frequencies - 1)).collect { |i|
    (i * ~stepSize).postln; // Print the decimal MIDI note number for debugging
};

// Print the decimal MIDI note numbers
~et53ToMIDIMap.postln;


// Write each frequency to the file

~et53ToMIDIMap.do { |note| file.write(note.asString+",\n") };

// Close the file
file.close;
)
 

all in all, not sure if \midinotes, even decimals are truly compatible with other ETs … or are actually only to use in ET12 … that is the question … in ET12 you have all the notes of 10 octaves in 128 midinotes …
… seems to be ideal for ET12 …

would make more sense & straightforward (without all the hassle :slight_smile: ) if it just were frequencies to work with (~ MiBraids ) or with scale, degree, tuning, stepsPerOctave etc. as it’s easier to manipulate in modulating or transpose

Did you try just writing MiBraids.ar(freq.cpsmidi) in your SynthDef?

AFAICS this will quantize to 1/128 divisions of semitones, which is close enough for human perception.

hjh

I think it is understood that 72ET is good enough already.
The good thing is that it contains all traditional and modern accidentals and the other ones already have their accidental symbols more of less standard (with variations)

It’s the sweet spot in my opinion

Braids isn’t using 128ET; it’s dividing semitones into 128 parts (not octaves / 128) – that is, slightly better than cents resolution. (Cents = 1200ET; Braids would be 128 * 12 = 1536ET.) EDIT: That “no-go” 432 Hz would become 432.cpsmidi.round(1/128).midicps = 431.934 Hz, which difference I’m willing to bet nobody would notice.

The SC port just wraps the MI c++ classes in a (relatively thin) SC UGen layer, which converts incoming float parameters into the data format that the Braids code expects.

hjh

1 Like

thanks, I got the specific problem in question here. It’s quite specific indeed.

I was describing the approach I adopted in a system that I wanted to be as general as possible, and I concluded that 72 is the sweet spot (and I was also thinking about traditional music notation as one of the aspects). Maybe I’m wrong, and there is no such thing as a sweet-spot.

thanx ! but that’s probably taking root freq = 440 Hz
as is midicps or cpsmidi … but it is okay indeed to have a feel , to try it out and later change to 432 Hz as base frequency …

I believe there is no rootfrequency or base frequency argument in Tuning … so you have to take a deviation to obtain it …

! hm interesting

Just calculate the frequency you want and .cpsmidi it, and you’re done.

It’s really significantly less of a problem than you think.

hjh

*cpsmidi is with 440Hz as root … so it gives other results than with 432Hz based frequencies … *
but i, for now abandoned the idea of Braids & its midi stuff … i’ll try later if the decimals are
+ - similar to the ET53 calculated freqs …

No, no at the moment
I have an array of 424 ET53 (432Hz base f) , frequencies & i’m looking how to distribute / spread it over real midi keys … like in a lumatone isomorphic midi keyboard … but around 4000 dollar … so i want to try it out with a push controller, that also has visual feedback (color of pads) - i mean don’t know if this is even possible …

lumatone droney subtle ET53 exploration

it felt very much being in a wood
sequencing in ET53 … too many trees to see the pathway if you like … so i went to check out the lumatone organisation of keys … & it made sense to have clusters of whole notes, half notes & then further down ## ‘quarter tones’, & even further down the line … until the 41 rest of the keys are taken …

Again – midinote numbers in sc are floating point – you do not have to worry about integer midi notes.

The problem goes away if you implement it in the way that I suggested a day or two ago. There is no good reason to reject that solution.

hjh

Note that the difference between choosing 440 and 432 as the root is the constant midinote value of 0.31766653633429, so if is important for your setup that 432 is an integer midi note value, you can simply add the constant to all midi note values when mapping to keys. Here shown with normal ET12.

// root
~offset = 440.cpsmidi - 432.cpsmidi // 0.31766653633429

440.cpsmidi // 69.0
432.cpsmidi // 68.682333463666
432.cpsmidi + ~offset // 69.0

// some other note, here I chose the 9th above the root, so add 14 midinotes

(69 + 14).midicps // 987.76660251225
(432.cpsmidi + 14).midicps // 969.8072097393
969.8072097393.cpsmidi // 82.682333463666
(82.682333463666 + ~offset) // 83.0 = 69 + 14
1 Like

I think I understand what you are asking now. As understand it, you want to find out how to convert the ET53 frequencies to integer numbers. If this is what you want, maybe this can be helpful:

~offset = 440.cpsmidi - 432.cpsmidi // 0.31766653633429
t = Tuning.et53;
t.ratios;

/// first 5 frequencies of ET53 starting at 432 Hz

~et53notes = 5.collect{|i| 432 * t.ratios[i] } // [ 432.0, 437.68690978674, 443.44868286728, 449.28630475273, 455.20077392761 ]

~nns = ~et53notes.cpsmidi + ~offset // [ 69.0, 69.226415094339, 69.452830188677, 69.679245283016, 69.905660377355 ]
~midiratio = t[1]; // ET12 midiratio: 1.midiratio = 1.0594630943591, ET53 midiratio: t[1] = 1.0131641430249;
~nns.collect{|n, i| ( n - ~nns[0] / ~midiratio ).round(0.0000001) } // [ 0.0, 1.0, 2.0, 3.0, 4.0 ]

An easier way is simply to create a lookup table for frequencies (maybe with some rounding) and then do ~loopUpTable.indexOf(~somefreq) to get the scale degree. Or maybe this freqToDegree method is already there in SC and can adapt to tunings, I didn’t check.

Or am I misunderstanding the whole thing?

1 Like

Ah, I missed that – apologies to @pajzd , I was focused on the transport mechanism to get the frequency into the synth and then on to MiBraids.

Event has a couple of ways to shift tuning away from 440:

e = (midinote: 69, ctranspose: (432/440).ratiomidi).play;
e[\freq]  // 432.0

e = (midinote: 69, harmonic: 432/440).play;
e[\freq]  // 432.0

And the \note key is for any-number-of-divisions-you-like. (\midinote is always 12ET; \note is any ET you want.) So then you can write 53ET integers for \note.

// relative to C, "A" would be 39.75 in 53ET
// so you won't get exactly 432 with C as the reference
e = (note: 40, stepsPerOctave: 53, harmonic: 432/440).play;
e[\freq]  // 433.414, well below 440

// calculate harmonic to adjust for 53ET
// the (2 ** ...) bit comes to 441.4409617292
// this is the nearest approximation to A in 53ET, using middle C as the reference
h = 432 / (2 ** (40/53) * 60.midicps);

e = (note: 40, stepsPerOctave: 53, harmonic: h).play;
e[\freq]  // 432.0

hjh

1 Like

thanx guys ! I can do already a lot with these suggestions !

1 Like