shithub: leaf

Download patch

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)