// 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 = 48000; 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); } // Get an entry of the sum table - allow for out-of-bounds // requests (those just default to silence). @Override public double readSumTable(int channel, int i) { // do the first shift i -= start; ret getEntry(channel, i); } long getEntry(int channel, int i) { if (i < 0) ret 0; i = min(i, length-1); // do the second 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); if (l(data) != length*channels) data = 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 moveToCenter(int t) { moveTo(max(start, t-length/2)); } 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); } } }