Tutorial Sketches - Explanations » History » Version 33

Robert Jack, 2015-07-17 09:55 PM

1 1 Astrid Bin
h1.  Tutorial Sketches - Explanations 
2 1 Astrid Bin
3 2 Astrid Bin
Find the tutorial sketches in Respository > Projects, or click this link: https://code.soundsoftware.ac.uk/projects/beaglert/repository/show/projects
4 1 Astrid Bin
5 1 Astrid Bin
Below is a list of the sample sketches, and what they do.
6 1 Astrid Bin
7 3 Astrid Bin
h2. Basic sketch structure
8 3 Astrid Bin
9 3 Astrid Bin
A collection of BeagleRT files are called a "project".
10 3 Astrid Bin
11 3 Astrid Bin
h3. The structure of a BeagleRT project
12 3 Astrid Bin
13 3 Astrid Bin
If you open a project folder in the above repository, you'll see that each of these BeagleRT project contains two files: main.cpp and render.cpp (some projects have additional files, but every project has at least these two). The main.cpp file you don't really have to worry about; it contains helper functions and things that run command line arguments. Most work is done in the render.cpp file.
14 3 Astrid Bin
15 3 Astrid Bin
h3. The structure of a render.cpp file
16 3 Astrid Bin
17 28 Andrew McPherson
A render.cpp file has three functions: @setup()@, @render()@ and @cleanup()@.
18 3 Astrid Bin
19 28 Andrew McPherson
@setup()@ is a function that runs at the beginning and is called once when the project starts.
20 3 Astrid Bin
21 28 Andrew McPherson
@render()@ is a function that is regularly called, over and over continuously, at the highest priority by the audio engine. 
22 3 Astrid Bin
23 28 Andrew McPherson
@cleanup()@ is a function that is called when the program stops, to finish up any processes that might still be running.
24 3 Astrid Bin
25 3 Astrid Bin
Here we will briefly explain each function and the structure of the render.cpp document
26 3 Astrid Bin
27 3 Astrid Bin
h3. Before any functions
28 3 Astrid Bin
29 3 Astrid Bin
At the top of the file, include any libraries you might need.
30 3 Astrid Bin
31 29 Andrew McPherson
Additionally, declare any global variables. In these tutorial sketches, all global variables are preceded by a @g@ so we always know which variables are global - @gSampleData@, for instance. It's not mandatory but is a really good way of keeping track of what's global and what isn't.
32 3 Astrid Bin
33 29 Andrew McPherson
Sometimes it's necessary to access a variable from another file, such as main.cpp. In this case, precede this variable with the keyword @extern@.
34 3 Astrid Bin
35 3 Astrid Bin
h3. Function arguments
36 3 Astrid Bin
37 29 Andrew McPherson
@setup()@, @render()@ and @cleanup()@ each take the same arguments. These are:
38 3 Astrid Bin
39 29 Andrew McPherson
@BeagleRTContext *context
40 3 Astrid Bin
void *userData
41 29 Andrew McPherson
@
42 30 Andrew McPherson
These arguments are pointers to data structures. The main one that's used is @context@, which is a pointer to a data structure containing lots of information you need. 
43 3 Astrid Bin
44 25 Robert Jack
Take a look at what's in the data structure here: https://code.soundsoftware.ac.uk/projects/beaglert/embedded/structBeagleRTContext.html
45 3 Astrid Bin
46 30 Andrew McPherson
You can access any of these bits of information about current audio and sensor settings and pointers to data buffers that are contained in the data structure like this: @context->name_of_item@
47 3 Astrid Bin
48 30 Andrew McPherson
For example, @context->audioChannels@ returns the number of audio channels. @context->audioSampleRate@ returns the audio sample rate. @context->audioIn[n]@ would give you the current input sample (assuming that your input is mono - if it's not you will have to account for multiple channels). 
49 3 Astrid Bin
50 30 Andrew McPherson
Note that @audioIn@, @audioOut@, @analogIn@, @analogOut@ are arrays (buffers).
51 3 Astrid Bin
52 1 Astrid Bin
h2. analogDigitalDemo
53 1 Astrid Bin
54 1 Astrid Bin
h2. audio_in_FFT
55 1 Astrid Bin
56 5 Astrid Bin
This sketch performs an FFT (Fast Fourier Transform) on incoming audio. It uses the NE10 library, included at the top of the file (line 11).
57 5 Astrid Bin
58 5 Astrid Bin
Read the documentation on the NE10 library here: http://projectne10.github.io/Ne10/doc/annotated.html
59 5 Astrid Bin
60 31 Andrew McPherson
The variables @timeDomainIn@, @timeDomainOut@ and @frequencyDomain@ are variables of the struct @ne10_fft_cpx_float32_t@ (http://projectne10.github.io/Ne10/doc/structne10__fft__cpx__float32__t.html). These are declared at the top of the file (line 21), and memory is allocated for them in @setup()@ (line 41).
61 6 Astrid Bin
62 31 Andrew McPherson
In @render()@ a @for@ loop performs the FFT is performed on each sample, and the resulting output is placed on each channel.
63 5 Astrid Bin
64 1 Astrid Bin
h2. basic
65 1 Astrid Bin
66 27 Robert Jack
This sketch, better known as bleep, produces a sine tone.
67 7 Astrid Bin
68 32 Robert Jack
The frequency of the sine tone is determined in a global variable, @gFrequency@ (line 12). This is produced by incrementing the phase of a sin function on every audio frame.
69 18 Robert Jack
70 18 Robert Jack
The important thing to notice is the nested for loop structure. You will see this in all BeagleRT projects and in most digital audio applications. The first for loop cycles through the audio frames, the second through each of the audio channels (in this case left 0 and right 1). It is good to familiarise yourself with this structure as it is fundamental to producing sound with the system.
71 7 Astrid Bin
72 1 Astrid Bin
h2. basic_analog_input
73 1 Astrid Bin
74 27 Robert Jack
This sketch produces a sine tone, the frequency and amplitude of which are affected by data received on the analog pins. Before looping through each audio frame, we declare a value for the frequency and amplitude of our sine tone (line 55); we adjust these values by taking in data from analog sensors (for example, a potentiometer).
75 8 Astrid Bin
76 8 Astrid Bin
The important thing to notice is that audio is sampled twice as often as analog data. The audio sampling rate is 44.1kHz (44100 frames per second) and the analog sampling rate is 22.05kHz (22050 frames per second). On line 62 you might notice that we are processing the analog data and updating frequency and amplitude only on every *second* audio sample, since the analog sampling rate is half that of the audio.
77 8 Astrid Bin
78 32 Robert Jack
Note that the pin numbers are stored in the variables @gAnalogInputFrequency@ and @gAnalogInputAmplitude@. These are declared in the main.cpp file; if you look in that file you will see that they have the values of 0 and 1. Bear in mind that these are analog input pins which is a specific header!
79 9 Astrid Bin
80 1 Astrid Bin
h2. basic_analog_output
81 1 Astrid Bin
82 27 Robert Jack
This sketch uses a sine wave to drive the brightness of a series of LEDs connected to the eight analog out pins. Again you can see the nested for loop structure but this time for the analog output channels rather than the audio.
83 10 Robert Jack
84 19 Robert Jack
Within the first for loop in render we cycle through each frame in the analog output matrix. At each frame we then cycle through the analog output channels with another for loop and set the output voltage according to the phase of a sine tone that acts as an LFO. The analog output pins can provide a voltage of ~4.092V.
85 10 Robert Jack
86 32 Robert Jack
The output on each pin is set with @analogWriteFrame@ within the for loop that cycles through the analog output channels. This needs to be provided with arguments as follows @analogWriteFrame(context, n, channel, out)@. Channel is where the you give the address of the analog output pin (in this case we cycle through each pin address in the for loop), out is the variable that holds the desired output (in this case set by the sine wave).
87 10 Robert Jack
88 19 Robert Jack
Notice that the phase of the brightness cycle for each led is different. This is achieved by updating a variable that stores a relative phase value -- this is advanced by pi/4 (1/8 of a full rotation) for each channel giving each of the eight LEDs a different phase.
89 10 Robert Jack
90 33 Robert Jack
h2. basic_blink
91 33 Robert Jack
92 1 Astrid Bin
h2. basic_network
93 1 Astrid Bin
94 17 Robert Jack
This sketch allows you to send audio and sensor data over UDP to a DAW on the host. The host needs to run Udpioplugin which you can find here https://code.soundsoftware.ac.uk/projects/udpioplugin. Note that this sketch and the accompanying plugin are still in testing.
95 16 Robert Jack
96 1 Astrid Bin
h2. basic_passthru
97 1 Astrid Bin
98 13 Astrid Bin
This sketch demonstrates the simplest possible case: it passes audio input straight to audio output.
99 1 Astrid Bin
100 13 Astrid Bin
Note the nested for loop structure. You will see this in all BeagleRT projects. The first for loop cycles through the audio frames, the second through each of the audio channels (in this case left 0 and right 1). 
101 13 Astrid Bin
102 32 Robert Jack
We write samples to the audio output buffer like this: @context->audioOut[n * context->audioChannels + ch]@ where n is the current audio frame and ch is the current channel, both provided by the nested for loop structure.
103 13 Astrid Bin
104 32 Robert Jack
We can access samples in the audio input buffer like this: @context->audioIn[n * context->audioChannels + ch]@.
105 13 Astrid Bin
106 32 Robert Jack
So a simple audio pass through is achieved by setting output buffer equal to input buffer: @context->audioOut[n * context->audioChannels + ch] = context->audioIn[n * context->audioChannels + ch]@.
107 11 Astrid Bin
108 1 Astrid Bin
h2. cape_test
109 1 Astrid Bin
110 14 Astrid Bin
This sketch is for testing purposes only. Each analog input should be connected to each analog output 0-0, 1-1, etc. The board will then produce either a 880Hz pulse if the every channel is functioning or a 220Hz continuous tone if one of the channels is not working. A message will be printed to the terminal window that details the particular channel that is not working.
111 14 Astrid Bin
112 1 Astrid Bin
h2. d-box
113 1 Astrid Bin
114 15 Astrid Bin
These files are from the d-box hackable musical instrument. See https://code.soundsoftware.ac.uk/publications/128?project_id=beaglert for more information.
115 15 Astrid Bin
116 1 Astrid Bin
h2. filter_FIR
117 1 Astrid Bin
118 20 Robert Jack
This sketch implements a finite impulse response filter.
119 20 Robert Jack
120 1 Astrid Bin
h2. filter_IIR
121 1 Astrid Bin
122 20 Robert Jack
This sketch implements a infinite impulse response filter.
123 20 Robert Jack
124 23 Robert Jack
h2. oscillator_bank
125 1 Astrid Bin
126 27 Robert Jack
These files demonstrate an oscillator bank implemented in assembly code that is used as part of the d-box project.
127 20 Robert Jack
128 1 Astrid Bin
h2. samples
129 20 Robert Jack
130 22 Robert Jack
This sketch shows how to playback audio samples from a buffer.
131 20 Robert Jack
132 32 Robert Jack
An audio file is loaded into a buffer @SampleData@ as @gSampleData@. This is accessed with a read pointer that is incremented at audio rate within the render function: @out += gSampleData.samples[gReadPtr++]@.
133 20 Robert Jack
134 32 Robert Jack
Note that the read pointer is stopped from incrementing past the length of the @gSampleData@. This is achieved by comparing the read pointer value against the sample length which we can access as follows: @if(gReadPtr >= gSampleData.sampleLen)@
135 20 Robert Jack
136 32 Robert Jack
The sample is triggered by keyboard input: (a) starts sample playback, (s) stops sample playback. The triggering is treated as a lower priority task to the audio. You can see this at the bottom of the render function: @BeagleRT_scheduleAuxiliaryTask(gTriggerSamplesTask)@;
137 1 Astrid Bin
138 1 Astrid Bin
h2. tank_wars
139 21 Robert Jack
140 22 Robert Jack
This sketch uses the analog outputs to draw a tank wars game using vector graphics. Best viewed on an analog oscilloscope.