sclass ContinuousOscillators_TestAudioRestoration_v2 { S audioURL = "https://mouth.gazelle.rocks/beaHTML/15/5502%2Frecognize+-+61351880347bd84b28c7f42d779cde94.mp3"; short[] inputSamples; double inputSampleRate = 48000; settable bool separateFrequencies; settable bool cumulative; settable bool subtractive; settable bool separateRealAndImag; settable bool playRestored; settable bool showImage; settable bool printAllIntensities; bool useInputSampleRate = true; double silence = 0.2; double minFreq = 0, maxFreq = 48000; int useEveryNthOscillator = 1; short[] resampled; new L audioOutput; File wavOut; new ContinuousOscillators_v2 co; void loadAudioURL { File mp3 = loadBinaryPageOnce(audioURL); loadMP3(mp3); } void loadMP3(File mp3) { printFileInfo(+mp3); File wav = mp3ToWAVUnlessExists(mp3, replaceExtension(mp3, ".mp3", ".wav")); loadWAV(wav); } void loadWAV(File wav) { //playWAV(wav); printFileInfo(+wav); wavOut = appendToBaseFileName(wav, ".restored"); temp WAVDecoder decoder = new(wav); print(sampleRate := decoder.sampleRate); int n = decoder.totalValues(); inputSamples = decodeWAVToMonoSamples(decoder, n); inputSampleRate = decoder.sampleRate; } // assumes soundSource is using the default inputSampleRate void setAudio(double seconds, VF1 soundSource) { inputSamples = concatShortArrays(soundSourceToShortArrays(seconds, soundSource, 1)); print(inputSamples := sfu(takeFirst(10, inputSamples)); } run { if (useInputSampleRate) co.sampleRate = inputSampleRate; resampled = convertSampleRate_shortArray_simple(inputSampleRate, co.sampleRate, inputSamples); print(samples := l(resampled)); co.setAudio(new StaticAudioSample(ll(resampled), 1, co.sampleRate)); if (subtractive) co.onEscalating(o -> { print("Escalating " + o); var data = co.subtractedAudio.toDoubleArray(); audioOutput.add(data); print("Got samples: " + l(data)); }); // START CALCULATION co.stepTo(co.audio.bounds()); print(coverageByFreq := co.coverageByFreq()); restoreAudio(); double[] audio = concatDoubleArrays(audioOutput); double[] audioNorm = normalizeDoubles(audio, 32767); if (wavOut != null) { shortArrayToMonoWAVE(doubleToShortArray_iround(audioNorm), wavOut, co.sampleRate); printFileInfo(+wavOut); if (playRestored) playWAV(wavOut); } print(audioNorm := sfu(takeFirst(10, audioNorm)); double pixelsPerSecond = 100; if (showImage) dm_showPixelatedImage(co.image(co.audio.bounds(), pixelsPerSecond)); } void restoreAudio { L oscillators = new L; //double ratio = 2; // octave int nOscillators = l(co.oscillators); var lOsc = asList(co.oscillators); for i to nOscillators: { if ((i % useEveryNthOscillator) == 0) oscillators.add(lOsc.get(i)); } oscillators = filter(oscillators, o -> between(o.frequency()!, minFreq, maxFreq)); print("Using " + nFrequencies(oscillators) + ": " + map(oscillators, o -> formatDouble(o.frequency()!, 1)); if (separateFrequencies) { wavOut = appendToBaseFileName(wavOut, ".separate"); double[] cum = null; for (o : oscillators) { if (printAllIntensities) pnl(map(o.intensities, (k, v) -> o.frequency() + " " + formatDouble(k, 1) + " = " + renderComplexWithAngle(div(v.first(), l(k)*32767)))); //co.toAudio_shouldPrint = (i, n) -> i < 30 || i >= n-10; for (xx : separateRealAndImag ? ll(1, 2) : ll(0)) { co.realOnly = (xx & 1) != 0; co.imagOnly = (xx & 2) != 0; double[] newAudio = co.toAudio(ifloor(co.audio.bounds()), ll(o)); /*if (subtractive) { audioOutput.add(co.subtractedAudio.toDoubleArray()); } else*/ { if (cumulative) cum = newAudio = doubleAdd(cum, newAudio); audioOutput.add(newAudio); audioOutput.add(repDouble(iround(co.sampleRate*silence), 0)); } co.toAudio_shouldPrint = null; co.realOnly = co.imagOnly = false; } } } audioOutput.add(co.toAudio(ifloor(co.audio.bounds()), oscillators)); } }