1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/*
* Komposter
*
* Copyright (c) 2010 Noora Halme et al. (see AUTHORS)
*
* This code is licensed under the GNU General Public
* License version 2. See LICENSE for full text.
*
* Memory management for module buffers
*
*/
#include "buffermm.h"
/*
memory management for keeping count on what buffers have been allocated and if they are still in use
eg. delay module. when the buffer is no longer needed and must be freed?
1. the module is deleted from the synthesizer -> all channels using the synth must release the memory
2. the synthesizer on a channel is changed -> this channel must release the memory
3. a new synthesizer is loaded from disk (see first point)
a garbage collector will scan the whole entry table and check that all parameters recorded match those
currently active. with cases above;
1/3. modtype will not match with mod-array -> synth has changed. release the buffer and set localdata for this voice to zero
2. synth will not match with seq_synth -> channel uses different synth. release and set localdata to zero.
localdata must be initialized to zero or there will be invalid pointer references left and right! also, when
deleting modules or changing/loading synths, the localdata for all involved voices must be reset to zero. the
garbage collector takes care of this, so calling it after each operation should keep things in check.
the buffer pointer must be stored on the first dword in the localdata on each module which uses buffers!
all in all - this is a pretty big mess and there has to be a better way to handle this. :)
*/
// from audio.c
extern float localdata[MAX_CHANNELS][MAX_MODULES][16];
// from synthesizer.c
extern synthmodule mod[MAX_SYNTH][MAX_MODULES];
// from sequencer.c
extern int seq_synth[MAX_CHANNELS]; // which synth assigned to each channel
typedef struct {
void *ptr;
unsigned long bytes;
int voice;
int synth;
int module;
int modtype;
} kmm_mement;
kmm_mement kmmtable[KMM_ENTRIES];
void kmm_init(void)
{
int i;
for(i=0;i<KMM_ENTRIES;i++) {
kmmtable[i].ptr=NULL;
kmmtable[i].bytes=0;
kmmtable[i].voice=0xfe;
kmmtable[i].synth=0xfe;
kmmtable[i].module=0xfe;
kmmtable[i].modtype=0xfe;
}
}
void *kmm_alloc(unsigned long len, int voice, int synth, int module, int modtype)
{
int i;
void *buffer;
// buffer=calloc(len, sizeof(unsigned long));
buffer=malloc(len*sizeof(u32));
if (buffer) {
for(i=0;i<KMM_ENTRIES;i++) {
if (!kmmtable[i].ptr) {
kmmtable[i].ptr=buffer;
kmmtable[i].bytes=len*sizeof(u32);
kmmtable[i].voice=voice;
kmmtable[i].synth=synth;
kmmtable[i].module=module;
kmmtable[i].modtype=modtype;
printf("kmm: module data buffer allocated from %08lx - len %d (%d bytes), v %d s %d mi %d mt %d\n",
(unsigned long)buffer, len, len*sizeof(u32), voice,synth,module,modtype);
return buffer;
}
}
}
return 0; // table is full
}
void kmm_gcollect(void)
{
int i;
// scan the kmm table and free any buffers which are no longer being used
for(i=0;i<KMM_ENTRIES;i++) {
if (kmmtable[i].ptr) {
if (seq_synth[kmmtable[i].voice] != kmmtable[i].synth) {
// channel no longer uses this synth -> release the buffer
// printf("kmm: synth changed, releasing module data from %08lx\n", (unsigned long)kmmtable[i].ptr);
printf("kmm: synth changed, releasing module data from %08lx (v %d s %d mi %d mt %d)\n",
(unsigned long)kmmtable[i].ptr, kmmtable[i].voice, kmmtable[i].synth, kmmtable[i].module, kmmtable[i].modtype);
free(kmmtable[i].ptr);
memset(&localdata[kmmtable[i].voice][kmmtable[i].module][0], 0, sizeof(void*));
// localdata[kmmtable[i].voice][kmmtable[i].module][0]=0;
kmmtable[i].ptr=NULL;
continue;
}
if (kmmtable[i].modtype != mod[kmmtable[i].synth][kmmtable[i].module].type) {
// module type has changed or it has been deleted -> release
// printf("kmm: modtype changed, releasing module data from %08lx\n", (unsigned long)kmmtable[i].ptr);
printf("kmm: modtype changed, releasing module data from %08lx (v %d s %d mi %d mt %d)\n",
(unsigned long)kmmtable[i].ptr, kmmtable[i].voice, kmmtable[i].synth, kmmtable[i].module, kmmtable[i].modtype);
free(kmmtable[i].ptr);
memset(&localdata[kmmtable[i].voice][kmmtable[i].module][0], 0, sizeof(void*));
// localdata[kmmtable[i].voice][kmmtable[i].module][0]=0;
kmmtable[i].ptr=NULL;
continue;
}
}
}
}
|