Coder Social home page Coder Social logo

Bar and beat about learn HOT 8 OPEN

supercollider avatar supercollider commented on June 29, 2024
Bar and beat

from learn.

Comments (8)

cianoc avatar cianoc commented on June 29, 2024

Thank you, that's good to hear.

I do plan to add more stuff to this later in the tutorial, but I'm curious as to what you mean by bar and beat. Something I do plan to add is a bit on how you can write parameters that are dependent upon the beat, or bar. But I'm guessing that you're looking for something a little bit different.

If you want to clarify what you're looking for (and the scsynth.org forum might be a better place), that would help me a lot. Thanks :)

from learn.

prko avatar prko commented on June 29, 2024

To show what I mean, here are two examples:

  • Example 1: the current status of my research on recursive playback of music written according to the bar structure of the piece with multiple voices. The music is the beginning of a Korean popular song.
  • Example 2: a previous version with the melody "twinkle, twinkle, little star".

I think the method of example 2 is not so good as example 1. Example 1 must be rewritten with patterns.

You need the following sample:
https://freewavesamples.com/alesis-fusion-nylon-string-guitar-c4

I am not sure if it is good to post these examples in the scsynth.org because they are too long. If you think I should post all two examples or one of them in the scsynth.org, I will post it or them there. I think the example 1 should also be rewritten with the piece "twinkle, twinkle, little star".

  • Example 1:
(
fork{
	var baseFolder, snd, gtrSmpl, aLetter_kjKim, player, reverb;

	s.freeAll;

	baseFolder = thisProcess.nowExecutingPath.dirname;
	snd = "Alesis-Fusion-Nylon-String-Guitar-C4.wav";
	gtrSmpl = Buffer.read(s, baseFolder+/+snd);

	s.sync;

	SynthDef(\gtr5, {
		|ptch=60, mul=0.25, ads=0.5, ade=0.25, rls=0.05, gate=1, vfs=4, vfe=5, vds=0.25, vde=0.25, len=1|
		var smplPtch, bRate, vShp, vDpth, rate, sig, env, envGen, vAmp;
		smplPtch = 60;
		bRate = 2 ** (ptch - smplPtch / 12);
		vShp = {|phs| SinOsc.kr(XLine.kr(vfs + 1, vfe + 1, len) - 1, phs)};
		vAmp = vShp.(pi/2).range(XLine.kr(ads + 1, ade + 1, len) - 1, 1);
		vDpth = vShp.(3pi/2).range(1, 2 ** (XLine.kr(vds + 1, vde + 1, len) - 1 / 12));
		rate = bRate * vDpth;
		env = Env.asr(0.01, 1, rls);
		envGen = EnvGen.kr(env, gate, doneAction:2);
		sig = PlayBuf.ar(gtrSmpl.numChannels, gtrSmpl, rate);
		sig = sig * envGen * mul * vAmp * [-1, 1].choose;
		OffsetOut.ar(0, sig)
	}
	).add;

	SynthDef(\melody, {
		|ptch=60, mul=0.25, ads=0.5, ade=0.25, rls=0.05, gate=1, vfs=4, vfe=5, vds=0.25, vde=0.25, len=1|
		var vShp, vDpth, sig, env, envGen, vAmp;
		vShp = {|phs| SinOsc.kr(XLine.kr(vfs + 1, vfe + 1, len) - 1, phs)};
		vAmp = vShp.(pi/2).range(XLine.kr(ads + 1, ade + 1, len) - 1, 1);
		vDpth = vShp.(3pi/2).range(1, 2**(XLine.kr(vds + 1, vde + 1, len) - 1 / 12));
		env = Env.adsr(0.12, 0.3, 0.6, rls + 0.05, 1, 4);
		envGen = EnvGen.kr(env, gate, doneAction:2);
		sig = LFTri.ar([1, 1.013]*ptch.midicps * vDpth);
		sig = sig * envGen * mul * vAmp * [-1, 1].choose;
		OffsetOut.ar(0, sig)
	}
	).add;

	SynthDef(\reverb2Ch, {
		|oCh, mix = 0.25, room = 0.15, damp = 0.5, amp = 1.0|
		var signal;
		signal = In.ar(oCh, 2);
		ReplaceOut.ar(oCh,
			FreeVerb2.ar( // FreeVerb2 - true stereo UGen
				signal[0], // Left channel
				signal[1], // Right Channel
				mix, room, damp, amp
			)
		); // same params as FreeVerb 1 chn version
	}).add;

	s.sync;

	aLetter_kjKim = [
		[ // 1st bar
			[ // voice 1
				[[69,60],65,8], // entry: [aChord, velocity, length.reciprocal]
				[[70,62],60,8],
				[[70,62],65,8],
				[[69,60],60,8],
				[[69,60],57,2]
			],
			[ // voice 2
				[53,55,1] // entry: [aNote, velocity, length.reciprocal]
			]
		],
		[ // 2nd bar
			[ // voice 1
				[67,62,8],
				[69,60,8],
				[69,65,8],
				[67,61,8],
				[67,58,2]
			],
			[ // voice 2
				[62,40,4],
				[59,35,4],
				[61,40,2]
			],
			[ // voice 3
				[52,50,2],
				[45,45,2]
			]
		],
		[ // 3rd bar
			([
				[65,50,8],
				[67,47,8],
				[67,48,8],
				[65,52,8]
			]!2).flatten,
			[
				[57,48,4],
				[62,43,4],
				[63,0,8],
				[63,53,8],
				[61,48,4]
			],
			[
				[50,47,2],
				[49,45,2]
			]
		],
		[ // 4th bar
			[
				[[65,60,58],50,2],
				[[64,60,55],45,2]
			],
			[
				[48,50,1]
			]
		]
	];

	player = {
		|music, synth, tempo=60, nthBar=0, vol=1|
		var tF, entries, voiceItems, maxItemVoice, lastVoice;
		tF = 60 / tempo * 4;
		entries = music[nthBar];
		voiceItems = entries.size.collect{
			|nth|
			entries[nth].size.collect{
				|ith|
				entries[nth][ith][2].reciprocal
			}
		};
		maxItemVoice = voiceItems.size.collect{
			|nth|
			var items, range;
			items = voiceItems[nth];
			range = (0..items.size - 2);
			(items.size == 1).if{ 0 }{ items[range].sum }
		};
		maxItemVoice.postln;
		lastVoice = maxItemVoice.maxIndex;
		("Bar"+nthBar++"\nThe voice which will be played lastly:" + lastVoice).postln;
		{
			|vce|
			fork{
				("\t\t\t\t\t\t\tVoice"+vce+"numItems:" + entries[vce].size

				).postln;
				("\t\t\t\t\t\t\t"++entries[vce]).postln;
				entries[vce].do{
					|entry,idxEntry|
					var aChord, entryPlayer, len, untilNext, rAmp, rRls;
					aChord = entry[0].asArray;
					entryPlayer = Array.newClear(10);
					len = entry[2];
					untilNext = len.reciprocal;
					rAmp = -0.1.rand;
					rRls = rrand(0.01, 0.03);
					aChord.size.do{
						|i|
						var aNote, amp;
						aNote = aChord[i];
						amp = entry[1]/127 * (2**(-3 - (i - 1.0.rand) + rAmp));
						s.makeBundle(
							0.2,
							{
								entryPlayer[i] = Synth(
									synth,
									[
										\ptch, aNote,
										\mul, amp * vol,
										\ads, 0.9,
										\ade, 0.85,
										\rls, rRls,
										\gate, 1,
										\vfs, 3,
										\vfe, 4,
										\vds, 2 ** -4,
										\vde, 2 ** -5,
										\len, 1
									],
									1,
									0) });
						(
							[
								"voice:" + vce,
								"MIDI note:" + aNote,
								"rhythm:" + untilNext.asString.padRight(8, "0"),
								"dbFS:" + amp.ampdb.round(0.01).asString.padRight(6, "0")+"dB"
							]
						).postln;
						rrand(256, 384).reciprocal.wait;
					};

					( tF * untilNext + (128.reciprocal.rand2) - rRls).wait;
					aChord.size.do{
						|i|
						entryPlayer[i].release
					};
					rRls.wait;

					if (
						(nthBar != (music.size - 1))
						&&
						vce == lastVoice
						&&
						(idxEntry == (entries[vce].size - 1))
					)
					{
						nthBar = nthBar+1;
						player.(music, synth, tempo, nthBar, vol);
					}
				}
			};
		}!entries.size;
	};

	// start the reverb
	reverb = Synth(\reverb2Ch,
		[
			\oCh, 0,
			\mix, 0.7,
			\room, 0.5,
			\damp, 0.6,
			\amp, 1
		],
		addAction:\addToTail
	);

	// play music
	player.(aLetter_kjKim ++ aLetter_kjKim, \gtr5, 75, 0, 1);
	player.(
		(aLetter_kjKim * [[[[[1],0,1]]]] ++ aLetter_kjKim).collect{
			|item|
			[
				item[0].collect{
					|itm|
					[if(itm[0].isArray){ itm[0][0] }{ itm[0] }, itm[1], itm[2]]
				}
			]
			+ [[[[-12],0,0]]]
		},
		\melody,
		75,
		0,
		0.4);
}
)
  • Example 2:
(
// score[nth bar][nth voice][nth note information][pitch, velocity, length to next note]
~twinkle_a=
[
	[ // bar 1, 17
		[ // voice 1
			[72,64,4], [72,64,4] // [pitch, velocity, length to next note]
		],
		[ // voice 2
			[48,52,4],[60,52,4]
		]
	],
	[ // bar 2, 18
		[
			[79,64,4], [79,64,4]
		],
		[
			[64,52,4],[60,52,4]
		]
	],
	[ // bar 3, 19
		[81,64,4].dup(2),
		[
			[65,52,4],[60,52,4]
		]
	],
	[ // bar 4, 20
		[
			[79,58,2]
		],
		[
			[64,46,4],[60,38,4]
		]
	],
	[ // bar 5, 21
		[77,64,4]!2,
		[
			[62,52,4],[59,52,4]
		]
	],
	[ // bar 6, 22
		[76,64,4]!2,
		[
			[60,52,4],[52,52,4]
		]
	],
	[ // bar 7, 23
		[74,64,4]!2,
		[
			[53,52,4],[55,52,4]
		]
	],
	[ // bar 8, 24
		[
			[72,64,2]
		],
		[
			[48,52,2]
		]
	]
];

~twinkle_b=
[
	[ // bar 9, 13
		[79,48,4]!2,
		[ // voice 2
			[64,48,4],[55,48,4]
		]
	],
	[ // bar 10, 14
		[77,48,4]!2,
		[
			[62,48,4],[55,48,4]
		]
	],
	[ // bar 11, 15
		[76,64,4].dup(2),
		[
			[60,48,4],[55,48,4]
		]
	],
	[ // bar 12, 16
		[
			[74,48,2]
		],
		[
			[59,48,4],[55,48,4]
		]
	]
];

~twinkle=~twinkle_a++(~twinkle_b!2).flatten(1)++~twinkle_a;
)

/* bus */

(
SynthDef(\reverb, {
	arg oCh, iCh, rs=100, rt=2.5, mul=0.5;
	var sig= GVerb.ar(In.ar(iCh), rs, rt, mul:mul);
	Out.ar(oCh, sig)
}
).add
)

~gtrC4m= Buffer.readChannel(s, "Alesis-Fusion-Nylon-String-Guitar-C4.wav".resolveRelative, channels:0);

(
SynthDef(\gtrM, {
	arg len=1, oCh=0, pit=60, vSpd=3.5, vDepth=0.3, mul=1;
	var env, atk=0.01, rls=0.05, rate, fm, am, sig;
	env=Env([0,1,1,0],[atk,len-atk-rls,rls]).kr(doneAction:2);
	fm= SinOsc.kr(vSpd,1.5pi).range(1, 2**(vDepth/12));
	rate= 2**(pit-60/12) * BufRateScale.kr(~gtrC4m.bufnum) * fm;
	am= SinOsc.kr(vSpd, 0.5pi).range(0.5.sqrt, 1);
	sig= PlayBuf.ar(~gtrC4m.numChannels, ~gtrC4m.bufnum, rate);
	sig= sig * am * env * mul;
	Out.ar(oCh, sig)
}
).add
)

(
~gtrM={
	arg score, voice=0, temp=2, offset=0, leg=1;
	fork{
		score.do{
			arg barItms, barIdx;
			barItms[voice].do{
				arg item, idx;
				var wait, len, notes, mul, phr;
				if (idx==0 && voice==0) {barIdx.postln};
				phr= if ((barIdx/2).asInteger.even==3) {idx} {barItms.size-idx} - barItms.size;
				wait= 2**(phr/20) * temp * item[2].reciprocal;
				len= wait * leg;
				notes= item[0].asArray;
				mul= exprand(2**2.5.neg, 2**1.neg) * (item[1]/127).sqrt;
				[voice, idx, item].postln;
				notes.size.do{
					arg i;
					var deTune, phrMul;
					deTune= rrand( -0.02, 0.02);
					phrMul= 2**(phr/3);
					Synth.before(
						~reverb,
						\gtrM,
						[
							oCh:~bus_reverb,
							pit:notes[i]+deTune+offset,
							len:len,
							mul:mul*(2**(1/(i+1)).neg).sqrt * phrMul,
							vSpd:2,
							vDepth:0.2
						]
					);
					(rrand(1/256, 1/128)).wait
				};
				( wait + rrand(-1/256, 1/256) ).wait
			}
		}
	}
}
)

~bus_reverb= Bus.audio(s, 1);

~reverb= Synth(\reverb, [iCh:~bus_reverb, oCh:0]);

(
~gtrM.(score:~twinkle, voice:0, leg:1);
~gtrM.(score:~twinkle, voice:1, leg:0.4)
)

~reverb.set(\rs, 10, \rt,1.15, \mul,2)

from learn.

cianoc avatar cianoc commented on June 29, 2024

I probably won't do this, no, though I may augment the melodic stuff a little (for example showing how you can specify the notes and duration together using nested arrays). I will also show a way to use environments so that you can use note names, rather than numbers (e.g. \cs4 for C sharp 4) - though that will probably go into the cookbook. I'm also going to talk about importing midi files, and using those with patterns.

If you want to discuss this further though, the SCcode forum is the place to do it. Other people may have views, and I would like to discuss this more generally. I think it's a shame that there isn't an easy way to do melodies in SuperCollider, though this looks pretty promising:
https://github.com/shimpe/panola

You don't get the bar lines, but there may be other ways to achieve that (e.g. using the current time in a pbind).

from learn.

prko avatar prko commented on June 29, 2024

Thank you for your precious opinion!

In February, 2018, I posted it in the mailing list, but nobody gave me any feedback:
https://www.listarc.bham.ac.uk/lists/sc-users/msg59085.html

I am a bit confused with the term SCcode forum. Do you mean scsynth.org, sccode.org or the mailing list?

I probably make code simpler with Pbind, then should post it. What do you think about it?

I do not use bar lines as an element of arrays. However, I can easily accentuate the first note or chord of each bar with altering velocity or altering duration in Example 1 because the playback firstly detects the size of the array of a bar then plays each element then go to next bar if the all notes in the current bar are played. In Example 1, I also make a rubato, accelerando, ritardando, crescendo and decrescendo within a bar. By using a global variable, I can do such things for some bars in Example 1.

I am not sure if pitch name is good because pitch names are diverse according to lands: In Germany, they use the Helmholtz-system; in the US, they use American Standard Pitch Notation (ASPN); In France, the octave number is lower than ASPN. Yamaha follows the French system, and Rolland follows the American system. Most software programmes provide an option to choose middle C as C3 or C4. Thus, I think that fixing middle C as C4 would be not good.

Anyway, Panola is cool! Is it your Quarks?

from learn.

cianoc avatar cianoc commented on June 29, 2024

Sorry I meant scsynth.org

There is a way to detect which beat of a bar you're in from within a pattern, and I plan to show how you can use that to create more realistic playback (it's a trick I use quite a bit). You can also do rubato/crescendo etc using patterns relatively easily - perhaps I should also show how to do that so it relates to bars/beats as well.

As far as notation goes - this is for an example, so the user can change it if they want. However, it is far easier to support ASPN in SuperCollider, than any of the others:

\C0;   \\ No problems
\C-1; \\ Not going to work.

Panola isn't mine - but I plan to use it.

from learn.

prko avatar prko commented on June 29, 2024

I expect to read your method in the tutorial!
I understand now ASPN is simpler in SC, but the system of the pitch names should be explained in the tutorial.

Twinkle ... is too simple, and the Korean song is good enough to discuss on notation method, but it is not well-known.
I will search for another short and well-known example for the post in scsynth.org.

Thank you a lot!

from learn.

prko avatar prko commented on June 29, 2024

Is the first part of the following piece interesting enough for a transcription example?
https://www.youtube.com/watch?v=ffZnrJpQmZY
the number of voice is fixed but mixed with rests.
There is a note exceeds a bar.

from learn.

cianoc avatar cianoc commented on June 29, 2024

Ha, I remember learning that piece for piano.

Yes, that's pretty good. Multiple voices, a tied note, rests, repeats. Post it on the forum and see what people make of it.

from learn.

Related Issues (5)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.