forked from surge-synthesizer/surge
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Memory Reuse for allocating oscillators: String (surge-synthesizer#5264)
This commit gives an API which allows us to reuse rather than reallocate the memory buffers that objects need at play time. Right now it only deals with the string oscillator and still does 'extra' allocation on the audio thread, but has a reasonable pre-allocate and re-use strategy. In the future the overflow allocs could be off thread but for now it's a simple save and reuse approach. Thanks to Luna for a review, and also glad I added that test! Closes surge-synthesizer#4840
- Loading branch information
Showing
10 changed files
with
294 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
** Surge Synthesizer is Free and Open Source Software | ||
** | ||
** Surge is made available under the Gnu General Public License, v3.0 | ||
** https://www.gnu.org/licenses/gpl-3.0.en.html | ||
** | ||
** Copyright 2004-2021 by various individuals as described by the Git transaction log | ||
** | ||
** All source at: https://github.com/surge-synthesizer/surge.git | ||
** | ||
** Surge was a commercial product from 2004-2018, with Copyright and ownership | ||
** in that period held by Claes Johanson at Vember Audio. Claes made Surge | ||
** open source in September 2018. | ||
*/ | ||
|
||
#ifndef SURGE_MEMORYPOOL_H | ||
#define SURGE_MEMORYPOOL_H | ||
|
||
#include <unordered_set> | ||
#include <iostream> | ||
|
||
namespace Surge | ||
{ | ||
namespace Memory | ||
{ | ||
// pre-alloc must be at least one | ||
template <typename T, size_t preAlloc, size_t growBy, size_t capacity = 16384> struct MemoryPool | ||
{ | ||
MemoryPool() | ||
{ | ||
while (position < preAlloc) | ||
refreshPool(); | ||
} | ||
~MemoryPool() | ||
{ | ||
std::cout << "Cleaning Up MemProol with " << position << std::endl; | ||
for (size_t i = 0; i < position; ++i) | ||
delete pool[i]; | ||
} | ||
T *getItem() | ||
{ | ||
if (position == 0) | ||
{ | ||
refreshPool(); | ||
} | ||
auto q = pool[position - 1]; | ||
pool[position - 1] = nullptr; // just to flag bugs | ||
position--; | ||
return q; | ||
} | ||
void returnItem(T *t) | ||
{ | ||
pool[position] = t; | ||
position++; | ||
} | ||
void refreshPool() | ||
{ | ||
// In an ideal world, this grow would be off thread. | ||
// For XT 1 leave it here and have a reasonable prealloc | ||
assert(position < (growBy + capacity)); | ||
for (size_t i = 0; i < growBy; ++i) | ||
{ | ||
pool[position] = new T(); | ||
position++; | ||
} | ||
} | ||
|
||
void setupPoolToSize(size_t upTo) | ||
{ | ||
while (position < upTo) | ||
{ | ||
pool[position] = new T(); | ||
position++; | ||
} | ||
} | ||
|
||
void returnToPreAllocSize() | ||
{ | ||
while (position > preAlloc) | ||
{ | ||
delete pool[position - 1]; | ||
pool[position - 1] = nullptr; | ||
position--; | ||
} | ||
} | ||
|
||
std::array<T *, capacity> pool; | ||
|
||
/* | ||
* Position is the location of the next *free* slot. That is | ||
* the pointer should be returned to position, and retrieved from | ||
* position -1. position == 0 is a sentinel to rebuild. | ||
*/ | ||
size_t position{0}; | ||
}; | ||
} // namespace Memory | ||
} // namespace Surge | ||
|
||
#endif // SURGE_MEMORYPOOL_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
** Surge Synthesizer is Free and Open Source Software | ||
** | ||
** Surge is made available under the Gnu General Public License, v3.0 | ||
** https://www.gnu.org/licenses/gpl-3.0.en.html | ||
** | ||
** Copyright 2004-2021 by various individuals as described by the Git transaction log | ||
** | ||
** All source at: https://github.com/surge-synthesizer/surge.git | ||
** | ||
** Surge was a commercial product from 2004-2018, with Copyright and ownership | ||
** in that period held by Claes Johanson at Vember Audio. Claes made Surge | ||
** open source in September 2018. | ||
*/ | ||
|
||
#ifndef SURGE_SURGEMEMORYPOOLS_H | ||
#define SURGE_SURGEMEMORYPOOLS_H | ||
|
||
#include "SurgeStorage.h" | ||
#include "MemoryPool.h" | ||
#include "SSESincDelayLine.h" | ||
|
||
namespace Surge | ||
{ | ||
namespace Memory | ||
{ | ||
struct SurgeMemoryPools | ||
{ | ||
/* | ||
* The largest number of oscillator instances of a particlar | ||
* type are scenes * oscs * max voices, but add some pad | ||
*/ | ||
static constexpr int maxosc = n_scenes * n_oscs * (MAX_VOICES + 8); | ||
|
||
/* | ||
* The string needs 2 delay lines per oscillator | ||
*/ | ||
MemoryPool<SSESincDelayLine<16384>, 8, 4, 2 * maxosc + 100> stringDelayLines; | ||
void resetAllPools(SurgeStorage *storage) { resetOscillatorPools(storage); } | ||
void resetOscillatorPools(SurgeStorage *storage) | ||
{ | ||
bool hasString{false}, hasTwist{false}; | ||
int nString{0}; | ||
for (int s = 0; s < n_scenes; ++s) | ||
{ | ||
for (int os = 0; os < n_oscs; ++os) | ||
{ | ||
auto ot = storage->getPatch().scene[s].osc[os].type.val.i; | ||
|
||
if (ot == ot_string) | ||
{ | ||
hasString = true; | ||
nString++; | ||
} | ||
hasTwist |= (ot == ot_twist); | ||
} | ||
} | ||
|
||
if (hasString) | ||
{ | ||
int maxUsed = nString * 2 * storage->getPatch().polylimit.val.i; | ||
stringDelayLines.setupPoolToSize((int)(maxUsed * 0.5)); | ||
} | ||
else | ||
{ | ||
stringDelayLines.returnToPreAllocSize(); | ||
} | ||
} | ||
}; | ||
|
||
} // namespace Memory | ||
} // namespace Surge | ||
#endif // SURGE_SURGEMEMORYPOOLS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.