Mercurial > hg > beaglert
comparison projects/basic_libpd/render.cpp @ 230:af211ee57867 mergingClockSync
Working basic_libpd
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Sat, 09 Apr 2016 08:19:09 +0100 |
parents | |
children | 600355cf4ed5 |
comparison
equal
deleted
inserted
replaced
229:c768ed1055b0 | 230:af211ee57867 |
---|---|
1 /* | |
2 * render.cpp | |
3 * | |
4 * Created on: Oct 24, 2014 | |
5 * Author: parallels | |
6 */ | |
7 | |
8 #include <BeagleRT.h> | |
9 #include <cmath> | |
10 #include <Utilities.h> | |
11 #include <I2c_Codec.h> | |
12 #include <PRU.h> | |
13 #include <stdio.h> | |
14 #include "z_libpd.h" | |
15 #include <UdpServer.h> | |
16 | |
17 // setup() is called once before the audio rendering starts. | |
18 // Use it to perform any initialisation and allocation which is dependent | |
19 // on the period size or sample rate. | |
20 // | |
21 // userData holds an opaque pointer to a data structure that was passed | |
22 // in from the call to initAudio(). | |
23 // | |
24 // Return true on success; returning false halts the program. | |
25 #define DEFDACBLKSIZE 8u //make sure this matches the one used to compile libpd | |
26 | |
27 const int gChannelsInUse = 6; | |
28 int gBufLength; | |
29 | |
30 float* gInBuf; | |
31 float* gOutBuf; | |
32 | |
33 void pdnoteon(int ch, int pitch, int vel) { | |
34 printf("noteon: %d %d %d\n", ch, pitch, vel); | |
35 } | |
36 | |
37 void BeagleRT_printHook(const char *recv){ | |
38 rt_printf("%s", recv); | |
39 } | |
40 | |
41 UdpServer udpServer; | |
42 | |
43 void udpRead(){ | |
44 char dest[100] = {0}; | |
45 while(!gShouldStop){ | |
46 libpd_sys_microsleep(0); | |
47 usleep(1000); | |
48 } | |
49 } | |
50 | |
51 AuxiliaryTask udpReadTask; | |
52 bool setup(BeagleRTContext *context, void *userData) | |
53 { | |
54 udpServer.bindToPort(1234); | |
55 | |
56 // check that we are not running with a blocksize smaller than DEFDACBLKSIZE | |
57 // it would still work, but the load would be executed unevenly between calls to render | |
58 if(context->audioFrames < DEFDACBLKSIZE){ | |
59 fprintf(stderr, "Error: minimum block size must be %d\n", DEFDACBLKSIZE); | |
60 return false; | |
61 } | |
62 | |
63 // check that the sampling rate of the analogs is the same as audio if running with | |
64 // more than 2 channels (that is with analog). If we fix the TODO in render, then | |
65 // this test is not needed. | |
66 if(context->analogFrames != context->audioFrames){ | |
67 fprintf(stderr, "Error: analog and audio sampling rates must be the same\n"); | |
68 return false; | |
69 } | |
70 //following lines borrowed from libpd/samples/c/pdtest/pdtest.c | |
71 // init pd | |
72 libpd_set_printhook(BeagleRT_printHook); // set this before calling libpd_init | |
73 libpd_set_noteonhook(pdnoteon); | |
74 libpd_init(); | |
75 //TODO: analyse the ASCII of the patch file and find the in/outs to use | |
76 libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate); | |
77 | |
78 libpd_start_message(1); // one entry in list | |
79 libpd_add_float(1.0f); | |
80 libpd_finish_message("pd", "dsp"); | |
81 | |
82 gBufLength = max(DEFDACBLKSIZE, context->audioFrames); | |
83 unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength; | |
84 gInBuf = (float*)malloc(bufferSize); | |
85 gOutBuf = (float*)malloc(bufferSize); | |
86 // no need to memset to zero | |
87 | |
88 | |
89 char file[] = "_main.pd"; | |
90 char folder[] = "./"; | |
91 // open patch [; pd open file folder( | |
92 libpd_openfile(file, folder); | |
93 | |
94 udpReadTask = BeagleRT_createAuxiliaryTask(udpRead, 60, "udpReadTask"); | |
95 BeagleRT_scheduleAuxiliaryTask(udpReadTask); | |
96 return true; | |
97 } | |
98 | |
99 // render() is called regularly at the highest priority by the audio engine. | |
100 // Input and output are given from the audio hardware and the other | |
101 // ADCs and DACs (if available). If only audio is available, numMatrixFrames | |
102 // will be 0. | |
103 BeagleRTContext *c; | |
104 void render(BeagleRTContext *context, void *userData) | |
105 { | |
106 static int inW = 0; | |
107 static int outR = 0; | |
108 /* | |
109 * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers | |
110 * and the blocksize of Bela is the same as DEFDACBLKSIZE, then you probably | |
111 * do not need the for loops before and after libpd_process_float, so you can save quite some | |
112 * memory operations. | |
113 */ | |
114 | |
115 for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved | |
116 for(unsigned int k = 0; k < context->audioChannels; k++){ | |
117 gInBuf[inW++] = audioReadFrame(context, n, k); | |
118 } | |
119 for(unsigned int k = 0; k < gChannelsInUse - context->audioChannels; k ++){ // add analogs | |
120 gInBuf[inW++] = analogReadFrame(context, n, k); | |
121 // TODO: Apply here sampling rate conversion from analogs to audio | |
122 } | |
123 if(inW == gBufLength * gChannelsInUse){ | |
124 inW = 0; | |
125 } | |
126 } | |
127 | |
128 if(inW == 0){ //if the buffer is full, process it | |
129 int numberOfPdBlocksToProcess = gBufLength/DEFDACBLKSIZE; | |
130 libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf); | |
131 outR = 0; // reset the read pointer. NOTE: hopefully this is not needed EXCEPT the first time | |
132 } | |
133 | |
134 for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved | |
135 for(unsigned int k = 0; k < context->audioChannels; k++){ | |
136 audioWriteFrame(context, n, k, gOutBuf[outR++]); | |
137 } | |
138 //add analogs here, limit them to channelsInUse | |
139 for(unsigned int k = 0; k < gChannelsInUse - context->audioChannels; k ++){ // add analogs | |
140 analogWriteFrame(context, n, k, gOutBuf[outR++]); | |
141 // TODO: Apply here sampling rate conversion from analogs to audio | |
142 } | |
143 if(outR == gBufLength * gChannelsInUse){ | |
144 outR = 0; | |
145 } | |
146 } | |
147 } | |
148 // cleanup() is called once at the end, after the audio has stopped. | |
149 // Release any resources that were allocated in setup(). | |
150 | |
151 void cleanup(BeagleRTContext *context, void *userData) | |
152 { | |
153 free(gInBuf); | |
154 free(gOutBuf); | |
155 } |