Libraryless. Compilation Failed (11097L/66K).
sclass PianoSampler { macro dprint { if (debug) printVars } bool debug; int channels = 1; double sampleRate = 48000; double currentSample; IQuerySound sound; IAudioSample audio; SlidingWindow window; long haarFeaturesChecked; persistable class Oscillator extends HasKey<Frequency> { double currentPeriodStart; // all recorded intensities new TreeMap<DoubleRange, Channels<Complex>> intensities; double interval; // in samples *(Frequency f) { super(f); interval = frequency().interval()*sampleRate; } Frequency frequency() { ret key(); } double interval() { ret interval; } void record_impl(DoubleRange r, Channels<Complex> c) { intensities.put(r, c); } void advancePeriodToRange(DoubleRange timeRange) { double end = currentPeriodStart + interval; int phaseShifts = ifloor((timeRange.start-end)/interval); if (phaseShifts = 0) ret; setStart(currentPeriodStart + phaseShifts*interval); } // we span a total range of interval*1.25 because of the sin/cos thing void measure(DoubleRange timeRange) { DoubleRange p1 = doubleRangeWithLength(phaseMinus90(), interval); p1 = intersectDoubleRanges(p1, timeRange); double re = 0; if (!isEmpty(p1)) { AudioHaarFeature haar = new(audio, p1); re = haar!; } DoubleRange p2 = doubleRangeWithLength(currentPeriodStart, interval); p2 = intersectDoubleRanges(p2, timeRange); double im = 0; if (!isEmpty(p2)) { AudioHaarFeature haar = new(audio, p2); im = haar!; } record(this, p1 /*TODO*/, complexChannels(re, im)); haarFeaturesChecked += 2; } void dropMeasurementsLeftOf(double t) { while ping (true) { var r = firstKey(intensities); if (r != null && r.end() <= t) popFirst(intensities); else break; } } void initial(double currentSample) { setStart(currentSample + startPhase()); } void moveTo(double time) { currentPeriodStart = time; double next = phase360(); dprint("moveTo", +this, +next); completionsForSample.put(next, this); } double startPhase() { ret phase90(); } double quarterPhase() { ret interval()*.25; } double phaseMinus90() { ret currentPeriodStart - interval()*.25; } double phase0() { ret currentPeriodStart; } double phase90() { ret currentPeriodStart + interval()*.25; } double phase180() { ret currentPeriodStart + interval()*.5; } double phase270() { ret currentPeriodStart + interval()*.75; } double phase360() { ret currentPeriodStart + interval(); } double phase450() { ret currentPeriodStart + interval()*1.25; } } // end of Oscillator TreeHasKeyMap<Frequency, Oscillator> oscillators = new TreeHasKeyMap<Frequency, Oscillator>(map(f -> new Oscillator(f), pianoFrequencies88())); new TreeMultiMap<Double, Oscillator> completionsForSample; *() {} *(IAudioSample audio, double *currentSample) { setAudio(audio); } *(IAudioSample audio) { setAudio(audio); } // start at time 0 void setAudio(IAudioSample audio) { this.audio = audio; window = optCast SlidingWindow(audio); } void verboseOnRecordAdded() { onRecordAdded(lambda1 print); } int nFrequencies() { ret oscillators.size(); } void startOscillators { for (o : oscillators) o.initial(currentSample); } void stepTo(DoubleRange timeRange) { while ping (true) { Double t = firstKey(completionsForSample); if (t != null && t <= timeRange.start) { var list = completionsForSample.getAndClear(t); dprint(+t, +list); for (Oscillator o : list) { o.measure(timeRange); o.relocate(t); } } else break; } } void record(Oscillator o, DoubleRange r, Channels<Complex> c) { if (o == null) ret; o.record_impl(r, c); onRecordAdded(new RecordAdded(o, r, c)); } record RecordAdded(Oscillator oscillator, DoubleRange period, Channels<Complex> intensity) {} transient event interface OnRecordAdded as onRecordAdded shipping RecordAdded; Frequency lowestFrequency() { ret oscillators.firstKey(); } Frequency highestFrequency() { ret oscillators.lastKey(); } int minWindowSize() { ret iceil(sampleRate*lowestFrequency().interval()); } void makeSmallestWindow(IQuerySound sound) { this.sound = sound; setAudio(new SlidingWindow(channels, sampleRate, sound, 0, minWindowSize()); } double windowSize() { ret window.length(); } S stats() { ret renderVars(+audio, +haarFeaturesChecked); } IIntegralImage imageColumn(DoubleRange timeRange) { int n = nFrequencies(); var l = reversedList(oscillators); double[] col = new[n]; for y to n: { var l2 = l.get(y).intensities; new Average avg; forEach(l2, (r, val) -> { double amplitude = val.first().abs(); // if only a part is in the time range double actualDuration = l(intersectDoubleRanges(r, timeRange)); avg.add(amplitude, actualDuration); }); col[y] = avg!; } double[] col2 = normalizeDoubles(col, 255); ret bwIntegralImageFromFunction(1, n, (x, y) -> ifloor(col2[y])); } // how much horizontal area have we covered L<Double> coverageByFreq() { ret mapReversed(oscillators, o -> totalLengthOfDoubleRanges(keys(o.intensities))); } void stepRight(double shift) { assertNotNull(+window); var r = window.bounds(); window.shiftRight(max(1, ifloor(shift))); for (o : oscillators) o.dropMeasurementsLeftOf(window.start()); stepTo(window.end()); } DoubleRange windowBounds() { ret window.bounds(); } }
download show line numbers debug dex old transpilations
Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1032970 |
Snippet name: | PianoSampler [dev.] |
Eternal ID of this version: | #1032970/58 |
Text MD5: | 16206552e3383e53a76f46517a272ed0 |
Transpilation MD5: | b1d20b360e5c5cceb4e23436d38322ed |
Author: | stefan |
Category: | javax / audio analysis |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-10-11 15:53:09 |
Source code size: | 6085 bytes / 199 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 286 / 599 |
Version history: | 57 change(s) |
Referenced in: | #1033037 - PianoSampler2 [much simpler, seems to produce a nice image] #1033245 - ContinuousOscillators [dev.] #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674) |