MUMT 616: Inharmonicity

Inharmonicity in the context of plucked strings.

Abstract

During the course MUMT 616: Timbre as a Form-Bearing Dimension in Music, I talked about inharmonicity in the context of plucked strings.

The slides are available here.

Five examples with varying degrees of inharmonicity are discussed. The examples are qualitatively classified as:

The musical examples were generated from Manuel María Ponce’s Valse for Solo Guitar.

The inharmonicity was computed for each partial using the following formula:

$$ f_n = nf_0 \sqrt{1 + Bn^2} $$

where $f_n$ is the frequency of a given partial, and the $B$ parameter controls the inharmonicity.

The SuperCollider programming language was used to generate the audio examples with varying inharmonicity.

The code is listed here for reference.

Examples

No inharmonicity

No inharmonicity
No inharmonicity

Low inharmonicity

Low inharmonicity
Low inharmonicity

Mid inharmonicity

Mid inharmonicity
Mid inharmonicity

High inharmonicity

High inharmonicity
High inharmonicity

Extreme inharmonicity

Extreme inharmonicity
Extreme inharmonicity

SuperCollider code for generating the audio samples

(
SynthDef(\inh, { |out=0, freq=440, amp=0.5, gate=1, c3=20, pan=0,fB = 180|
    var env = Env.new([0,1, 1, 0],[0.001,0.006, 0.0005],[5,-5, -8]);
    var inp = amp * LFClipNoise.ar(2000) * EnvGen.ar(env,gate);
	var son = DWGPluckedStiff.ar(freq, amp, gate,0.1,1,c3,inp,1,MouseX.kr(0,200));
    DetectSilence.ar(son, 0.001, doneAction:2);
    Out.ar(out, Pan2.ar(son * 0.1, pan));
}).add;
)

(
SynthDef(\har, { |out=0, freq=440, amp=0.5, gate=1, c3=20, pan=0|
    var env = Env.new([0,1, 1, 0],[0.001,0.006, 0.0005],[5,-5, -8]);
    var inp = amp * LFClipNoise.ar(2000) * EnvGen.ar(env,gate);
    var son = DWGPlucked.ar(freq, amp, gate,0.1,1,c3,inp,1);
    DetectSilence.ar(son, 0.001, doneAction:2);
    Out.ar(out, Pan2.ar(son * 0.1, pan));
}).add;
)


(
SynthDef(\noinh,
	{
		|out=0, freq=440, amp=0.4, fB=0| //partials = 4
		// Number of partials cannot change dynamically in the SynthDef :(
		var sig, env, partials = 16;
		// Need an envelope, otherwise the sinewaves play forever
		env = Env.linen(0.03, 0.5, 0.15, amp);
		// Summing the sinewaves
		sig = Mix.fill(partials,
			{
				arg i;
				// Need a 1-based-index for the partials
				var n = i+1, harmonic, partial, ampdecay;
				harmonic = n*freq;
				partial = harmonic * sqrt(1 + (fB* n**2));
				ampdecay = 1/n;
				SinOsc.ar(partial, 0, ampdecay * EnvGen.kr(env,doneAction:2));
			}
		);
		Out.ar(out, Pan2.ar(sig));
}).add;
)

(
SynthDef(\sineSynth,
	{
		|out=0, freq=440, amp=0.4|
		var sig;
		sig = SinOsc.ar(freq, 0, amp);
		Out.ar(out, Pan2.ar(sig));
}).add;
)




(
SynthDef(\lowinh,
	{
		|out=0, freq=440, amp=0.4, fB=0.005| //partials = 4
		// Number of partials cannot change dynamically in the SynthDef :(
		var sig, env, partials = 20;
		// Need an envelope, otherwise the sinewaves play forever
		env = Env.linen(0.03, 0.4, 0.15, amp);
		// Summing the sinewaves
		sig = Mix.fill(partials,
			{
				arg i;
				// Need a 1-based-index for the partials
				var n = i+1, harmonic, partial, ampdecay;
				harmonic = n*freq;
				partial = harmonic * sqrt(1 + (fB* n**2));
				ampdecay = 1/n;
				SinOsc.ar(partial, 0, ampdecay * EnvGen.kr(env,doneAction:2));
			}
		);
		Out.ar(out, Pan2.ar(sig));
}).add;
)

(
SynthDef(\midinh,
	{
		|out=0, freq=440, amp=0.4, fB=0.015| //partials = 4
		// Number of partials cannot change dynamically in the SynthDef :(
		var sig, env, partials = 20;
		// Need an envelope, otherwise the sinewaves play forever
		env = Env.linen(0.03, 0.4, 0.15, amp);
		// Summing the sinewaves
		sig = Mix.fill(partials,
			{
				arg i;
				// Need a 1-based-index for the partials
				var n = i+1, harmonic, partial, ampdecay;
				harmonic = n*freq;
				partial = harmonic * sqrt(1 + (fB* n**2));
				ampdecay = 1/n;
				SinOsc.ar(partial, 0, ampdecay * EnvGen.kr(env,doneAction:2));
			}
		);
		Out.ar(out, Pan2.ar(sig));
}).add;
)

(
SynthDef(\highinh,
	{
		|out=0, freq=440, amp=0.4, fB=0.0874| //partials = 4
		// Number of partials cannot change dynamically in the SynthDef :(
		var sig, env, partials = 20;
		// Need an envelope, otherwise the sinewaves play forever
		env = Env.linen(0.03, 0.4, 0.15, amp);
		// Summing the sinewaves
		sig = Mix.fill(partials,
			{
				arg i;
				// Need a 1-based-index for the partials
				var n = i+1, harmonic, partial, ampdecay;
				harmonic = n*freq;
				partial = harmonic * sqrt(1 + (fB* n**2));
				ampdecay = 1/n;
				SinOsc.ar(partial, 0, ampdecay * EnvGen.kr(env,doneAction:2));
			}
		);
		Out.ar(out, Pan2.ar(sig));
}).add;
)

(
SynthDef(\crazyinh,
	{
		|out=0, freq=440, amp=0.4, fB=1| //partials = 4
		// Number of partials cannot change dynamically in the SynthDef :(
		var sig, env, partials = 20;
		// Need an envelope, otherwise the sinewaves play forever
		env = Env.linen(0.03, 0.4, 0.15, amp);
		// Summing the sinewaves
		sig = Mix.fill(partials,
			{
				arg i;
				// Need a 1-based-index for the partials
				var n = i+1, harmonic, partial, ampdecay;
				harmonic = n*freq;
				partial = harmonic * sqrt(1 + (fB* n**2));
				ampdecay = 1/n;
				SinOsc.ar(partial, 0, ampdecay * EnvGen.kr(env,doneAction:2));
			}
		);
		Out.ar(out, Pan2.ar(sig));
}).add;
)

(
m = SimpleMIDIFile.read("/Stimulus 1 major.mid");
m.p(\noinh).play;
)

(
m = SimpleMIDIFile.read("/op28n20.mid");
m.p(\lowinh).play;
)

(
m = SimpleMIDIFile.read("/op28n20.mid");
m.p(\lowinh).play;
)

(
m = SimpleMIDIFile.read("/op28n20.mid");
m.p(\lowinh).play;
)

(
Routine.run {
	var s, m, synth, release;
	s = Server.default;
	s.sync;
    s.record(path: "~/out.wav".standardizePath);

	release = 0.3;
	m = SimpleMIDIFile.read("/Stimulus 1 major.mid");
	m.p(\lowinh).play;
	3.wait;

	// Wait for the Synth to release before stopping the recording.
	release.wait;
	s.stopRecording;
    };
)
s.stopRecording;

(
    Routine.run {
        var s, synth, release;
        s = Server.default;

        s.sync;

        s.record(path: "~/out.wav".standardizePath);

        release = 0.3;
        synth = Synth(\noinh, [freq: 30.midicps]);
        2.wait;
        synth.set(0);

        // Wait for the Synth to release before stopping the recording.
        release.wait;
        s.stopRecording;
    };
)


(
x = Synth(\sineSynth);
f = {
	arg m;
	x.set("freq", m.midicps);
	m.postln;
};
m = SimpleMIDIFile.read("/Stimulus 1 major.mid");
//x = Synth(\sineSynth);
m.playNotesWithFunction(f)
)
Previous
Next