sclass PianoSampler { double sampleRate = 48000; double currentSample; IAudioSample audio; persistable class Oscillator extends HasKey { double currentPeriodStart; // all recorded intensities new TreeMap> intensities; *(Frequency f) { super(f); } Frequency frequency() { ret key(); } double interval() { ret frequency().interval(); } void record(DoubleRange r, Channels c) { intensities.put(r, c); } void measure { double end = phase360(); AudioHaarFeature haar = new(audio, start, end); val value = haar.get(channel); record(doubleRange(start, end), value); } void relocate(double time) { currentPeriodStart = time; completionsForSample.put(phase360(), this); } double phase90() { ret currentPeriodStart + interval()*.25; } double phase180() { ret currentPeriodStart + interval()*.5; } double phase270() { ret currentPeriodStart + interval()*.75; } double phase360() { ret currentPeriodStart + interval(); } } HasKeyMap oscillators = new(map(f -> new Oscillator(f), pianoFrequencies88())); new TreeMultiMap completionsForSample; *(IAudioSample *audio, double *currentSample) {} *(IAudioSample *audio) {} // start at time 0 void init { for (o : oscillators) o.relocate(currentPeriodStart); } void stepTo(double time) { Double t = firstKey(completionsForSample); if (t != null && t <= time) for (Oscillator o : completionsForSample.getAndClear(t)) { o.measure(); o.relocate(t); } } }