annotate projects/heavy/hello-world/HvContext_bbb.c @ 162:c3e8226a5651 heavy-updated

- added additional flags to C rules (-DNDEBUG, -mfpu=neon) - sample-accurate envelope triggering pd/heavy example
author chnrx <chris.heinrichs@gmail.com>
date Thu, 12 Nov 2015 14:59:46 +0000
parents 5bcf04234f80
children
rev   line source
chris@160 1
chris@160 2 /**
chris@160 3 * Copyright (c) 2014,2015 Enzien Audio, Ltd.
chris@160 4 *
chris@160 5 * Permission is hereby granted, free of charge, to any person obtaining a copy
chris@160 6 * of this software and associated documentation files (the "Software"),
chris@160 7 * to deal in the Software without restriction, including without limitation
chris@160 8 * the rights to use, copy, modify, merge, publish, distribute, and/or
chris@160 9 * sublicense copies of the Software, strictly on a non-commercial basis,
chris@160 10 * and to permit persons to whom the Software is furnished to do so,
chris@160 11 * subject to the following conditions:
chris@160 12 *
chris@160 13 * The above copyright notice and this permission notice shall be included in
chris@160 14 * all copies or substantial portions of the Software.
chris@160 15 *
chris@160 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
chris@160 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
chris@160 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
chris@160 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
chris@160 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
chris@160 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
chris@160 22 * IN THE SOFTWARE.
chris@160 23 *
chris@160 24 * DO NOT MODIFY. THIS CODE IS MACHINE GENERATED BY THE SECTION6 HEAVY COMPILER.
chris@160 25 */
chris@160 26
chris@160 27 /*
chris@160 28 * System Includes
chris@160 29 */
chris@160 30
chris@160 31 #include <assert.h>
chris@160 32 #include <math.h>
chris@160 33 #include <string.h>
chris@160 34 #include <stdarg.h>
chris@160 35 #include "HvContext_bbb.h"
chris@160 36 #include "HeavyMath.h"
chris@160 37
chris@160 38
chris@160 39 /*
chris@160 40 * Function Declarations
chris@160 41 */
chris@160 42
chris@160 43
chris@160 44
chris@160 45 /*
chris@160 46 * Static Helper Functions
chris@160 47 */
chris@160 48
chris@160 49 static void ctx_intern_scheduleMessageForReceiver(
chris@160 50 HvBase *const _c, const char *name, HvMessage *m) {
chris@160 51 switch (msg_symbolToHash(name)) {
chris@160 52 default: return;
chris@160 53 }
chris@160 54 }
chris@160 55
chris@160 56 static struct HvTable *ctx_intern_getTableForHash(HvBase *const _c, hv_uint32_t h) {
chris@160 57 switch (h) {
chris@160 58 default: return NULL;
chris@160 59 }
chris@160 60 }
chris@160 61
chris@160 62
chris@160 63
chris@160 64 /*
chris@160 65 * Context Include and Implementatons
chris@160 66 */
chris@160 67
chris@160 68 Hv_bbb *hv_bbb_new_with_pool(double sampleRate, int poolKb) {
chris@160 69 hv_assert(sampleRate > 0.0); // can't initialise with sampling rate of 0
chris@160 70 hv_assert(poolKb >= 1); // a message pool of some reasonable size is always needed
chris@160 71 Hv_bbb *const _c = (Hv_bbb *) hv_malloc(sizeof(Hv_bbb));
chris@160 72
chris@160 73 Base(_c)->numInputChannels = 0;
chris@160 74 Base(_c)->numOutputChannels = 2;
chris@160 75 Base(_c)->sampleRate = sampleRate;
chris@160 76 Base(_c)->blockStartTimestamp = 0;
chris@160 77 Base(_c)->f_scheduleMessageForReceiver = &ctx_intern_scheduleMessageForReceiver;
chris@160 78 Base(_c)->f_getTableForHash = &ctx_intern_getTableForHash;
chris@160 79 mq_initWithPoolSize(&Base(_c)->mq, poolKb);
chris@160 80 Base(_c)->basePath = NULL;
chris@160 81 Base(_c)->printHook = NULL;
chris@160 82 Base(_c)->sendHook = NULL;
chris@160 83 Base(_c)->userData = NULL;
chris@160 84 Base(_c)->name = "bbb";
chris@160 85
chris@160 86 Base(_c)->numBytes = sizeof(Hv_bbb);
chris@162 87 Base(_c)->numBytes += sPhasor_k_init(&_c->sPhasor_XIjUg, 440.0f, sampleRate);
chris@160 88
chris@160 89 // loadbang
chris@160 90
chris@160 91 return _c;
chris@160 92 }
chris@160 93
chris@160 94 Hv_bbb *hv_bbb_new(double sampleRate) {
chris@160 95 return hv_bbb_new_with_pool(sampleRate, 10); // default to 10KB MessagePool
chris@160 96 }
chris@160 97
chris@160 98 void hv_bbb_free(Hv_bbb *_c) {
chris@160 99
chris@160 100 hv_free(Base(_c)->basePath);
chris@160 101 mq_free(&Base(_c)->mq); // free queue after all objects have been freed, messages may be cancelled
chris@160 102
chris@160 103 hv_free(_c);
chris@160 104 }
chris@160 105
chris@160 106
chris@160 107
chris@160 108 /*
chris@160 109 * Static Function Implementation
chris@160 110 */
chris@160 111
chris@160 112
chris@160 113
chris@160 114 /*
chris@160 115 * Context Process Implementation
chris@160 116 */
chris@160 117
chris@160 118 int hv_bbb_process(Hv_bbb *const _c, float **const inputBuffers, float **const outputBuffers, int nx) {
chris@160 119 const int n4 = nx & ~HV_N_SIMD_MASK; // ensure that the block size is a multiple of HV_N_SIMD
chris@160 120
chris@160 121 // temporary signal vars
chris@160 122 hv_bufferf_t Bf0, Bf1, Bf2, Bf3, Bf4;
chris@160 123
chris@160 124 // input and output vars
chris@160 125 hv_bufferf_t O0, O1;
chris@160 126
chris@160 127 // declare and init the zero buffer
chris@160 128 hv_bufferf_t ZERO; __hv_zero_f(VOf(ZERO));
chris@160 129
chris@160 130 hv_uint32_t nextBlock = Base(_c)->blockStartTimestamp;
chris@160 131 for (int n = 0; n < n4; n += HV_N_SIMD) {
chris@160 132
chris@160 133 // process all of the messages for this block
chris@160 134 nextBlock += HV_N_SIMD;
chris@160 135 while (mq_hasMessageBefore(&Base(_c)->mq, nextBlock)) {
chris@160 136 MessageNode *const node = mq_peek(&Base(_c)->mq);
chris@160 137 node->sendMessage(Base(_c), node->let, node->m);
chris@160 138 mq_pop(&Base(_c)->mq);
chris@160 139 }
chris@160 140
chris@160 141
chris@160 142
chris@160 143 // zero output buffers
chris@160 144 __hv_zero_f(VOf(O0));
chris@160 145 __hv_zero_f(VOf(O1));
chris@160 146
chris@160 147 // process all signal functions
chris@162 148 __hv_phasor_k_f(&_c->sPhasor_XIjUg, VOf(Bf0));
chris@160 149 __hv_var_k_f(VOf(Bf1), 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0);
chris@160 150 __hv_sub_f(VIf(Bf0), VIf(Bf1), VOf(Bf1));
chris@160 151 __hv_abs_f(VIf(Bf1), VOf(Bf1));
chris@160 152 __hv_var_k_f(VOf(Bf0), 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0);
chris@160 153 __hv_sub_f(VIf(Bf1), VIf(Bf0), VOf(Bf0));
chris@160 154 __hv_var_k_f(VOf(Bf1), 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 0);
chris@160 155 __hv_mul_f(VIf(Bf0), VIf(Bf1), VOf(Bf1));
chris@160 156 __hv_mul_f(VIf(Bf1), VIf(Bf1), VOf(Bf0));
chris@160 157 __hv_mul_f(VIf(Bf1), VIf(Bf0), VOf(Bf2));
chris@160 158 __hv_mul_f(VIf(Bf2), VIf(Bf0), VOf(Bf0));
chris@160 159 __hv_var_k_f(VOf(Bf3), 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0);
chris@160 160 __hv_var_k_f(VOf(Bf4), 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0);
chris@160 161 __hv_mul_f(VIf(Bf2), VIf(Bf4), VOf(Bf4));
chris@160 162 __hv_sub_f(VIf(Bf1), VIf(Bf4), VOf(Bf4));
chris@160 163 __hv_fma_f(VIf(Bf0), VIf(Bf3), VIf(Bf4), VOf(Bf4));
chris@160 164 __hv_var_k_f(VOf(Bf3), 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0);
chris@160 165 __hv_mul_f(VIf(Bf4), VIf(Bf3), VOf(Bf3));
chris@162 166 __hv_add_f(VIf(Bf3), VIf(O0), VOf(O0));
chris@160 167 __hv_add_f(VIf(Bf3), VIf(O1), VOf(O1));
chris@160 168
chris@160 169 // save output vars to output buffer
chris@160 170 __hv_store_f(outputBuffers[0]+n, VIf(O0));
chris@160 171 __hv_store_f(outputBuffers[1]+n, VIf(O1));
chris@160 172 }
chris@160 173
chris@160 174 Base(_c)->blockStartTimestamp = nextBlock;
chris@160 175
chris@160 176 return n4; // return the number of frames processed
chris@160 177 }
chris@160 178
chris@160 179 int hv_bbb_process_inline(Hv_bbb *c, float *const inputBuffers, float *const outputBuffers, int n4) {
chris@160 180 hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD
chris@160 181 int i = ctx_getNumInputChannels(Base(c));
chris@160 182 float **bIn = (float **) hv_alloca(i*sizeof(float *));
chris@160 183 while (i--) bIn[i] = inputBuffers+(i*n4);
chris@160 184
chris@160 185 i = ctx_getNumOutputChannels(Base(c));
chris@160 186 float **bOut = (float **) hv_alloca(i*sizeof(float *));
chris@160 187 while (i--) bOut[i] = outputBuffers+(i*n4);
chris@160 188
chris@160 189 int n = hv_bbb_process(c, bIn, bOut, n4);
chris@160 190 return n;
chris@160 191 }
chris@160 192
chris@160 193 int hv_bbb_process_inline_short(Hv_bbb *c, short *const inputBuffers, short *const outputBuffers, int n4) {
chris@160 194 hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD
chris@160 195 int numChannels = ctx_getNumInputChannels(Base(c));
chris@160 196 float *bIn = (float *) hv_alloca(numChannels*n4*sizeof(float));
chris@160 197 for (int i = 0; i < numChannels; ++i) {
chris@160 198 for (int j = 0; j < n4; ++j) {
chris@160 199 bIn[i*n4+j] = ((float) inputBuffers[i+numChannels*j]) * 0.00003051757813f;
chris@160 200 }
chris@160 201 }
chris@160 202
chris@160 203 numChannels = ctx_getNumOutputChannels(Base(c));
chris@160 204 float *bOut = (float *) hv_alloca(numChannels*n4*sizeof(float));
chris@160 205
chris@160 206 int n = hv_bbb_process_inline(c, bIn, bOut, n4);
chris@160 207
chris@160 208 for (int i = 0; i < numChannels; ++i) {
chris@160 209 for (int j = 0; j < n4; ++j) {
chris@160 210 outputBuffers[i+numChannels*j] = (short) (bOut[i*n4+j] * 32767.0f);
chris@160 211 }
chris@160 212 }
chris@160 213
chris@160 214 return n;
chris@160 215 }