GeoMaestro

-- Back to the tutorials index--

Tutorial 11: sound synthesis with GeoMaestro




Instead of projecting notes in a composition, why not projecting peak data in a raw audio wave ? This way we could use GeoMaestro as a synthesizer... let's try it.

In the process, we will deal with events with scripts, a topic not very much documented. The next chapter is thus dedicated to this subject.



Scripts and local time


Here is the idea: if the "script" field of an event is defined and not an empty string, the call
efunction(Ev[ch][ne]["script"])(ch,ne,side,dist,tht,t)
... is performed whenever the event Ev[ch][ne] is projected, before any other calculation relative to this event.

So we can use "empty" events, without musical content such as MIDI phrase or Csound score, to simply trigger an arbitrary function and pass it the parameters dist, side, tht (which define the geometry of the projection) and t.

This last parameter, t, is a bit tricky. It is the local time of the projection, expressed in clicks. You should know by now that any projector is eventually a combination of Ecoute() et EcouteC() calls. The argument t0 marks the beginning of the Ecoute/EcouteC projector local time for this call.


Let's see on an example: we create a projector that do the following:



... given points A and B, it projects the scene on segment AB, then on circle C (starting at A), then on segment BA

Here is its code (see here if it's not crystal clear to you):

 
function SegPlusCirPlusSeg(a, b, ...)	
{
	duree = OptArgs(...)["duree"]
	t0 = OptArgs(...)["t0"]
	region = OptArgs(...)["region"]	
	df = OptArgs(...)["df"]

	c = Cerc(Milieu(a,b),0.5*Dist(a,b))

	nl = Ecoute(a, b, duree, t0, region, df)
	nl = AddLignes(nl, EcouteC(c, a, 1, duree, 0, region, df))
	nl = AddLignes(nl, Ecoute(b, a, duree, 0, region, df))

	return(nl)
}


Now here is another way to code it:

 
function SegPlusCirPlusSeg(a, b, ...)
{
	duree = OptArgs(...)["duree"]
	t0 = OptArgs(...)["t0"]
	region = OptArgs(...)["region"]	
	df = OptArgs(...)["df"]

	c = Cerc(Milieu(a,b),0.5*Dist(a,b))

	nl = Ecoute(a, b, duree, t0, region, df)
	nl = MergeLignes(nl, EcouteC(c, a, 1, duree, nl[1], region, df))
	nl = MergeLignes(nl, Ecoute(b, a, duree, nl[1], region, df))

	return(nl)
}


Given the same arguments, both return exactly the same result. In the first function three lignes are added: note that t0 is set to 0 when we add a ligne (in the AddLignes() call) so that there is no time offset; in the second function, the lignes are merged, but their t0 is adjusted so that their contents actually get added.

What changes is the local time within each inner projector call. In the first case, the local time clock starts at t0 for the first Ecoute(), then it starts at 0 for the two other projections, while in the second case, it starts at 0 for the first one, then keeps its last value and starts there for the second one, then again keeps its current value when the last projection starts.

So we have to keep this in mind when using the parameter t in a script (or in a distortion function): the value of t for a given event will not necessarily be the time value for the projection of that event in the eventual rendered phrase. It all depends on the way the projector has been coded.

However, note that for most of the projectors in the distribution, if not all of them, t IS the time value of the event projection, since MergeLignes() is used preferably to AddLignes() precisely for this reason.



Sound synthesis




(more here later ...)



A few results


loops:

RawDataExample1(100): RawData_1.wav
RawDataExample4(50): RawData_2.wav
RawDataExample8(200): RawData_3.wav
RawDataExample5(100): RawData_4.wav
RawDataExample2(): RawData_5.wav


(more here later ...)






-- Back to the tutorials index--
-- Back --