History

reworked mempool to use a linked list of free space and headers at the start of allocated regions

Matthew Wang committed 7 years ago

Commit 1fdec381 parent 4f70bc68 files · +220 −145Browse files

Unified · Split

8 files
  1. .DS_Store +0 −0
  2. LEAF/Inc/leaf-math.h +14 −0
  3. LEAF/Inc/leaf-mempool.h +10 −10
  4. LEAF/Src/leaf-effects.c +3 −1
  5. LEAF/Src/leaf-envelopes.c +0 −61
  6. LEAF/Src/leaf-math.c +57 −0
  7. LEAF/Src/leaf-mempool.c +130 −67
  8. LEAF_JUCEPlugin/Source/MyTest.cpp +7 −7
.DS_Store+0−0

Binary file not shown.

LEAF/Inc/leaf-math.h+14−0
@@ -128,6 +128,20 @@ int fastabs_int(int in); · 127 unmodified lines
128// alternative implementation for abs()128// alternative implementation for abs()
129// REQUIRES: 32 bit floats129// REQUIRES: 32 bit floats
130float fastabs(float f);130float fastabs(float f);
131
132#define LOGTEN 2.302585092994
133
134float mtof(float f);
135
136float ftom(float f);
137
138float powtodb(float f);
139
140float rmstodb(float f);
141
142float dbtopow(float f);
143
144float dbtorms(float f);
131 145
132//==============================================================================146//==============================================================================
133 147
LEAF/Inc/leaf-mempool.h+10−10
@@ -57,19 +57,20 @@ extern "C" { · 56 unmodified lines
57/**57/**
58 * memory pool structure58 * memory pool structure
59 */59 */
60typedef struct mpool_pool_t {60
61// node of free list
62typedef struct mpool_node_t {
61 void *pool; // memory pool field63 void *pool; // memory pool field
62 struct mpool_pool_t *next; // next memory pool's pointer64 struct mpool_node_t *next; // next node pointer
65 struct mpool_node_t *prev; // prev node pointer
63 size_t size;66 size_t size;
64 int used; // used flag67} mpool_node_t;
65} mpool_pool_t;
66 68
67typedef struct mpool_t {69typedef struct mpool_t {
68 mpool_pool_t *head; // memory pool's head70 void* mpool; // start of the mpool
69 size_t usize; // used pool size of current pool71 size_t usize; // used size of the pool
70 size_t msize; // max pool size of current pool72 size_t msize; // max size of the pool
71 mpool_pool_t *mpool; // memory pool73 mpool_node_t* head; // first node of memory pool free list
72 int next;
73} mpool_t;74} mpool_t;
74 75
75void mpool_create (char* memory, size_t size, mpool_t* pool);76void mpool_create (char* memory, size_t size, mpool_t* pool);
@@ -80,7 +81,6 @@ void mpool_free(void* ptr, mpool_t* pool); · 4 unmodified lines
80size_t mpool_get_size(mpool_t* pool);81size_t mpool_get_size(mpool_t* pool);
81size_t mpool_get_used(mpool_t* pool);82size_t mpool_get_used(mpool_t* pool);
82 83
83
84void leaf_pool_init(char* memory, size_t size);84void leaf_pool_init(char* memory, size_t size);
85 85
86void* leaf_alloc(size_t size);86void* leaf_alloc(size_t size);
LEAF/Src/leaf-effects.c+3−1
@@ -779,7 +779,9 @@ float tPitchShift_shiftToFreq (tPitchShift* ps, float freq) · 778 unmodified lines
779 779
780 tSOLAD_setPeriod(&ps->sola, period);780 tSOLAD_setPeriod(&ps->sola, period);
781 781
782 ps->pitchFactor = period*freq*leaf.invSampleRate;782 if (period != 0) ps->pitchFactor = period*freq*leaf.invSampleRate;
783 else ps->pitchFactor = 1.0f;
784
783 tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);785 tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
784 786
785 tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);787 tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
LEAF/Src/leaf-envelopes.c+0−61
@@ -23,67 +23,6 @@ · 22 unmodified lines
23 23
24#endif24#endif
25 25
26#define LOGTEN 2.302585092994
27
28float mtof(float f)
29{
30 if (f <= -1500.0f) return(0);
31 else if (f > 1499.0f) return(mtof(1499.0f));
32 else return (8.17579891564f * expf(0.0577622650f * f));
33}
34
35float ftom(float f)
36{
37 return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
38}
39
40float powtodb(float f)
41{
42 if (f <= 0) return (0);
43 else
44 {
45 float val = 100 + 10.f/LOGTEN * logf(f);
46 return (val < 0 ? 0 : val);
47 }
48}
49
50float rmstodb(float f)
51{
52 if (f <= 0) return (0);
53 else
54 {
55 float val = 100 + 20.f/LOGTEN * log(f);
56 return (val < 0 ? 0 : val);
57 }
58}
59
60float dbtopow(float f)
61{
62 if (f <= 0)
63 return(0);
64 else
65 {
66 if (f > 870.0f)
67 f = 870.0f;
68 return (expf((LOGTEN * 0.1f) * (f-100.0f)));
69 }
70}
71
72float dbtorms(float f)
73{
74 if (f <= 0)
75 return(0);
76 else
77 {
78 if (f > 485.0f)
79 f = 485.0f;
80 }
81 return (expf((LOGTEN * 0.05f) * (f-100.0f)));
82}
83
84
85
86
87// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //26// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
88void tEnvelope_init(tEnvelope* const env, float attack, float decay, oBool loop)27void tEnvelope_init(tEnvelope* const env, float attack, float decay, oBool loop)
89{28{
LEAF/Src/leaf-math.c+57−0
@@ -356,4 +356,61 @@ float LEAF_interpolation_linear (float A, float B, float alpha) · 355 unmodified lines
356 return out;356 return out;
357}357}
358 358
359#define LOGTEN 2.302585092994
360
361float mtof(float f)
362{
363 if (f <= -1500.0f) return(0);
364 else if (f > 1499.0f) return(mtof(1499.0f));
365 else return (8.17579891564f * expf(0.0577622650f * f));
366}
367
368float ftom(float f)
369{
370 return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
371}
372
373float powtodb(float f)
374{
375 if (f <= 0) return (0);
376 else
377 {
378 float val = 100 + 10.f/LOGTEN * logf(f);
379 return (val < 0 ? 0 : val);
380 }
381}
382
383float rmstodb(float f)
384{
385 if (f <= 0) return (0);
386 else
387 {
388 float val = 100 + 20.f/LOGTEN * log(f);
389 return (val < 0 ? 0 : val);
390 }
391}
392
393float dbtopow(float f)
394{
395 if (f <= 0)
396 return(0);
397 else
398 {
399 if (f > 870.0f)
400 f = 870.0f;
401 return (expf((LOGTEN * 0.1f) * (f-100.0f)));
402 }
403}
404
405float dbtorms(float f)
406{
407 if (f <= 0)
408 return(0);
409 else
410 {
411 if (f > 485.0f)
412 f = 485.0f;
413 }
414 return (expf((LOGTEN * 0.05f) * (f-100.0f)));
415}
359 416
LEAF/Src/leaf-mempool.c+130−67
@@ -48,33 +48,30 @@ · 47 unmodified lines
48 48
49#endif49#endif
50 50
51// This might be too low.
52#define NUM_BLOCKS 50
53
54mpool_pool_t blocks[NUM_BLOCKS];
55mpool_t leaf_pool;51mpool_t leaf_pool;
52size_t header_size;
56 53
57/**54/**
58 * private function55 * private function
59 */56 */
60static inline size_t mpool_align(size_t size);57static inline size_t mpool_align(size_t size);
61 58static inline mpool_node_t* create_node(void* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size);
59static inline void delink_node(mpool_node_t* node);
62 60
63/**61/**
64 * create memory pool62 * create memory pool
65 */63 */
66void mpool_create (char* memory, size_t size, mpool_t* pool)64void mpool_create (char* memory, size_t size, mpool_t* pool)
67{65{
68 pool->mpool = &blocks[0];66 header_size = mpool_align(sizeof(mpool_node_t));
69
70 pool->mpool->pool = (void*)memory;
71 pool->mpool->size = size;
72 pool->mpool->used = 0;
73 67
68 pool->mpool = (void*)memory;
74 pool->usize = 0;69 pool->usize = 0;
75 pool->msize = size;70 pool->msize = size;
76 71
77 for (int i = 0; i < size; i++) memory[i]=0;72 pool->head = create_node(pool->mpool, NULL, NULL, pool->msize-header_size);
73
74 for (int i = 0; i < pool->head->size; i++) memory[i+header_size]=0;
78}75}
79 76
80void leaf_pool_init(char* memory, size_t size)77void leaf_pool_init(char* memory, size_t size)
@@ -85,45 +82,61 @@ void leaf_pool_init(char* memory, size_t size) · 4 unmodified lines
85/**82/**
86 * allocate memory from memory pool83 * allocate memory from memory pool
87 */84 */
88void* mpool_alloc(size_t size, mpool_t* pool)85void* mpool_alloc(size_t asize, mpool_t* pool)
89{86{
90 pool->next += 1;87 // If the head is NULL, the mempool is full
88 if (pool->head == NULL) return NULL;
91 89
92 if (pool->next >= NUM_BLOCKS) return NULL;90 // Should we alloc the first block large enough or check all blocks and pick the one closest in size?
91 size_t size_to_alloc = mpool_align(asize);
92 mpool_node_t* node_to_alloc = pool->head;
93 93
94 mpool_pool_t* new_chunk = &blocks[pool->next];94 // Traverse the free list for a large enough block
95 new_chunk->size = mpool_align(size);95 while (node_to_alloc->size < size_to_alloc)
96 {
97 node_to_alloc = node_to_alloc->next;
98
99 // If we reach the end of the free list, there
100 // are no blocks large enough, return NULL
101 if (node_to_alloc == NULL) return NULL;
102 }
96 103
97 int idx = pool->next - 1;104 // Create a new node after the node to be allocated if there is enough space
98 for (mpool_pool_t *old_chunk = &blocks[idx]; idx >= 0; old_chunk = &blocks[--idx])105 mpool_node_t* new_node;
106 size_t leftover = node_to_alloc->size - size_to_alloc;
107 node_to_alloc->size = size_to_alloc;
108 if (leftover > header_size)
99 {109 {
100 if (old_chunk->used == 0)110 long offset = node_to_alloc - (mpool_node_t*) pool->mpool;
101 {111 offset *= sizeof(mpool_node_t);
102 if (new_chunk->size < old_chunk->size)112 offset += header_size + node_to_alloc->size;
103 {113 new_node = create_node(&pool->mpool[offset],
104 // set memory start pointer of this chunk to that of old chunk, mark new chunk used114 node_to_alloc->next,
105 new_chunk->pool = old_chunk->pool;115 node_to_alloc->prev,
106 new_chunk->used = 1;116 leftover - header_size);
107 117 }
108 // increment memory start pointer of old chunk118 else
109 char* ptr = (char*)old_chunk->pool;119 {
110 ptr += new_chunk->size;120 // Add any leftover space to the allocated node to avoid fragmentation
111 old_chunk->pool = (void*)ptr;121 node_to_alloc->size += leftover;
112 122
113 // decrement size of old chunk by size of new chunk123 new_node = node_to_alloc->next;
114 old_chunk->size -= new_chunk->size;124 }
115 125
116 // increment used size of whole mempool by size of new chunk126 // Update the head if we are allocating the first node of the free list
117 pool->usize += new_chunk->size;127 // The head will be NULL if there is no space left
118 128 if (pool->head == node_to_alloc)
119 // return memory pointer of new chunk129 {
120 return new_chunk->pool;130 pool->head = new_node;
121 }
122 }
123 }131 }
124 132
125 // if not enough space anywhere, return NULL133 // Remove the allocated node from the free list
126 return NULL;134 delink_node(node_to_alloc);
135
136 pool->usize += header_size + node_to_alloc->size;
137
138 // Return the pool of the allocated node;
139 return node_to_alloc->pool;
127}140}
128 141
129void* leaf_alloc(size_t size)142void* leaf_alloc(size_t size)
@@ -138,30 +151,50 @@ void* leaf_alloc(size_t size) · 8 unmodified lines
138 151
139void mpool_free(void* ptr, mpool_t* pool)152void mpool_free(void* ptr, mpool_t* pool)
140{153{
141 //printf("finding %p\n", ptr);154 //if (ptr < pool->mpool || ptr >= pool->mpool + pool->msize)
155 // Get the node at the freed space
156 mpool_node_t* freed_node = (mpool_node_t*) (ptr - header_size);
142 157
143 int idx = 0;158 pool->usize -= header_size + freed_node->size;
144 for (mpool_pool_t *block = &blocks[0]; idx < NUM_BLOCKS; block = &blocks[++idx])159
160 // Check each node in the list against the newly freed one to see if it's adjacent in memory
161 mpool_node_t* other_node = pool->head;
162 mpool_node_t* next_node;
163 while (other_node != NULL)
145 {164 {
146 if (block->pool == ptr)165 next_node = other_node->next;
166 // Check if a node is directly after the freed node
167 if ((long) freed_node + (header_size + freed_node->size) == (long) other_node)
147 {168 {
148 // Mark unused169 // Increase freed node's size
149 block->used = 0;170 freed_node->size += header_size + other_node->size;
150 171 // Delink the merged node
151 172 delink_node(other_node);
152 // Format to all zeros (kinda arbitrary, but possibly handy / needed)173 // Attach the merging node to the head
153 char* buff = (char*)block->pool;174 freed_node->next = pool->head;
154 for (int i = 0; i < block->size; i++)
155 {
156 buff[i] = 0;
157 }
158
159 // decrement overall pool size
160 pool->usize -= block->size;
161
162 break;
163 }175 }
176 // Check if a node is directly before the freed node
177 else if ((long) other_node + (header_size + other_node->size) == (long) freed_node)
178 {
179 // Increase the merging node's size
180 other_node->size += header_size + freed_node->size;
181 // Delink the merging node
182 delink_node(other_node);
183 // Attach the merging node to the head
184 other_node->next = pool->head;
185 // Nodes are merged
186 freed_node = other_node;
187 }
188
189 other_node = next_node;
164 }190 }
191
192 // Do this after any merging
193 pool->head = freed_node;
194
195 // Format the freed pool
196 char* freed_pool = (char*)freed_node->pool;
197 for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0;
165}198}
166 199
167void leaf_free(void* ptr)200void leaf_free(void* ptr)
@@ -174,14 +207,14 @@ size_t mpool_get_size(mpool_t* pool) · 6 unmodified lines
174 return pool->msize;207 return pool->msize;
175}208}
176 209
177size_t leaf_pool_get_size(void)210size_t mpool_get_used(mpool_t* pool)
178{211{
179 return mpool_get_size(&leaf_pool);212 return pool->usize;
180}213}
181 214
182size_t mpool_get_used(mpool_t* pool)215size_t leaf_pool_get_size(void)
183{216{
184 return pool->usize;217 return mpool_get_size(&leaf_pool);
185}218}
186 219
187size_t leaf_pool_get_used(void)220size_t leaf_pool_get_used(void)
@@ -191,7 +224,7 @@ size_t leaf_pool_get_used(void) · 3 unmodified lines
191 224
192void* leaf_pool_get_pool(void)225void* leaf_pool_get_pool(void)
193{226{
194 float* buff = (float*)leaf_pool.mpool->pool;227 float* buff = (float*)leaf_pool.mpool;
195 228
196 return buff;229 return buff;
197}230}
@@ -203,6 +236,36 @@ static inline size_t mpool_align(size_t size) { · 5 unmodified lines
203 return (size + (MPOOL_ALIGN_SIZE - 1)) & ~(MPOOL_ALIGN_SIZE - 1);236 return (size + (MPOOL_ALIGN_SIZE - 1)) & ~(MPOOL_ALIGN_SIZE - 1);
204}237}
205 238
239static inline mpool_node_t* create_node(void* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size)
240{
241 mpool_node_t* node = (mpool_node_t*)block_location;
242 node->pool = block_location + header_size;
243 node->next = next;
244 node->prev = prev;
245 node->size = size;
246
247 return node;
248}
249
250static inline void delink_node(mpool_node_t* node)
251{
252 // If there is a node after the node to remove
253 if (node->next != NULL)
254 {
255 // Close the link
256 node->next->prev = node->prev;
257 }
258 // If there is a node before the node to remove
259 if (node->prev != NULL)
260 {
261 // Close the link
262 node->prev->next = node->next;
263 }
264
265 node->next = NULL;
266 node->prev = NULL;
267}
268
206void leaf_mempool_overrun(void)269void leaf_mempool_overrun(void)
207{270{
208 271
LEAF_JUCEPlugin/Source/MyTest.cpp+7−7
@@ -42,8 +42,8 @@ void LEAFTest_init (float sampleRate, int blockSize) · 41 unmodified lines
42 tDelay_free(&delay); //most basic free test42 tDelay_free(&delay); //most basic free test
43 tDelay_init(&delay, 44100, 44100);43 tDelay_init(&delay, 44100, 44100);
44 44
45 tRetune_init(&retune, 1, 4096, 2048);45 tRetune_init(&retune, 1, 2048, 1024);
46 tAutotune_init(&autotune, 1, 4096, 2048);46 tAutotune_init(&autotune, 8, 2048, 1024);
47}47}
48 48
49float LEAFTest_tick (float input)49float LEAFTest_tick (float input)
@@ -53,9 +53,9 @@ float LEAFTest_tick (float input) · 3 unmodified lines
53 float* autotuneOut = tAutotune_tick(&autotune, sample);53 float* autotuneOut = tAutotune_tick(&autotune, sample);
54 float r1 = retuneOut[0];54 float r1 = retuneOut[0];
55 //float r2 = retuneOut[1];55 //float r2 = retuneOut[1];
56 float a1 = autotuneOut[0];56 float a1 = autotuneOut[6];
57 //float a2 = autotuneOut[1];57 float a2 = autotuneOut[7];
58 sample = a1;58 sample = a1 + a2;
59 59
60 return sample * 0.25f;60 return sample * 0.25f;
61}61}
@@ -67,11 +67,11 @@ void LEAFTest_block (void) · 5 unmodified lines
67{67{
68 float val = getSliderValue("mod freq");68 float val = getSliderValue("mod freq");
69 tRetune_setPitchFactor(&retune, val*4.0f + 0.5f, 0);69 tRetune_setPitchFactor(&retune, val*4.0f + 0.5f, 0);
70 tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 0);70 tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 7);
71 71
72 val = getSliderValue("mod depth");72 val = getSliderValue("mod depth");
73 tRetune_setPitchFactor(&retune, val*4.0f + 0.5f, 1);73 tRetune_setPitchFactor(&retune, val*4.0f + 0.5f, 1);
74 tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 1);74 tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 6);
75}75}
76 76
77void LEAFTest_controllerInput (int cnum, float cval)77void LEAFTest_controllerInput (int cnum, float cval)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t