Exemplo n.º 1
0
HvMessage *mp_addMessage(MessagePool *mp, const HvMessage *m) {
  const hv_size_t b = msg_getSize(m);
  // determine the message list index to allocate data from based on the msg size
  // smallest chunk size is 32 bytes
  const hv_size_t i = mp_messagelistIndexForSize(b);

  hv_assert(i < MP_NUM_MESSAGE_LISTS); // how many chunk sizes do we want to support? 32, 64, 128, 256 at the moment
  MessagePoolList *ml = &mp->lists[i];
  const hv_size_t chunkSize = 32 << i;

  if (ml_hasAvailable(ml)) {
    char *buf = ml_pop(ml);
    msg_copyToBuffer(m, buf, chunkSize);
    return (HvMessage *) buf;
  } else {
    // if no appropriately sized buffer is immediately available, increase the size of the used buffer
    const hv_size_t newIndex = mp->bufferIndex + MP_BLOCK_SIZE_BYTES;
    hv_assert((newIndex <= mp->bufferSize) &&
        "The message pool buffer size has been exceeded. The context cannot store more messages. "
        "Try using the new_with_options() initialiser with a larger pool size (default is 10KB).");

    for (hv_size_t j = mp->bufferIndex; j < newIndex; j += chunkSize) {
      ml_push(ml, mp->buffer + j); // push new nodes onto the list with chunk pointers
    }
    mp->bufferIndex = newIndex;
    char *buf = ml_pop(ml);
    msg_copyToBuffer(m, buf, chunkSize);
    return (HvMessage *) buf;
  }
}
Exemplo n.º 2
0
HvMessage *mp_addMessage(MessagePool *mp, const HvMessage *m) {
  const hv_size_t b = msg_getNumHeapBytes(m);
  // determine the message list index to allocate data from based on the msg size
  // smallest chunk size is 32 bytes
  const hv_size_t i = mp_messagelistIndexForSize(b);

  assert(i < MP_NUM_MESSAGE_LISTS); // how many chunk sizes do we want to support? 32, 64, 128, 256 at the moment
  MessagePoolList *ml = &mp->lists[i];
  const hv_size_t chunkSize = 32 << i;

  if (ml_hasAvailable(ml)) {
    char *buf = ml_pop(ml);
    msg_copyToBuffer(m, buf, chunkSize);
    return (HvMessage *) buf;
  } else {
    // if no appropriately sized buffer is immediately available, increase the size of the used buffer
    const hv_size_t newIndex = mp->bufferIndex + MP_BLOCK_SIZE_BYTES;
    hv_assert(newIndex <= mp->bufferSize); // have we have exceeded the buffer size?

    for (hv_size_t i = mp->bufferIndex; i < newIndex; i += chunkSize) {
      ml_push(ml, mp->buffer + i); // push new nodes onto the list with chunk pointers
    }
    mp->bufferIndex = newIndex;
    char *buf = ml_pop(ml);
    msg_copyToBuffer(m, buf, chunkSize);
    return (HvMessage *) buf;
  }
}
hv_size_t mq_initWithPoolSize(MessageQueue *q, hv_size_t poolSizeKB) {
  hv_assert(poolSizeKB > 0);
  q->head = NULL;
  q->tail = NULL;
  q->pool = NULL;
  return mp_init(&q->mp, poolSizeKB);
}
Exemplo n.º 4
0
void cDelay_onMessage(HvBase *_c, ControlDelay *o, int letIn, const HvMessage *const m,
    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
  switch (letIn) {
    case 0: {
      if (msg_compareSymbol(m, 0, "flush")) {
        // send all messages immediately
        for (int i = 0; i < __HV_DELAY_MAX_MESSAGES; i++) {
          HvMessage *n = o->msgs[i];
          if (n != NULL) {
            msg_setTimestamp(n, msg_getTimestamp(m)); // update the timestamp to now
            sendMessage(_c, 0, n); // send the message
            ctx_cancelMessage(_c, n, sendMessage); // then clear it
            // NOTE(mhroth): there may be a problem here if a flushed message causes a clear message to return
            // to this object in the same step
          }
        }
        hv_memset(o->msgs, __HV_DELAY_MAX_MESSAGES*sizeof(HvMessage *));
      } else if (msg_compareSymbol(m, 0, "clear")) {
        // cancel (clear) all (pending) messages
        for (int i = 0; i < __HV_DELAY_MAX_MESSAGES; i++) {
          HvMessage *n = o->msgs[i];
          if (n != NULL) {
            ctx_cancelMessage(_c, n, sendMessage);
          }
        }
        hv_memset(o->msgs, __HV_DELAY_MAX_MESSAGES*sizeof(HvMessage *));
      } else {
        hv_uint32_t ts = msg_getTimestamp(m);
        msg_setTimestamp((HvMessage *) m, ts+o->delay); // update the timestamp to set the delay
        int i;
        for (i = 0; i < __HV_DELAY_MAX_MESSAGES; i++) {
          if (o->msgs[i] == NULL) {
            o->msgs[i] = ctx_scheduleMessage(_c, m, sendMessage, 0);
            break;
          }
        }
        hv_assert(i < __HV_DELAY_MAX_MESSAGES); // scheduled message limit reached
        msg_setTimestamp((HvMessage *) m, ts); // return to the original timestamp
      }
      break;
    }
    case 1: {
      if (msg_isFloat(m,0)) {
        // set delay in milliseconds
        o->delay = ctx_millisecondsToSamples(_c,msg_getFloat(m,0));
      }
      break;
    }
    case 2: {
      if (msg_isFloat(m,0)) {
        // set delay in samples
        o->delay = (hv_uint32_t) msg_getFloat(m,0);
      }
      break;
    }
    default: break;
  }
}
static MessageNode *mq_getOrCreateNodeFromPool(MessageQueue *q) {
  if (q->pool == NULL) {
    // if necessary, create a new empty node
    q->pool = (MessageNode *) hv_malloc(sizeof(MessageNode));
    hv_assert(q->pool != NULL);
    q->pool->next = NULL;
  }
  MessageNode *node = q->pool;
  q->pool = q->pool->next;
  return node;
}
Exemplo n.º 6
0
hv_size_t mp_init(MessagePool *mp, hv_size_t numKB) {
  mp->bufferSize = numKB * 1024;
  mp->buffer = (char *) hv_malloc(mp->bufferSize);
  hv_assert(mp->buffer != NULL);
  mp->bufferIndex = 0;

  // initialise all message lists
  for (int i = 0; i < MP_NUM_MESSAGE_LISTS; i++) {
    mp->lists[i].head = NULL;
    mp->lists[i].pool = NULL;
  }

  return mp->bufferSize;
}
Exemplo n.º 7
0
/** Push a MessageListNode with the given pointer onto the head of the queue. */
static void ml_push(MessagePoolList *ml, void *p) {
  MessageListNode *n = NULL;
  if (ml->pool != NULL) {
    // take an empty MessageListNode from the pool
    n = ml->pool;
    ml->pool = n->next;
  } else {
    // a MessageListNode is not available, allocate one
    n = (MessageListNode *) hv_malloc(sizeof(MessageListNode));
    hv_assert(n != NULL);
  }
  n->p = (char *) p;
  n->next = ml->head;
  ml->head = n; // push to the front of the queue
}
Exemplo n.º 8
0
static void sBiquad_k_updateCoefficients(SignalBiquad_k *const o) {
#if 0
  // inspect the filter coefficients to ensure that the filter is stable
  // 1/((1-a*z^-1) * (1-b*z^-1))
  float k = (o->a1*o->a1) - (4.0f*o->a2);
  float l = hv_sqrt_f(hv_abs_f(k));

  float m_alpha = 0.0f;
  float m_beta = 0.0f;
  if (k < 0.0f) {
    // alpha is complex
    float r_alpha = o->a1 * 0.5f;
    float i_alpha = l * 0.5f;
    m_alpha = (r_alpha*r_alpha + i_alpha*i_alpha); // |alpha|^2

    float r_beta = (o->a2 * r_alpha) / m_alpha;
    float i_beta = (o->a2 * -i_alpha) / m_alpha;
    m_alpha = hv_sqrt_f(m_alpha);
    m_beta = hv_sqrt_f(r_beta*r_beta + i_beta*i_beta);
  } else {
    // alpha is real
    float alpha = (o->a1 + l) * 0.5f;
    float beta = o->a2 / alpha;
    m_alpha = hv_abs_f(alpha);
    m_beta = hv_abs_f(beta);
  }

  hv_assert(m_alpha < 1.0f);
  hv_assert(m_beta < 1.0f);
#endif

  // calculate all filter coefficients in the double domain
#if HV_SIMD_AVX || HV_SIMD_SSE || HV_SIMD_NEON
  double b0 = (double) o->b0;
  double b1 = (double) o->b1;
  double b2 = (double) o->b2;
  double a1 = (double) -o->a1;
  double a2 = (double) -o->a2;

  double coeffs[4][8] =
  {
    { 0,  0,  0,  b0, b1, b2, a1, a2 },
    { 0,  0,  b0, b1, b2, 0,  a2, 0  },
    { 0,  b0, b1, b2, 0,  0,  0,  0  },
    { b0, b1, b2, 0,  0,  0,  0,  0  },
  };

  for (int i = 0; i < 8; i++) {
    coeffs[1][i] += a1*coeffs[0][i];
    coeffs[2][i] += a1*coeffs[1][i] + a2*coeffs[0][i];
    coeffs[3][i] += a1*coeffs[2][i] + a2*coeffs[1][i];
  }

#if HV_SIMD_AVX || HV_SIMD_SSE
  o->coeff_xp3 = _mm_set_ps((float) coeffs[3][0], (float) coeffs[2][0], (float) coeffs[1][0], (float) coeffs[0][0]);
  o->coeff_xp2 = _mm_set_ps((float) coeffs[3][1], (float) coeffs[2][1], (float) coeffs[1][1], (float) coeffs[0][1]);
  o->coeff_xp1 = _mm_set_ps((float) coeffs[3][2], (float) coeffs[2][2], (float) coeffs[1][2], (float) coeffs[0][2]);
  o->coeff_x0 =  _mm_set_ps((float) coeffs[3][3], (float) coeffs[2][3], (float) coeffs[1][3], (float) coeffs[0][3]);
  o->coeff_xm1 = _mm_set_ps((float) coeffs[3][4], (float) coeffs[2][4], (float) coeffs[1][4], (float) coeffs[0][4]);
  o->coeff_xm2 = _mm_set_ps((float) coeffs[3][5], (float) coeffs[2][5], (float) coeffs[1][5], (float) coeffs[0][5]);
  o->coeff_ym1 = _mm_set_ps((float) coeffs[3][6], (float) coeffs[2][6], (float) coeffs[1][6], (float) coeffs[0][6]);
  o->coeff_ym2 = _mm_set_ps((float) coeffs[3][7], (float) coeffs[2][7], (float) coeffs[1][7], (float) coeffs[0][7]);
#else // HV_SIMD_NEON
  o->coeff_xp3 = (float32x4_t) {(float) coeffs[0][0], (float) coeffs[1][0], (float) coeffs[2][0], (float) coeffs[3][0]};
  o->coeff_xp2 = (float32x4_t) {(float) coeffs[0][1], (float) coeffs[1][1], (float) coeffs[2][1], (float) coeffs[3][1]};
  o->coeff_xp1 = (float32x4_t) {(float) coeffs[0][2], (float) coeffs[1][2], (float) coeffs[2][2], (float) coeffs[3][2]};
  o->coeff_x0 =  (float32x4_t) {(float) coeffs[0][3], (float) coeffs[1][3], (float) coeffs[2][3], (float) coeffs[3][3]};
  o->coeff_xm1 = (float32x4_t) {(float) coeffs[0][4], (float) coeffs[1][4], (float) coeffs[2][4], (float) coeffs[3][4]};
  o->coeff_xm2 = (float32x4_t) {(float) coeffs[0][5], (float) coeffs[1][5], (float) coeffs[2][5], (float) coeffs[3][5]};
  o->coeff_ym1 = (float32x4_t) {(float) coeffs[0][6], (float) coeffs[1][6], (float) coeffs[2][6], (float) coeffs[3][6]};
  o->coeff_ym2 = (float32x4_t) {(float) coeffs[0][7], (float) coeffs[1][7], (float) coeffs[2][7], (float) coeffs[3][7]};
#endif
#endif
  // NOTE(mhroth): not necessary to calculate any coefficients for HV_SIMD_NONE case
}
Exemplo n.º 9
0
void hv_scheduleMessageForReceiver(HvBase *c, const char *receiverName, double delayMs, HvMessage *m) {
  hv_assert(delayMs >= 0.0);
  msg_setTimestamp(m, c->blockStartTimestamp + (hv_uint32_t) (delayMs*ctx_getSampleRate(c)/1000.0));
  ctx_scheduleMessageForReceiver(c, receiverName, m);
}