sclass AudioAdder extends AbstractAudioSample { new Cl sources; srecord SumAndSlope(double sum, double slope) { double sumFor(double myTime, double time) { ret sum+(time-myTime)*slope; } } // for now same value in all channels new TreeMap additions; void addSource(IAudioSample source) { addUnlessNull(sources, source); } void grabSpecsFromSource(IAudioSample source) { if (source == null) ret; setSampleRate(source.sampleRate()); setChannels(source.channels()); } void addPlateau(double start, double end, double intensity) { printVars("addPlateau", +start, +end, +intensity); if (start >= end) ret; _incSlope(start, intensity); _incSlope(end, -intensity); } void subtractPlateau(double start, double end, double intensity) { addPlateau(start, end, -intensity); } // We will probably add plateaus rather randomly throughout an area, // so could optimize this doing something akin to LogNArray. void _incSlope(double time, double intensity) { if (intensity == 0) ret; // create, overwrite or delete var last = floorPair(additions, time); if (last.a == time) { // we are our own node already last.b.slope += intensity; } else (if last == null) { // we are first node mapPut(additions, time, new SumAndSlope(0, intensity); } else { // we are an insertion! mapPut(additions, time, new SumAndSlope(last.b.sumFor(last.a, time), last.slope+intensity); } recalcFrom(time); printVars _incSlope(+time, +intensity, value := _getValue(time)); } void recalcFrom(double time) { SumAndSlope me = additions.get(time); if (me == null) ret; Pair next; while ((next = higherPair(additions, time)) != null) { next.b.sum = me.sumFor(time, next.a); time = next.a; me = next.b; } } double _getValue(double time) { ret unnull(floorValue(additions, time)); } void _incValue(double time, double diff) { double before = _getValue(time); double value = before + diff; printVars _incValue(+time, +before, +value); //mapPutOrRemove(additions, time, nullIfZero(value)); additions.put(time, value); printStruct(additions); } @Override public double readSumTable(int channel, int t) { double t2 = t; Double key = floorKey(additions, t2); double diff = unnull(floorValue(additions, t2)); printVars readSumTable(+t, +key, +diff); for (source : sources) diff += source.readSumTable(channel, t); ret diff; } }