Mercurial > hg > beaglert
view projects/heavy/samphold/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 |
line wrap: on
line source
/** * Copyright (c) 2014,2015 Enzien Audio, Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, and/or * sublicense copies of the Software, strictly on a non-commercial basis, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * DO NOT MODIFY. THIS CODE IS MACHINE GENERATED BY THE SECTION6 HEAVY COMPILER. */ /* * System Includes */ #include <assert.h> #include <math.h> #include <string.h> #include <stdarg.h> #include "HvContext_bbb.h" #include "HeavyMath.h" /* * Function Declarations */ static void cMsg_5KHpJ_sendMessage(HvBase *, int, const HvMessage *const); static void cSystem_tEzb9_sendMessage(HvBase *, int, const HvMessage *const); static void cBinop_DXD3m_sendMessage(HvBase *, int, const HvMessage *const); static void cBinop_tyjup_sendMessage(HvBase *, int, const HvMessage *const); static void cMsg_QrCwu_sendMessage(HvBase *, int, const HvMessage *const); static void cBinop_iWcBL_sendMessage(HvBase *, int, const HvMessage *const); static void cBinop_6USpC_sendMessage(HvBase *, int, const HvMessage *const); static void cBinop_QuDfQ_sendMessage(HvBase *, int, const HvMessage *const); static void cLoadbang_0Dgs1_sendMessage(HvBase *, int, const HvMessage *const); static void cVar_lxt7X_sendMessage(HvBase *, int, const HvMessage *const); static void cMsg_qW1tH_sendMessage(HvBase *, int, const HvMessage *const); static void cLoadbang_bGFum_sendMessage(HvBase *, int, const HvMessage *const); static void cBinop_79eIJ_sendMessage(HvBase *, int, const HvMessage *const); static void cRandom_zn9Go_sendMessage(HvBase *, int, const HvMessage *const); static void cUnop_2Y2rq_sendMessage(HvBase *, int, const HvMessage *const); /* * Static Helper Functions */ static void ctx_intern_scheduleMessageForReceiver( HvBase *const _c, const char *name, HvMessage *m) { switch (msg_symbolToHash(name)) { default: return; } } static struct HvTable *ctx_intern_getTableForHash(HvBase *const _c, hv_uint32_t h) { switch (h) { default: return NULL; } } /* * Context Include and Implementatons */ Hv_bbb *hv_bbb_new_with_pool(double sampleRate, int poolKb) { hv_assert(sampleRate > 0.0); // can't initialise with sampling rate of 0 hv_assert(poolKb >= 1); // a message pool of some reasonable size is always needed Hv_bbb *const _c = (Hv_bbb *) hv_malloc(sizeof(Hv_bbb)); Base(_c)->numInputChannels = 0; Base(_c)->numOutputChannels = 2; Base(_c)->sampleRate = sampleRate; Base(_c)->blockStartTimestamp = 0; Base(_c)->f_scheduleMessageForReceiver = &ctx_intern_scheduleMessageForReceiver; Base(_c)->f_getTableForHash = &ctx_intern_getTableForHash; mq_initWithPoolSize(&Base(_c)->mq, poolKb); Base(_c)->basePath = NULL; Base(_c)->printHook = NULL; Base(_c)->sendHook = NULL; Base(_c)->userData = NULL; Base(_c)->name = "bbb"; Base(_c)->numBytes = sizeof(Hv_bbb); Base(_c)->numBytes += sVari_init(&_c->sVari_9lqOg, 0, 0, false); Base(_c)->numBytes += sVarf_init(&_c->sVarf_a6sNx, 0.0f, 0.0f, false); Base(_c)->numBytes += sVarf_init(&_c->sVarf_l59CR, 0.0f, 0.0f, false); Base(_c)->numBytes += sRPole_init(&_c->sRPole_ACVjc); Base(_c)->numBytes += sPhasor_k_init(&_c->sPhasor_GKtI5, 880.0f, sampleRate); Base(_c)->numBytes += sDel1_init(&_c->sDel1_OZ8Kl); Base(_c)->numBytes += sSamphold_init(&_c->sSamphold_XcpkT); Base(_c)->numBytes += sPhasor_init(&_c->sPhasor_6rvdw, sampleRate); Base(_c)->numBytes += cBinop_init(&_c->cBinop_tyjup, 0.0f); // __mul Base(_c)->numBytes += cBinop_init(&_c->cBinop_iWcBL, 0.0f); // __max Base(_c)->numBytes += cBinop_init(&_c->cBinop_6USpC, 1.0f); // __min Base(_c)->numBytes += cVar_init_f(&_c->cVar_lxt7X, 1.0f); Base(_c)->numBytes += cBinop_init(&_c->cBinop_79eIJ, 8388610.0f); // __mul Base(_c)->numBytes += cRandom_init(&_c->cRandom_zn9Go, 1159211063); // loadbang ctx_scheduleMessage(Base(_c), msg_initWithBang(HV_MESSAGE_ON_STACK(1), 0), &cLoadbang_0Dgs1_sendMessage, 0); ctx_scheduleMessage(Base(_c), msg_initWithBang(HV_MESSAGE_ON_STACK(1), 0), &cLoadbang_bGFum_sendMessage, 0); return _c; } Hv_bbb *hv_bbb_new(double sampleRate) { return hv_bbb_new_with_pool(sampleRate, 10); // default to 10KB MessagePool } void hv_bbb_free(Hv_bbb *_c) { hv_free(Base(_c)->basePath); mq_free(&Base(_c)->mq); // free queue after all objects have been freed, messages may be cancelled hv_free(_c); } /* * Static Function Implementation */ static void cMsg_5KHpJ_sendMessage(HvBase *_c, int letIn, const HvMessage *const n) { HvMessage *m = NULL; m = HV_MESSAGE_ON_STACK(1); msg_init(m, 1, msg_getTimestamp(n)); msg_setSymbol(m, 0, "samplerate"); cSystem_onMessage(_c, NULL, 0, m, &cSystem_tEzb9_sendMessage); } static void cSystem_tEzb9_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cMsg_QrCwu_sendMessage(_c, 0, m); } static void cBinop_DXD3m_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cBinop_onMessage(_c, &Context(_c)->cBinop_tyjup, HV_BINOP_MULTIPLY, 1, m, &cBinop_tyjup_sendMessage); } static void cBinop_tyjup_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cBinop_onMessage(_c, &Context(_c)->cBinop_6USpC, HV_BINOP_MIN, 0, m, &cBinop_6USpC_sendMessage); } static void cMsg_QrCwu_sendMessage(HvBase *_c, int letIn, const HvMessage *const n) { HvMessage *m = NULL; m = HV_MESSAGE_ON_STACK(2); msg_init(m, 2, msg_getTimestamp(n)); msg_setFloat(m, 0, 6.28319f); msg_setElementToFrom(m, 1, n, 0); cBinop_k_onMessage(_c, NULL, HV_BINOP_DIVIDE, 0.0f, 0, m, &cBinop_DXD3m_sendMessage); } static void cBinop_iWcBL_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cBinop_k_onMessage(_c, NULL, HV_BINOP_SUBTRACT, 1.0f, 0, m, &cBinop_QuDfQ_sendMessage); sVarf_onMessage(_c, &Context(_c)->sVarf_a6sNx, m); } static void cBinop_6USpC_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cBinop_onMessage(_c, &Context(_c)->cBinop_iWcBL, HV_BINOP_MAX, 0, m, &cBinop_iWcBL_sendMessage); } static void cBinop_QuDfQ_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { sVarf_onMessage(_c, &Context(_c)->sVarf_l59CR, m); } static void cLoadbang_0Dgs1_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cMsg_5KHpJ_sendMessage(_c, 0, m); cVar_onMessage(_c, &Context(_c)->cVar_lxt7X, 0, m, &cVar_lxt7X_sendMessage); } static void cVar_lxt7X_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cBinop_onMessage(_c, &Context(_c)->cBinop_tyjup, HV_BINOP_MULTIPLY, 0, m, &cBinop_tyjup_sendMessage); } static void cMsg_qW1tH_sendMessage(HvBase *_c, int letIn, const HvMessage *const n) { HvMessage *m = NULL; m = HV_MESSAGE_ON_STACK(2); msg_init(m, 2, msg_getTimestamp(n)); msg_setElementToFrom(m, 0, n, 0); msg_setFloat(m, 1, 1.0f); sVari_onMessage(_c, &Context(_c)->sVari_9lqOg, m); } static void cLoadbang_bGFum_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cRandom_onMessage(_c, &Context(_c)->cRandom_zn9Go, 0, m, &cRandom_zn9Go_sendMessage); } static void cBinop_79eIJ_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cUnop_onMessage(_c, HV_UNOP_FLOOR, m, &cUnop_2Y2rq_sendMessage); } static void cRandom_zn9Go_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cBinop_onMessage(_c, &Context(_c)->cBinop_79eIJ, HV_BINOP_MULTIPLY, 0, m, &cBinop_79eIJ_sendMessage); } static void cUnop_2Y2rq_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) { cMsg_qW1tH_sendMessage(_c, 0, m); } /* * Context Process Implementation */ int hv_bbb_process(Hv_bbb *const _c, float **const inputBuffers, float **const outputBuffers, int nx) { const int n4 = nx & ~HV_N_SIMD_MASK; // ensure that the block size is a multiple of HV_N_SIMD // temporary signal vars hv_bufferf_t Bf0, Bf1, Bf2, Bf3, Bf4; hv_bufferi_t Bi0, Bi1; // input and output vars hv_bufferf_t O0, O1; // declare and init the zero buffer hv_bufferf_t ZERO; __hv_zero_f(VOf(ZERO)); hv_uint32_t nextBlock = Base(_c)->blockStartTimestamp; for (int n = 0; n < n4; n += HV_N_SIMD) { // process all of the messages for this block nextBlock += HV_N_SIMD; while (mq_hasMessageBefore(&Base(_c)->mq, nextBlock)) { MessageNode *const node = mq_peek(&Base(_c)->mq); node->sendMessage(Base(_c), node->let, node->m); mq_pop(&Base(_c)->mq); } // zero output buffers __hv_zero_f(VOf(O0)); __hv_zero_f(VOf(O1)); // process all signal functions __hv_var_i(&_c->sVari_9lqOg, VOi(Bi0)); __hv_var_k_i(VOi(Bi1), 16807, 16807, 16807, 16807, 16807, 16807, 16807, 16807, 0); __hv_mul_i(VIi(Bi0), VIi(Bi1), VOi(Bi1)); sVarseti_process(&_c->sVari_9lqOg, VIi(Bi1)); __hv_cast_if(VIi(Bi1), VOf(Bf0)); __hv_var_k_f(VOf(Bf1), 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 0); __hv_mul_f(VIf(Bf0), VIf(Bf1), VOf(Bf1)); __hv_var_f(&_c->sVarf_a6sNx, VOf(Bf0)); __hv_mul_f(VIf(Bf1), VIf(Bf0), VOf(Bf0)); __hv_var_f(&_c->sVarf_l59CR, VOf(Bf1)); __hv_rpole_f(&_c->sRPole_ACVjc, VIf(Bf0), VIf(Bf1), VOf(Bf1)); __hv_var_k_f(VOf(Bf0), 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 0); __hv_mul_f(VIf(Bf1), VIf(Bf0), VOf(Bf0)); __hv_phasor_k_f(&_c->sPhasor_GKtI5, VOf(Bf1)); __hv_del1_f(&_c->sDel1_OZ8Kl, VIf(Bf1), VOf(Bf2)); __hv_lt_f(VIf(Bf1), VIf(Bf2), VOf(Bf2)); __hv_samphold_f(&_c->sSamphold_XcpkT, VIf(Bf0), VIf(Bf2), VOf(Bf2)); __hv_phasor_f(&_c->sPhasor_6rvdw, VIf(Bf2), VOf(Bf2)); __hv_var_k_f(VOf(Bf0), 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0); __hv_sub_f(VIf(Bf2), VIf(Bf0), VOf(Bf0)); __hv_abs_f(VIf(Bf0), VOf(Bf0)); __hv_var_k_f(VOf(Bf2), 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0); __hv_sub_f(VIf(Bf0), VIf(Bf2), VOf(Bf2)); __hv_var_k_f(VOf(Bf0), 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 0); __hv_mul_f(VIf(Bf2), VIf(Bf0), VOf(Bf0)); __hv_mul_f(VIf(Bf0), VIf(Bf0), VOf(Bf2)); __hv_mul_f(VIf(Bf0), VIf(Bf2), VOf(Bf1)); __hv_mul_f(VIf(Bf1), VIf(Bf2), VOf(Bf2)); __hv_var_k_f(VOf(Bf3), 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0); __hv_var_k_f(VOf(Bf4), 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0); __hv_mul_f(VIf(Bf1), VIf(Bf4), VOf(Bf4)); __hv_sub_f(VIf(Bf0), VIf(Bf4), VOf(Bf4)); __hv_fma_f(VIf(Bf2), VIf(Bf3), VIf(Bf4), VOf(Bf4)); __hv_var_k_f(VOf(Bf3), 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0); __hv_mul_f(VIf(Bf4), VIf(Bf3), VOf(Bf3)); __hv_add_f(VIf(Bf3), VIf(O0), VOf(O0)); __hv_add_f(VIf(Bf3), VIf(O1), VOf(O1)); // save output vars to output buffer __hv_store_f(outputBuffers[0]+n, VIf(O0)); __hv_store_f(outputBuffers[1]+n, VIf(O1)); } Base(_c)->blockStartTimestamp = nextBlock; return n4; // return the number of frames processed } int hv_bbb_process_inline(Hv_bbb *c, float *const inputBuffers, float *const outputBuffers, int n4) { hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD int i = ctx_getNumInputChannels(Base(c)); float **bIn = (float **) hv_alloca(i*sizeof(float *)); while (i--) bIn[i] = inputBuffers+(i*n4); i = ctx_getNumOutputChannels(Base(c)); float **bOut = (float **) hv_alloca(i*sizeof(float *)); while (i--) bOut[i] = outputBuffers+(i*n4); int n = hv_bbb_process(c, bIn, bOut, n4); return n; } int hv_bbb_process_inline_short(Hv_bbb *c, short *const inputBuffers, short *const outputBuffers, int n4) { hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD int numChannels = ctx_getNumInputChannels(Base(c)); float *bIn = (float *) hv_alloca(numChannels*n4*sizeof(float)); for (int i = 0; i < numChannels; ++i) { for (int j = 0; j < n4; ++j) { bIn[i*n4+j] = ((float) inputBuffers[i+numChannels*j]) * 0.00003051757813f; } } numChannels = ctx_getNumOutputChannels(Base(c)); float *bOut = (float *) hv_alloca(numChannels*n4*sizeof(float)); int n = hv_bbb_process_inline(c, bIn, bOut, n4); for (int i = 0; i < numChannels; ++i) { for (int j = 0; j < n4; ++j) { outputBuffers[i+numChannels*j] = (short) (bOut[i*n4+j] * 32767.0f); } } return n; }