// We're a a bit confused about whether the time coordinates are double // or int. (Probably int.) persistable sclass SlidingWindow implements IAudioSample { // general params double sampleRate; int channels; // length of window int length; // in samples per channel // start of window int start; // at which index in data array is our first value? int boundaryIndex; // in data // Here they are: the partial sums of the 16 bit audio samples // in an array of 6-byte integers. Channels are stored interleaved. HalfLongs data; // query original sound (channel, time -> short-range) IQuerySound sound; public double sampleRate() { ret sampleRate; } public int channels() { ret channels; } public DoubleRange bounds() { ret DoubleRange(start, start+length); } // result is in the range -32768*(end-start) to 32767*(end-start) public double sampleSum(int channel, double start, double end) { // We could do linear interpolation here if we weren't so basic. int a = ifloor(start-this.start), b = ifloor(end); ret getEntry(channel, b-1)-getEntry(channel, a-1); } // Get an entry of the sum table - allow for out-of-bounds // requests (those just default to silence). long getEntry(int channel, int i) { if (i < 0) ret 0; i = min(i, length-1); // do the shift i = (i+boundaryIndex) % length; ret data.get(i*channels+channel); } void setEntry(int channel, int i, long l) { // do the shift i = (i+boundaryIndex) % length; data.set(i*channels+channel, l); } // constructor - perform integration of the raw audio data *(int *channels, double *sampleRate, IQuerySound *sound, int *start, int *length) { grab(); } short getSample_short(int channel, double relTime) { ret clampToShort(iround(sound.getSample(channel, start+relTime))); } void grab { assertTrue(length > 0); data if null = new HalfLongs(length*channels); long[] sums = new[channels]; for i to length: for c to channels: setEntry(c, i, sums[c] += getSample_short(c, i)); } void moveTo(int newStart) { shiftRight(newStart-start); } void shiftRight(int n default 1) { if (n == 0) ret; assertTrue(n >= 0); int oldEnd = ifloor(end()); start += n; boundaryIndex = mod(boundaryIndex+n, length); int overlap = max(0, oldEnd-ifloor(start)); if (overlap == 0) grab(); else for (int i = overlap; i < length; i++) try { for c to channels: setEntry(c, i, getEntry(c, i-1) + getSample_short(c, i)); } on fail { printVars(+i, +start, +n, +length); } } }