-
Notifications
You must be signed in to change notification settings - Fork 12
/
buffermm.c
145 lines (109 loc) · 4.48 KB
/
buffermm.c
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;
}
}
}
}