Skip to content

Commit 5c9c192

Browse files
committed
Ignore this. A LOT of stuff is happening right now-
1 parent 2894f83 commit 5c9c192

File tree

15 files changed

+4061
-257
lines changed

15 files changed

+4061
-257
lines changed

docs/NotePool.md

Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
# NotePool Documentation
2+
3+
## Overview
4+
5+
The `NotePool` class is a high-performance object pooling system designed specifically for managing `Note` objects in the Mixtape Engine. Instead of constantly creating and destroying note objects (which can cause memory allocation overhead and garbage collection spikes), the pool maintains a cache of pre-created notes that can be reused.
6+
7+
## Benefits
8+
9+
- **Performance**: Reduces memory allocations and garbage collection overhead
10+
- **Consistency**: Eliminates frame rate drops caused by frequent object creation/destruction
11+
- **Memory Efficiency**: Reuses existing objects instead of creating new ones
12+
- **Statistics**: Provides detailed metrics about pool usage and efficiency
13+
14+
## Basic Usage
15+
16+
### 1. Create a Note Pool
17+
18+
```haxe
19+
var notePool = new NotePool();
20+
```
21+
22+
### 2. Get Notes from the Pool
23+
24+
```haxe
25+
// Get a regular note
26+
var note = notePool.getNote(strumTime, noteData);
27+
28+
// Get a sustain note
29+
var sustainNote = notePool.getNote(strumTime, noteData, prevNote, true);
30+
31+
// Get a note for the editor
32+
var editorNote = notePool.getNote(strumTime, noteData, null, false, true);
33+
```
34+
35+
### 3. Return Notes to the Pool
36+
37+
```haxe
38+
// Return a single note
39+
notePool.returnNote(note);
40+
41+
// Return multiple notes
42+
notePool.returnNotes([note1, note2, note3]);
43+
44+
// Clear all active notes
45+
notePool.clearActiveNotes();
46+
```
47+
48+
## Configuration
49+
50+
### Pool Size Settings
51+
52+
```haxe
53+
// Adjust maximum pool size (default: 200)
54+
NotePool.MAX_POOL_SIZE = 300;
55+
56+
// Adjust minimum pool size (default: 50)
57+
NotePool.MIN_POOL_SIZE = 100;
58+
```
59+
60+
### Enable/Disable Pool
61+
62+
```haxe
63+
// Disable the pool (falls back to normal note creation)
64+
notePool.setEnabled(false);
65+
66+
// Re-enable the pool
67+
notePool.setEnabled(true);
68+
```
69+
70+
## Integration Examples
71+
72+
### PlayState Integration
73+
74+
```haxe
75+
class PlayState extends MusicBeatState
76+
{
77+
private var notePool:NotePool;
78+
private var activeNotes:Array<Note>;
79+
80+
override public function create():Void
81+
{
82+
super.create();
83+
84+
// Initialize note pool
85+
notePool = new NotePool();
86+
activeNotes = [];
87+
}
88+
89+
private function spawnNote(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false):Note
90+
{
91+
// Use pool instead of creating new note
92+
var note = notePool.getNote(strumTime, noteData, prevNote, sustainNote);
93+
activeNotes.push(note);
94+
notesGroup.add(note);
95+
return note;
96+
}
97+
98+
private function removeNote(note:Note):Void
99+
{
100+
activeNotes.remove(note);
101+
notesGroup.remove(note);
102+
notePool.returnNote(note); // Return to pool instead of destroying
103+
}
104+
105+
override public function destroy():Void
106+
{
107+
if (notePool != null)
108+
{
109+
notePool.destroy();
110+
notePool = null;
111+
}
112+
super.destroy();
113+
}
114+
}
115+
```
116+
117+
### Chart Editor Integration
118+
119+
```haxe
120+
class ChartingState extends MusicBeatState
121+
{
122+
private var notePool:NotePool;
123+
124+
override public function create():Void
125+
{
126+
super.create();
127+
notePool = new NotePool();
128+
}
129+
130+
private function createChartNote(strumTime:Float, noteData:Int):Note
131+
{
132+
// Create note for editor
133+
var note = notePool.getNote(strumTime, noteData, null, false, true);
134+
return note;
135+
}
136+
137+
private function deleteChartNote(note:Note):Void
138+
{
139+
// Return to pool instead of destroying
140+
notePool.returnNote(note);
141+
}
142+
}
143+
```
144+
145+
## Performance Monitoring
146+
147+
### Get Pool Statistics
148+
149+
```haxe
150+
var stats = notePool.getStats();
151+
trace("Total created: " + stats.totalCreated);
152+
trace("Total reused: " + stats.totalReused);
153+
trace("Active notes: " + stats.activeNotes);
154+
trace("Pool efficiency: " + stats.efficiency + "%");
155+
```
156+
157+
### Monitor Pool Usage
158+
159+
```haxe
160+
// Check active note count
161+
var activeCount = notePool.getActiveCount();
162+
163+
// Check pooled note count
164+
var pooledCount = notePool.getPooledCount();
165+
166+
// Monitor efficiency
167+
var efficiency = (stats.totalReused / (stats.totalCreated + stats.totalReused)) * 100;
168+
```
169+
170+
## Best Practices
171+
172+
### 1. Always Return Notes
173+
174+
```haxe
175+
// ✅ Good
176+
var note = notePool.getNote(strumTime, noteData);
177+
// ... use note ...
178+
notePool.returnNote(note);
179+
180+
// ❌ Bad - creates memory leak
181+
var note = notePool.getNote(strumTime, noteData);
182+
// ... use note ...
183+
// Never returned to pool
184+
```
185+
186+
### 2. Clear Pool When Changing Songs
187+
188+
```haxe
189+
override public function switchSong():Void
190+
{
191+
notePool.clearActiveNotes();
192+
super.switchSong();
193+
}
194+
```
195+
196+
### 3. Handle Sustain Notes Properly
197+
198+
```haxe
199+
// Create sustain chain
200+
var headNote = notePool.getNote(strumTime, noteData);
201+
var sustainNote = notePool.getNote(strumTime + 100, noteData, headNote, true);
202+
var tailNote = notePool.getNote(strumTime + 200, noteData, sustainNote, true);
203+
204+
// Return in reverse order
205+
notePool.returnNote(tailNote);
206+
notePool.returnNote(sustainNote);
207+
notePool.returnNote(headNote);
208+
```
209+
210+
### 4. Monitor Pool Efficiency
211+
212+
```haxe
213+
#if debug
214+
var stats = notePool.getStats();
215+
if (stats.efficiency < 50) {
216+
trace("Warning: Pool efficiency is low (" + stats.efficiency + "%)");
217+
}
218+
#end
219+
```
220+
221+
## Troubleshooting
222+
223+
### Common Issues
224+
225+
1. **Memory Leaks**: Make sure to always return notes to the pool
226+
2. **Performance Issues**: Check if pool sizes are appropriate for your use case
227+
3. **Sustain Note Problems**: Ensure sustain notes are properly linked and returned
228+
229+
### Debug Mode
230+
231+
```haxe
232+
#if debug
233+
// Enable detailed logging
234+
notePool.enabled = true;
235+
var stats = notePool.getStats();
236+
trace("Pool stats: " + stats);
237+
#end
238+
```
239+
240+
## Technical Details
241+
242+
### Pool Implementation
243+
244+
The `NotePool` uses two separate pools:
245+
- **Regular Notes**: For tap notes and note heads
246+
- **Sustain Notes**: For sustain tails and holds
247+
248+
### Memory Management
249+
250+
- Notes are reset to default values when returned to pool
251+
- Automatic cleanup of references to prevent memory leaks
252+
- Configurable pool sizes to balance memory usage vs. performance
253+
254+
### Thread Safety
255+
256+
The pool is designed for single-threaded use. Do not access from multiple threads simultaneously.
257+
258+
## API Reference
259+
260+
### Constructor
261+
- `new NotePool()`: Creates a new note pool with default settings
262+
263+
### Methods
264+
- `getNote(strumTime, noteData, prevNote?, sustainNote?, inEditor?, createdFrom?)`: Get a note from the pool
265+
- `returnNote(note)`: Return a note to the pool
266+
- `returnNotes(notes)`: Return multiple notes to the pool
267+
- `createNotesFromTemplates(templates, inEditor?, createdFrom?)`: Create notes from templates
268+
- `createNoteFromTemplate(template, prevNote?, inEditor?, createdFrom?)`: Create a single note from template
269+
- `prePopulateFromTemplates(templates)`: Pre-populate pool with templated notes
270+
- `clearActiveNotes()`: Clear all active notes and return them to the pool
271+
- `getStats()`: Get pool statistics
272+
- `getExtendedStats()`: Get extended pool statistics with utilization info
273+
- `setEnabled(enabled)`: Enable or disable the pool
274+
- `getActiveCount()`: Get number of active notes
275+
- `getPooledCount()`: Get number of pooled notes
276+
- `destroy()`: Clean up the pool
277+
278+
### NoteTemplate Methods
279+
- `new NoteTemplate(strumTime, noteData, sustainNote?, noteType?, mustPress?)`: Create a new template
280+
- `setCustomData(key, value)`: Set custom data for the template
281+
- `setEventData(eventName, val1?, val2?)`: Set event data for the template
282+
- `applyToNote(note)`: Apply template properties to a note
283+
- `clone()`: Create a copy of the template
284+
285+
### AbstractNoteArray Methods
286+
- `new AbstractNoteArray(notes?)`: Create a new note array
287+
- `add(template)`: Add a template to the array
288+
- `addAll(templates)`: Add multiple templates to the array
289+
- `remove(template)`: Remove a template from the array
290+
- `clear()`: Clear all templates from the array
291+
- `getNext()`: Get and remove the next template
292+
- `peekNext()`: Look at the next template without removing it
293+
- `getByType(noteType)`: Get all templates of a specific type
294+
- `getByTimeRange(startTime, endTime)`: Get templates within a time range
295+
- `sortByTime()`: Sort templates by strum time
296+
- `createNotes(pool, inEditor?, createdFrom?)`: Create actual notes from templates
297+
- `isEmpty()`: Check if the array is empty
298+
- `get(index)`: Get template at index
299+
- `set(index, template)`: Set template at index
300+
301+
## Advanced Features
302+
303+
### NoteTemplate System
304+
305+
The `NoteTemplate` class allows you to create reusable note configurations that can be applied to notes from the pool:
306+
307+
```haxe
308+
// Create a template for a hurt note
309+
var hurtTemplate = new NoteTemplate(1000, 0, false, "Hurt Note", true)
310+
.setCustomData('hitCausesMiss', true)
311+
.setCustomData('lowPriority', true);
312+
313+
// Create a note from the template
314+
var hurtNote = notePool.createNoteFromTemplate(hurtTemplate);
315+
```
316+
317+
### AbstractNoteArray
318+
319+
The `AbstractNoteArray` provides a powerful way to work with collections of note templates:
320+
321+
```haxe
322+
// Create an array of note templates
323+
var templates:AbstractNoteArray = new AbstractNoteArray();
324+
325+
// Add templates
326+
templates.add(new NoteTemplate(0, 0, false, null, true));
327+
templates.add(new NoteTemplate(500, 1, false, null, true));
328+
templates.add(new NoteTemplate(1000, 2, false, null, true));
329+
330+
// Convert existing notes to templates
331+
var existingNotes:Array<Note> = [note1, note2, note3];
332+
var convertedTemplates:AbstractNoteArray = existingNotes;
333+
334+
// Create notes from templates
335+
var createdNotes = notePool.createNotesFromTemplates(templates);
336+
```
337+
338+
### Template Features
339+
340+
#### Custom Data
341+
```haxe
342+
var template = new NoteTemplate(1000, 0, false, "Mine Note", true)
343+
.setCustomData('isMine', true)
344+
.setCustomData('specialNote', true)
345+
.setCustomData('ignoreMiss', true);
346+
```
347+
348+
#### Event Data
349+
```haxe
350+
var eventTemplate = new NoteTemplate(2000, 1, false, null, true)
351+
.setEventData('Camera Focus', 'dad', '');
352+
```
353+
354+
#### Template Filtering
355+
```haxe
356+
// Get templates by type
357+
var hurtNotes = templates.getByType("Hurt Note");
358+
359+
// Get templates in time range
360+
var earlyNotes = templates.getByTimeRange(0, 2000);
361+
362+
// Sort by time
363+
templates.sortByTime();
364+
```
365+
366+
### Pattern Creation
367+
368+
Create complex note patterns using templates:
369+
370+
```haxe
371+
// Arpeggio pattern
372+
var arpeggio = createArpeggiPattern(startTime, 16);
373+
374+
// Sustain chain
375+
var sustain = createSustainChain(startTime, noteData, 2000);
376+
377+
// Chord
378+
var chord = createChord(startTime, [0, 1, 2, 3]);
379+
```

0 commit comments

Comments
 (0)