chris@160
|
1 /**
|
chris@160
|
2 * Copyright (c) 2014, 2015, Enzien Audio Ltd.
|
chris@160
|
3 *
|
chris@160
|
4 * Permission to use, copy, modify, and/or distribute this software for any
|
chris@160
|
5 * purpose with or without fee is hereby granted, provided that the above
|
chris@160
|
6 * copyright notice and this permission notice appear in all copies.
|
chris@160
|
7 *
|
chris@160
|
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
chris@160
|
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
chris@160
|
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
chris@160
|
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
chris@160
|
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
chris@160
|
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
chris@160
|
14 * PERFORMANCE OF THIS SOFTWARE.
|
chris@160
|
15 */
|
chris@160
|
16
|
chris@160
|
17 #include "HvTable.h"
|
chris@160
|
18
|
chris@160
|
19 hv_size_t hTable_init(HvTable *o, int length) {
|
chris@160
|
20 o->length = length;
|
chris@160
|
21 // true size of the table is always an integer multple of HV_N_SIMD
|
chris@160
|
22 o->size = (length + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
|
chris@160
|
23 // add an extra length for mirroring
|
chris@160
|
24 o->allocated = o->size + HV_N_SIMD;
|
chris@160
|
25 o->head = 0;
|
chris@160
|
26 hv_size_t numBytes = o->allocated * sizeof(float);
|
chris@160
|
27 o->buffer = (float *) hv_malloc(numBytes);
|
chris@160
|
28 hv_memset(o->buffer, numBytes);
|
chris@160
|
29 return numBytes;
|
chris@160
|
30 }
|
chris@160
|
31
|
chris@160
|
32 hv_size_t hTable_initWithData(HvTable *o, int length, const float *const data) {
|
chris@160
|
33 o->length = length;
|
chris@160
|
34 o->size = (length + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
|
chris@160
|
35 o->allocated = o->size + HV_N_SIMD;
|
chris@160
|
36 o->head = 0;
|
chris@160
|
37 hv_size_t numBytes = o->size * sizeof(float);
|
chris@160
|
38 o->buffer = (float *) hv_malloc(numBytes);
|
chris@160
|
39 hv_memset(o->buffer, numBytes);
|
chris@160
|
40 hv_memcpy(o->buffer, data, length*sizeof(float));
|
chris@160
|
41 return numBytes;
|
chris@160
|
42 }
|
chris@160
|
43
|
chris@160
|
44 hv_size_t hTable_initWithFinalData(HvTable *o, int length, float *data) {
|
chris@160
|
45 o->length = length;
|
chris@160
|
46 o->size = length;
|
chris@160
|
47 o->allocated = length;
|
chris@160
|
48 o->buffer = data;
|
chris@160
|
49 o->head = 0;
|
chris@160
|
50 return 0;
|
chris@160
|
51 }
|
chris@160
|
52
|
chris@160
|
53 void hTable_free(HvTable *o) {
|
chris@160
|
54 hv_free(o->buffer);
|
chris@160
|
55 }
|
chris@160
|
56
|
chris@160
|
57 int hTable_resize(HvTable *o, hv_uint32_t newLength) {
|
chris@160
|
58 // TODO(mhroth): update context with memory allocated by table
|
chris@160
|
59 // NOTE(mhroth): mirrored bytes are not necessarily carried over
|
chris@160
|
60 const hv_uint32_t oldBytes = (hv_uint32_t) (o->size * sizeof(float));
|
chris@160
|
61 const hv_uint32_t newSize = (newLength + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
|
chris@160
|
62 const hv_uint32_t newAllocated = newSize + HV_N_SIMD;
|
chris@160
|
63 const hv_uint32_t newBytes = (hv_uint32_t) (newAllocated * sizeof(float));
|
chris@160
|
64 float *b = (float *) hv_realloc(o->buffer, newBytes);
|
chris@160
|
65 hv_assert(b != NULL); // error while reallocing!
|
chris@160
|
66 if (newSize > o->size) hv_clear_buffer(b+o->size, newAllocated-o->size); // clear new parts of the buffer
|
chris@160
|
67 if (b != o->buffer) {
|
chris@160
|
68 // the buffer has been reallocated, ensure that it is on a 32-byte boundary
|
chris@160
|
69 if ((((uintptr_t) (const void *) b) & 0x10) == 0) {
|
chris@160
|
70 o->buffer = b;
|
chris@160
|
71 } else {
|
chris@160
|
72 float *c = (float *) hv_malloc(newBytes);
|
chris@160
|
73 hv_assert(c != NULL);
|
chris@160
|
74 hv_clear_buffer(c, newLength);
|
chris@160
|
75 const hv_size_t min = hv_min_ui(o->size, newLength);
|
chris@160
|
76 hv_memcpy(c, b, min * sizeof(float));
|
chris@160
|
77 hv_free(b);
|
chris@160
|
78 o->buffer = c;
|
chris@160
|
79 }
|
chris@160
|
80 }
|
chris@160
|
81 o->length = newLength;
|
chris@160
|
82 o->size = newSize;
|
chris@160
|
83 o->allocated = newAllocated;
|
chris@160
|
84 return (int) (newBytes - oldBytes);
|
chris@160
|
85 }
|
chris@160
|
86
|
chris@160
|
87 void hTable_onMessage(HvBase *_c, HvTable *o, int letIn, const HvMessage *const m,
|
chris@160
|
88 void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
|
chris@160
|
89 if (msg_compareSymbol(m,0,"resize") && msg_isFloat(m,1) && msg_getFloat(m,1) >= 0.0f) {
|
chris@160
|
90 hTable_resize(o, (int) hv_ceil_f(msg_getFloat(m,1))); // apply ceil to ensure that tables always have enough space
|
chris@160
|
91
|
chris@160
|
92 // send out the new size of the table
|
chris@160
|
93 HvMessage *n = HV_MESSAGE_ON_STACK(1);
|
chris@160
|
94 msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getSize(o));
|
chris@160
|
95 sendMessage(_c, 0, n);
|
chris@160
|
96 }
|
chris@160
|
97
|
chris@160
|
98 else if (msg_compareSymbol(m,0,"mirror")) {
|
chris@160
|
99 hv_memcpy(o->buffer+o->size, o->buffer, HV_N_SIMD*sizeof(float));
|
chris@160
|
100 }
|
chris@160
|
101 }
|