Audio from Scratch with Go: Frère Jacques

0

In the final post I stopped by asserting we
would possibly well be in a draw to make utilize of GoAudio to generate some easy tunes.
On this post we can essentially build that to the test. Click the video to listen to the consequence 🙂

Brother John / Frère Jacques is a typical nursing rhyme, and moreover undoubtedly one of the vital few things I became taught
to play on the piano as a teen. As such, I idea it’d be fitting to put off a notion at to code this music this time.
The notes for taking part in this are taken from real-piano-classes.com.
The code takes the notes starting within the important thing of C. (Perchance since it’s in Go, I will be able to possess to nonetheless possess started in G. Feel free to swap it).

In the previous posts, we essentially left out the disaster of turning notes into frequencies.
GoAudio works with given frequencies. So we’ll possess to
first put in pressure a capability to expose the notes into frequencies. For this, I came up with a considerably
hackish resolution nonetheless I didn’t know a greater draw varied than hardcoding it.

As we’re making the music using the equal-tempered scale we can calculate the frequencies for every
demonstrate given a reference frequency. I’m using heart C because the reference frequency, which is ready to be
derived from live performance A (A440) in this fashion: middleC = (concertA math.Pow(2, 3/12)) / 2.

To be conscious alongside with how we catch the frequencies for every demonstrate, I imply taking a notion at
wikipedia. The normal notion alternatively is that now we possess
12 semitones in an octave, so for every octave now we possess to generate the 12 semitones essentially based off a
reference frequency. Confusingly alternatively, an octave starts at C and now no longer at A. (it does loop
round) so we in discovering: C D E F G A B. Every time we loop round and in discovering aid to C, we creep up one
octave (meaning greater frequency, thus greater pitch).

Chances are you’ll well doubtless build a query to a desk of all frequencies from C0 (C at octave 0) as a lot as B8 (B at octave 8)
right here.

The code for right here’s a small hacky, so when you are going to need got a greater draw please let me know! 🙂

Here I’m generating in every the fourth and fifth octave, from C4 -> B5. If we print the draw
generated by this code we in discovering (abbreviated)

Additionally demonstrate that I truly possess added WAIT with frequency 0 in there. Here’s a small hacky (and pointless
in Go). I’ve added this so we can possess some more wait time between taking part in varied sections of the music.
Because the default-zero worth of a waft is zero, and since it is possible you’ll well doubtless access a draw safely even when a
secret’s missing, this became now no longer indispensable. We would possibly well right name the draw with the WAIT key even when it
wasn’t inserted and our result would nonetheless be factual.

In case you’re discovering out this, there’s a somewhat factual likelihood you know this. But I vital to specialize in it, as
I trust right here’s a somewhat cold characteristic of Go! But, in this case, I chose to be explicit about the
intend of the WAIT demonstrate.

Alright, so now we possess our notes and our frequencies linked with them. We nonetheless possess to essentially
generate a wave. For this I’ve presented the consolation characteristic “play” which takes about a
parameters and returns a physique:

Here’s moderately linked to the previous about
ADSR, and right as in that post we
will be conscious the ADSR envelope to the signal right here as properly. Leer that ‘play’ takes a LookupOscillator.
In the previous post we’ve construct about a of these for generating sine waves, triangle, sq., etc.

This characteristic tells us, play a demonstrate for a obvious duration (in seconds) with a given oscillator, and
return a slash of frames. This characteristic allowed me to love a flash swap the form of wave, and play
round with the of taking part in varied notes for plenty of timespans.

Getting the ADSR envelope to sound adore I vital to became truthfully the goold feeble draw of trial and mistake. 😅.

Finally now we possess the entire lot prepared to build the music. The below code is completely now no longer somewhat, nonetheless it will get the job performed!
First we generate the notes, then we invent a wave desk of a form that we’d adore. We
proceed this into an Oscillator, after which we open calling the Play characteristic with the notes that we
need.

For consolation I’ve added some variables to without concerns adapt the duration of sections of the music.
Variables, yeah!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
func most fundamental() {
	nm := generateNotes()
	st, err := synth.NewTriangleTable(8*1024, 11)
	if err != nil {
		terror(err)
	}
	osc, err := synth.NewLookupOscillator(sr, st, 0)
	if err != nil {
		terror(err)
	}

	waitdur := .1
	cdecdur := 0.6
	efgdur := 0.6
	gagfecdur := 0.5
	cgcdur := 0.5

	// notes: https://www.real-piano-classes.com/frere-jacques.html
	output := []wave.Physique{}
	// frere jacues
	output = append(output, play(osc, "C5", cdecdur, nm)...)
	output = append(output, play(osc, "D5", cdecdur, nm)...)
	output = append(output, play(osc, "E5", cdecdur, nm)...)
	output = append(output, play(osc, "C5", cdecdur, nm)...)
	output = append(output, play(osc, "C5", cdecdur, nm)...)
	output = append(output, play(osc, "D5", cdecdur, nm)...)
	output = append(output, play(osc, "E5", cdecdur, nm)...)
	output = append(output, play(osc, "C5", cdecdur, nm)...)
	output = append(output, play(osc, "WAIT", waitdur, nm)...)
	// dormez-vous
	output = append(output, play(osc, "E5", efgdur, nm)...)
	output = append(output, play(osc, "F5", efgdur, nm)...)
	output = append(output, play(osc, "G5", efgdur, nm)...)
	output = append(output, play(osc, "WAIT", 0.2, nm)...)
	output = append(output, play(osc, "E5", efgdur, nm)...)
	output = append(output, play(osc, "F5", efgdur, nm)...)
	output = append(output, play(osc, "G5", efgdur, nm)...)
	// sonnez les matines
	output = append(output, play(osc, "G5", gagfecdur, nm)...)
	output = append(output, play(osc, "A5", gagfecdur, nm)...)
	output = append(output, play(osc, "G5", gagfecdur, nm)...)
	output = append(output, play(osc, "F5", gagfecdur, nm)...)
	output = append(output, play(osc, "E5", gagfecdur, nm)...)
	output = append(output, play(osc, "C5", gagfecdur, nm)...)
	output = append(output, play(osc, "WAIT", 0.2, nm)...)
	output = append(output, play(osc, "G5", gagfecdur, nm)...)
	output = append(output, play(osc, "A5", gagfecdur, nm)...)
	output = append(output, play(osc, "G5", gagfecdur, nm)...)
	output = append(output, play(osc, "F5", gagfecdur, nm)...)
	output = append(output, play(osc, "E5", gagfecdur, nm)...)
	output = append(output, play(osc, "C5", gagfecdur, nm)...)
	output = append(output, play(osc, "WAIT", gagfecdur, nm)...)
	// dindindon
	output = append(output, play(osc, "C5", cgcdur, nm)...)
	output = append(output, play(osc, "G5", cgcdur, nm)...)
	output = append(output, play(osc, "C5", cgcdur, nm)...)
	output = append(output, play(osc, "WAIT", 0.1, nm)...)
	output = append(output, play(osc, "C5", cgcdur, nm)...)
	output = append(output, play(osc, "G5", cgcdur, nm)...)
	output = append(output, play(osc, "C5", cgcdur, nm)...)

	wfmt := wave.NewWaveFmt(1, 1, sr, 16, nil)
	wave.WriteFrames(output, wfmt, "frerejacques.wav")
}

In case you liked this and are attempting to know after I write contemporary posts, the handiest technique to preserve up thus far is by following me on
twitter
.

Read More

Leave A Reply

Your email address will not be published.