andrewm@13
|
1 /*
|
robert@269
|
2 ____ _____ _ _
|
robert@269
|
3 | __ )| ____| | / \
|
robert@269
|
4 | _ \| _| | | / _ \
|
robert@269
|
5 | |_) | |___| |___ / ___ \
|
robert@269
|
6 |____/|_____|_____/_/ \_\.io
|
robert@269
|
7
|
robert@269
|
8 */
|
robert@269
|
9
|
robert@269
|
10 /*
|
andrewm@13
|
11 * render.cpp
|
andrewm@13
|
12 *
|
andrewm@13
|
13 * Created on: Oct 24, 2014
|
andrewm@13
|
14 * Author: parallels
|
andrewm@13
|
15 */
|
andrewm@13
|
16
|
robert@269
|
17 /**
|
robert@269
|
18 \example 1_basic_audio_passthrough
|
robert@269
|
19
|
robert@269
|
20 Audio passthrough: input to output
|
robert@269
|
21 -----------------------------------------
|
robert@269
|
22
|
robert@269
|
23 This sketch demonstrates the simplest possible case of using audio: it passes
|
robert@269
|
24 audio input straight to audio output.
|
robert@269
|
25
|
robert@269
|
26 Note the nested `for` loop structure. You will see this in all Bela projects. The
|
robert@269
|
27 first `for` loop cycles through the audio frames, the second through each of the
|
robert@269
|
28 audio channels (in this case left 0 and right 1).
|
robert@269
|
29
|
robert@269
|
30
|
robert@269
|
31 We write samples to the audio output buffer like this:
|
robert@269
|
32 `context->audioOut[n * context->audioChannels + ch]` where `n` is the current audio
|
robert@269
|
33 frame and `ch` is the current channel, both provided by the nested for loop structure.
|
robert@269
|
34
|
robert@269
|
35 We can access samples in the audio input buffer in a similar way, like this:
|
robert@269
|
36 `context->audioIn[n * context->audioChannels + ch]`.
|
robert@269
|
37
|
robert@269
|
38 So a simple audio pass through is achieved by setting output buffer equal to
|
robert@269
|
39 input buffer:
|
robert@269
|
40 `context->audioOut[n * context->audioChannels + ch] = context->audioIn[n * context->audioChannels + ch]`.
|
robert@269
|
41
|
robert@269
|
42
|
robert@269
|
43 */
|
robert@269
|
44
|
robert@269
|
45
|
robert@269
|
46
|
robert@269
|
47
|
andrewm@13
|
48
|
andrewm@56
|
49 #include <BeagleRT.h>
|
andrewm@56
|
50 #include <Utilities.h>
|
andrewm@13
|
51 #include <rtdk.h>
|
andrewm@13
|
52
|
andrewm@56
|
53 // setup() is called once before the audio rendering starts.
|
andrewm@13
|
54 // Use it to perform any initialisation and allocation which is dependent
|
andrewm@13
|
55 // on the period size or sample rate.
|
andrewm@13
|
56 //
|
andrewm@13
|
57 // userData holds an opaque pointer to a data structure that was passed
|
andrewm@13
|
58 // in from the call to initAudio().
|
andrewm@13
|
59 //
|
andrewm@13
|
60 // Return true on success; returning false halts the program.
|
andrewm@13
|
61
|
andrewm@56
|
62 bool setup(BeagleRTContext *context, void *userData)
|
andrewm@13
|
63 {
|
andrewm@13
|
64 // Nothing to do here...
|
andrewm@13
|
65 return true;
|
andrewm@13
|
66 }
|
andrewm@13
|
67
|
andrewm@13
|
68 // render() is called regularly at the highest priority by the audio engine.
|
andrewm@13
|
69 // Input and output are given from the audio hardware and the other
|
andrewm@13
|
70 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
|
andrewm@13
|
71 // will be 0.
|
andrewm@13
|
72
|
andrewm@52
|
73 void render(BeagleRTContext *context, void *userData)
|
andrewm@13
|
74 {
|
andrewm@13
|
75 // Simplest possible case: pass inputs through to outputs
|
andrewm@52
|
76 for(unsigned int n = 0; n < context->audioFrames; n++) {
|
giuliomoro@180
|
77 for(unsigned int ch = 0; ch < context->audioChannels; ch++){
|
giuliomoro@180
|
78 // Two equivalent ways to write this code
|
giuliomoro@180
|
79
|
giuliomoro@180
|
80 // The long way, using the buffers directly:
|
giuliomoro@180
|
81 // context->audioOut[n * context->audioChannels + ch] =
|
giuliomoro@180
|
82 // context->audioIn[n * context->audioChannels + ch];
|
giuliomoro@180
|
83
|
giuliomoro@180
|
84 // Or using the macros:
|
giuliomoro@180
|
85 audioWriteFrame(context, n, ch, audioReadFrame(context, n, ch));
|
giuliomoro@180
|
86 }
|
andrewm@13
|
87 }
|
andrewm@13
|
88
|
giuliomoro@180
|
89 // Same with analog channelss
|
giuliomoro@180
|
90 for(unsigned int n = 0; n < context->analogFrames; n++) {
|
giuliomoro@180
|
91 for(unsigned int ch = 0; ch < context->analogChannels; ch++) {
|
giuliomoro@180
|
92 // Two equivalent ways to write this code
|
giuliomoro@180
|
93
|
giuliomoro@180
|
94 // The long way, using the buffers directly:
|
giuliomoro@180
|
95 // context->analogOut[n * context->analogChannels + ch] = context->analogIn[n * context->analogChannels + ch];
|
giuliomoro@180
|
96
|
giuliomoro@180
|
97 // Or using the macros:
|
giuliomoro@180
|
98 analogWriteFrame(context, n, ch, analogReadFrame(context, n, ch));
|
giuliomoro@180
|
99 }
|
giuliomoro@180
|
100 }
|
andrewm@13
|
101 }
|
andrewm@13
|
102
|
andrewm@56
|
103 // cleanup() is called once at the end, after the audio has stopped.
|
andrewm@56
|
104 // Release any resources that were allocated in setup().
|
andrewm@13
|
105
|
andrewm@56
|
106 void cleanup(BeagleRTContext *context, void *userData)
|
andrewm@13
|
107 {
|
andrewm@13
|
108
|
andrewm@13
|
109 }
|