ref: 1fdec38ec4c2fe00804f80c23583fb1f14728f78
parent: 4f70bc64d136ec816e6a8476429fb1c69be1ffa7
author: Matthew Wang <Matthew@nat-oitwireless-inside-vapornet100-10-9-155-151.princeton.edu>
date: Wed Nov 6 12:42:55 EST 2019
reworked mempool to use a linked list of free space and headers at the start of allocated regions
binary files a/.DS_Store b/.DS_Store differ
--- a/LEAF/Inc/leaf-math.h
+++ b/LEAF/Inc/leaf-math.h
@@ -128,6 +128,20 @@
// alternative implementation for abs()
// REQUIRES: 32 bit floats
float fastabs(float f);
+
+#define LOGTEN 2.302585092994
+
+float mtof(float f);
+
+float ftom(float f);
+
+float powtodb(float f);
+
+float rmstodb(float f);
+
+float dbtopow(float f);
+
+float dbtorms(float f);
//==============================================================================
--- a/LEAF/Inc/leaf-mempool.h
+++ b/LEAF/Inc/leaf-mempool.h
@@ -57,19 +57,20 @@
/**
* memory pool structure
*/
-typedef struct mpool_pool_t {
+
+// node of free list
+typedef struct mpool_node_t {
void *pool; // memory pool field
- struct mpool_pool_t *next; // next memory pool's pointer
+ struct mpool_node_t *next; // next node pointer
+ struct mpool_node_t *prev; // prev node pointer
size_t size;
- int used; // used flag
-} mpool_pool_t;
+} mpool_node_t;
typedef struct mpool_t {
- mpool_pool_t *head; // memory pool's head
- size_t usize; // used pool size of current pool
- size_t msize; // max pool size of current pool
- mpool_pool_t *mpool; // memory pool
- int next;
+ void* mpool; // start of the mpool
+ size_t usize; // used size of the pool
+ size_t msize; // max size of the pool
+ mpool_node_t* head; // first node of memory pool free list
} mpool_t;
void mpool_create (char* memory, size_t size, mpool_t* pool);
@@ -79,7 +80,6 @@
size_t mpool_get_size(mpool_t* pool);
size_t mpool_get_used(mpool_t* pool);
-
void leaf_pool_init(char* memory, size_t size);
--- a/LEAF/Src/leaf-effects.c
+++ b/LEAF/Src/leaf-effects.c
@@ -779,7 +779,9 @@
tSOLAD_setPeriod(&ps->sola, period);
- ps->pitchFactor = period*freq*leaf.invSampleRate;
+ if (period != 0) ps->pitchFactor = period*freq*leaf.invSampleRate;
+ else ps->pitchFactor = 1.0f;
+
tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
--- a/LEAF/Src/leaf-envelopes.c
+++ b/LEAF/Src/leaf-envelopes.c
@@ -23,67 +23,6 @@
#endif
-#define LOGTEN 2.302585092994
-
-float mtof(float f)
-{
- if (f <= -1500.0f) return(0);
- else if (f > 1499.0f) return(mtof(1499.0f));
- else return (8.17579891564f * expf(0.0577622650f * f));
-}
-
-float ftom(float f)
-{
- return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
-}
-
-float powtodb(float f)
-{
- if (f <= 0) return (0);
- else
- {
- float val = 100 + 10.f/LOGTEN * logf(f);
- return (val < 0 ? 0 : val);
- }
-}
-
-float rmstodb(float f)
-{
- if (f <= 0) return (0);
- else
- {
- float val = 100 + 20.f/LOGTEN * log(f);
- return (val < 0 ? 0 : val);
- }
-}
-
-float dbtopow(float f)
-{
- if (f <= 0)
- return(0);
- else
- {
- if (f > 870.0f)
- f = 870.0f;
- return (expf((LOGTEN * 0.1f) * (f-100.0f)));
- }
-}
-
-float dbtorms(float f)
-{
- if (f <= 0)
- return(0);
- else
- {
- if (f > 485.0f)
- f = 485.0f;
- }
- return (expf((LOGTEN * 0.05f) * (f-100.0f)));
-}
-
-
-
-
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
void tEnvelope_init(tEnvelope* const env, float attack, float decay, oBool loop)
{
--- a/LEAF/Src/leaf-math.c
+++ b/LEAF/Src/leaf-math.c
@@ -356,4 +356,61 @@
return out;
}
+#define LOGTEN 2.302585092994
+
+float mtof(float f)
+{
+ if (f <= -1500.0f) return(0);
+ else if (f > 1499.0f) return(mtof(1499.0f));
+ else return (8.17579891564f * expf(0.0577622650f * f));
+}
+
+float ftom(float f)
+{
+ return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
+}
+
+float powtodb(float f)
+{
+ if (f <= 0) return (0);
+ else
+ {
+ float val = 100 + 10.f/LOGTEN * logf(f);
+ return (val < 0 ? 0 : val);
+ }
+}
+
+float rmstodb(float f)
+{
+ if (f <= 0) return (0);
+ else
+ {
+ float val = 100 + 20.f/LOGTEN * log(f);
+ return (val < 0 ? 0 : val);
+ }
+}
+
+float dbtopow(float f)
+{
+ if (f <= 0)
+ return(0);
+ else
+ {
+ if (f > 870.0f)
+ f = 870.0f;
+ return (expf((LOGTEN * 0.1f) * (f-100.0f)));
+ }
+}
+
+float dbtorms(float f)
+{
+ if (f <= 0)
+ return(0);
+ else
+ {
+ if (f > 485.0f)
+ f = 485.0f;
+ }
+ return (expf((LOGTEN * 0.05f) * (f-100.0f)));
+}
--- a/LEAF/Src/leaf-mempool.c
+++ b/LEAF/Src/leaf-mempool.c
@@ -48,33 +48,30 @@
#endif
-// This might be too low.
-#define NUM_BLOCKS 50
-
-mpool_pool_t blocks[NUM_BLOCKS];
mpool_t leaf_pool;
+size_t header_size;
/**
* private function
*/
static inline size_t mpool_align(size_t size);
+static inline mpool_node_t* create_node(void* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size);
+static inline void delink_node(mpool_node_t* node);
-
/**
* create memory pool
*/
void mpool_create (char* memory, size_t size, mpool_t* pool)
{
- pool->mpool = &blocks[0];
+ header_size = mpool_align(sizeof(mpool_node_t));
- pool->mpool->pool = (void*)memory;
- pool->mpool->size = size;
- pool->mpool->used = 0;
-
+ pool->mpool = (void*)memory;
pool->usize = 0;
pool->msize = size;
- for (int i = 0; i < size; i++) memory[i]=0;
+ pool->head = create_node(pool->mpool, NULL, NULL, pool->msize-header_size);
+
+ for (int i = 0; i < pool->head->size; i++) memory[i+header_size]=0;
}
void leaf_pool_init(char* memory, size_t size)
@@ -85,45 +82,61 @@
/**
* allocate memory from memory pool
*/
-void* mpool_alloc(size_t size, mpool_t* pool)
+void* mpool_alloc(size_t asize, mpool_t* pool)
{
- pool->next += 1;
+ // If the head is NULL, the mempool is full
+ if (pool->head == NULL) return NULL;
- if (pool->next >= NUM_BLOCKS) return NULL;
+ // Should we alloc the first block large enough or check all blocks and pick the one closest in size?
+ size_t size_to_alloc = mpool_align(asize);
+ mpool_node_t* node_to_alloc = pool->head;
- mpool_pool_t* new_chunk = &blocks[pool->next];
- new_chunk->size = mpool_align(size);
+ // Traverse the free list for a large enough block
+ while (node_to_alloc->size < size_to_alloc)
+ {
+ node_to_alloc = node_to_alloc->next;
+
+ // If we reach the end of the free list, there
+ // are no blocks large enough, return NULL
+ if (node_to_alloc == NULL) return NULL;
+ }
- int idx = pool->next - 1;
- for (mpool_pool_t *old_chunk = &blocks[idx]; idx >= 0; old_chunk = &blocks[--idx])
+ // Create a new node after the node to be allocated if there is enough space
+ mpool_node_t* new_node;
+ size_t leftover = node_to_alloc->size - size_to_alloc;
+ node_to_alloc->size = size_to_alloc;
+ if (leftover > header_size)
{
- if (old_chunk->used == 0)
- {
- if (new_chunk->size < old_chunk->size)
- {
- // set memory start pointer of this chunk to that of old chunk, mark new chunk used
- new_chunk->pool = old_chunk->pool;
- new_chunk->used = 1;
-
- // increment memory start pointer of old chunk
- char* ptr = (char*)old_chunk->pool;
- ptr += new_chunk->size;
- old_chunk->pool = (void*)ptr;
-
- // decrement size of old chunk by size of new chunk
- old_chunk->size -= new_chunk->size;
-
- // increment used size of whole mempool by size of new chunk
- pool->usize += new_chunk->size;
-
- // return memory pointer of new chunk
- return new_chunk->pool;
- }
- }
+ long offset = node_to_alloc - (mpool_node_t*) pool->mpool;
+ offset *= sizeof(mpool_node_t);
+ offset += header_size + node_to_alloc->size;
+ new_node = create_node(&pool->mpool[offset],
+ node_to_alloc->next,
+ node_to_alloc->prev,
+ leftover - header_size);
}
+ else
+ {
+ // Add any leftover space to the allocated node to avoid fragmentation
+ node_to_alloc->size += leftover;
+
+ new_node = node_to_alloc->next;
+ }
- // if not enough space anywhere, return NULL
- return NULL;
+ // Update the head if we are allocating the first node of the free list
+ // The head will be NULL if there is no space left
+ if (pool->head == node_to_alloc)
+ {
+ pool->head = new_node;
+ }
+
+ // Remove the allocated node from the free list
+ delink_node(node_to_alloc);
+
+ pool->usize += header_size + node_to_alloc->size;
+
+ // Return the pool of the allocated node;
+ return node_to_alloc->pool;
}
void* leaf_alloc(size_t size)
@@ -138,30 +151,50 @@
void mpool_free(void* ptr, mpool_t* pool)
{
- //printf("finding %p\n", ptr);
+ //if (ptr < pool->mpool || ptr >= pool->mpool + pool->msize)
+ // Get the node at the freed space
+ mpool_node_t* freed_node = (mpool_node_t*) (ptr - header_size);
- int idx = 0;
- for (mpool_pool_t *block = &blocks[0]; idx < NUM_BLOCKS; block = &blocks[++idx])
+ pool->usize -= header_size + freed_node->size;
+
+ // Check each node in the list against the newly freed one to see if it's adjacent in memory
+ mpool_node_t* other_node = pool->head;
+ mpool_node_t* next_node;
+ while (other_node != NULL)
{
- if (block->pool == ptr)
+ next_node = other_node->next;
+ // Check if a node is directly after the freed node
+ if ((long) freed_node + (header_size + freed_node->size) == (long) other_node)
{
- // Mark unused
- block->used = 0;
-
-
- // Format to all zeros (kinda arbitrary, but possibly handy / needed)
- char* buff = (char*)block->pool;
- for (int i = 0; i < block->size; i++)
- {
- buff[i] = 0;
- }
-
- // decrement overall pool size
- pool->usize -= block->size;
-
- break;
+ // Increase freed node's size
+ freed_node->size += header_size + other_node->size;
+ // Delink the merged node
+ delink_node(other_node);
+ // Attach the merging node to the head
+ freed_node->next = pool->head;
}
+ // Check if a node is directly before the freed node
+ else if ((long) other_node + (header_size + other_node->size) == (long) freed_node)
+ {
+ // Increase the merging node's size
+ other_node->size += header_size + freed_node->size;
+ // Delink the merging node
+ delink_node(other_node);
+ // Attach the merging node to the head
+ other_node->next = pool->head;
+ // Nodes are merged
+ freed_node = other_node;
+ }
+
+ other_node = next_node;
}
+
+ // Do this after any merging
+ pool->head = freed_node;
+
+ // Format the freed pool
+ char* freed_pool = (char*)freed_node->pool;
+ for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0;
}
void leaf_free(void* ptr)
@@ -174,14 +207,14 @@
return pool->msize;
}
-size_t leaf_pool_get_size(void)
+size_t mpool_get_used(mpool_t* pool)
{
- return mpool_get_size(&leaf_pool);
+ return pool->usize;
}
-size_t mpool_get_used(mpool_t* pool)
+size_t leaf_pool_get_size(void)
{
- return pool->usize;
+ return mpool_get_size(&leaf_pool);
}
size_t leaf_pool_get_used(void)
@@ -191,7 +224,7 @@
void* leaf_pool_get_pool(void)
{
- float* buff = (float*)leaf_pool.mpool->pool;
+ float* buff = (float*)leaf_pool.mpool;
return buff;
}
@@ -201,6 +234,36 @@
*/
static inline size_t mpool_align(size_t size) {
return (size + (MPOOL_ALIGN_SIZE - 1)) & ~(MPOOL_ALIGN_SIZE - 1);
+}
+
+static inline mpool_node_t* create_node(void* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size)
+{
+ mpool_node_t* node = (mpool_node_t*)block_location;
+ node->pool = block_location + header_size;
+ node->next = next;
+ node->prev = prev;
+ node->size = size;
+
+ return node;
+}
+
+static inline void delink_node(mpool_node_t* node)
+{
+ // If there is a node after the node to remove
+ if (node->next != NULL)
+ {
+ // Close the link
+ node->next->prev = node->prev;
+ }
+ // If there is a node before the node to remove
+ if (node->prev != NULL)
+ {
+ // Close the link
+ node->prev->next = node->next;
+ }
+
+ node->next = NULL;
+ node->prev = NULL;
}
void leaf_mempool_overrun(void)
--- a/LEAF_JUCEPlugin/Source/MyTest.cpp
+++ b/LEAF_JUCEPlugin/Source/MyTest.cpp
@@ -42,8 +42,8 @@
tDelay_free(&delay); //most basic free test
tDelay_init(&delay, 44100, 44100);
- tRetune_init(&retune, 1, 4096, 2048);
- tAutotune_init(&autotune, 1, 4096, 2048);
+ tRetune_init(&retune, 1, 2048, 1024);
+ tAutotune_init(&autotune, 8, 2048, 1024);
}
float LEAFTest_tick (float input)
@@ -53,9 +53,9 @@
float* autotuneOut = tAutotune_tick(&autotune, sample);
float r1 = retuneOut[0];
//float r2 = retuneOut[1];
- float a1 = autotuneOut[0];
- //float a2 = autotuneOut[1];
- sample = a1;
+ float a1 = autotuneOut[6];
+ float a2 = autotuneOut[7];
+ sample = a1 + a2;
return sample * 0.25f;
}
@@ -67,11 +67,11 @@
{
float val = getSliderValue("mod freq");
tRetune_setPitchFactor(&retune, val*4.0f + 0.5f, 0);
- tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 0);
+ tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 7);
val = getSliderValue("mod depth");
tRetune_setPitchFactor(&retune, val*4.0f + 0.5f, 1);
- tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 1);
+ tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 6);
}
void LEAFTest_controllerInput (int cnum, float cval)