Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

audioLies + audio data #67

Open
Thorin-Oakenpants opened this issue May 10, 2021 · 22 comments
Open

audioLies + audio data #67

Thorin-Oakenpants opened this issue May 10, 2021 · 22 comments
Labels

Comments

@Thorin-Oakenpants
Copy link
Contributor

@kkapsner : just FYI on the CB inconsistencies: not that I think it matters, as anyone wanting to NOT protect one of get vs copy is a bit silly and not likely in the slightest, but it does make testing it a bit weird, or otherwise I'm missing something

just some notes

have leveraged isBraveMode locally, but have found prototype lies to be unreliable. This can be said for any of prototype lies, while it may detect the extension is willing to use them, it doesn't mean it does

I would rather go down the road of double executions, mathematical proofs and equivalency

prototype lie results: trying to work out which lies MUST be present for a lie on the automatic audio test

// expecting
	// ba40f4d0c7290cd5143ac224e7f0ef363eee1e31e10e2a5bf7424ec4f1825a3b
	// 35.7383295930922

TRACE
====
"AudioBuffer.copyFromChannel"

I think trace is broken: audio is unaffected. Which sucks, this would have been a good
way to test a bypass when not all values are protected, since copy and get should be the same.


CB
==
0: "AnalyserNode.getByteFrequencyData"
1: "AnalyserNode.getByteTimeDomainData"
2: "AnalyserNode.getFloatFrequencyData"
3: "AnalyserNode.getFloatTimeDomainData"
4: "AudioBuffer.copyFromChannel"
5: "AudioBuffer.getChannelData"
6: "BiquadFilterNode.getFrequencyResponse"

^^ these are what come and go when toggling audio protection on/off

note: toggling individual options: inconsistent
note: using new tabs followed by a page refresh to ensure seeding
- uncheck just copyFromChannel
	- copyFromChannel not spoofed
	- "AudioBuffer.copyFromChannel" still reported in prototype lies
- uncheck just getChannelData
	- getChannelData is spoofed
	- "AudioBuffer.getChannelData" still reported in prototype lies

CHAMELEON
=========

0: "AudioBuffer.copyFromChannel"
1: "AudioBuffer.getChannelData"

^^ diffs with spoof/no-spoof

CYDEX: TOTAL MODE
=====

0: "AnalyserNode.fftSize"
1: "AnalyserNode.frequencyBinCount"
2: "AnalyserNode.getByteFrequencyData"
3: "AnalyserNode.getByteTimeDomainData"
4: "AnalyserNode.getFloatFrequencyData"
5: "AnalyserNode.getFloatTimeDomainData"
6: "AnalyserNode.maxDecibels"
7: "AnalyserNode.minDecibels"
8: "AnalyserNode.smoothingTimeConstant"
9: "AudioBuffer.copyFromChannel"
10: "AudioBuffer.getChannelData"
11: "BiquadFilterNode.getFrequencyResponse"

Sheesh that cydec is unintuitive: couldn't even get it back to standard mode

@Thorin-Oakenpants
Copy link
Contributor Author

Thorin-Oakenpants commented May 23, 2021

	for (let i=0; i < getTest.length; i++) {
		let x = getTest[i]
		sum2 += x
		sum3 += Math.abs(x)
		if (i > 4499 && i < 5000) {sum += Math.abs(x)}
	}
	console.log("sum: "+ sum +"\nsum2: "+ sum2 +"\nsum3: "+ sum3)

my machine

REAL
====
chromium
sum:    124.04347527516074
sum2:    -0.11990348991866995
sum3: 10748.96479334074

firefox
sum:    35.7383295930922
sum2:   -0.019596409052610397
sum3: 3188.503997568041

LIES
====
FF+canvas blocker
	sum: 35.738326121121645
	sum2: -0.019551539269741625
	sum3: 3188.504004060698

FF+chameleon
	sum: 35.73832958500134
	sum2: -0.01932726310678845
	sum3: 3188.5039971747838

FF+cydec: sum2+3 match
	sum: 1035.8892937898636
	sum2: 88414.9803841114
	sum3: 88414.9803841114

chrome+cydec: sum2+3 match
	sum: 998.6193348169327
	sum2: 88129.88009166718
	sum3: 88129.88009166718

brave lies
1: strict: sum2+3 match
	sum:    24.038141147364513
	sum2: 2224.6813276491157
	sum3: 2224.6813276491157
2: standard
	sum:    123.75700060309464
	sum2:    -0.1196279372202298
	sum3: 10724.140386573516

@Thorin-Oakenpants
Copy link
Contributor Author

note to self:

currently leveraging

  • isBraveMode
  • get + copy should match
  • sum2 + 3 shouldn't match

the current test needs a massive upgrade

  • multiple parameters, runs
    • triangle/sine (and other waves?) MDN
    • setPeriodicWave() looks exciting MDN
    • frequencies MDN
    • numberOfChannels, length, sampleRate MDN
    • delayed vs not ?
    • what is this chunkTest thing (is this chunks of the array - need to get @kkapsner to explain)
  • why are we only summing get and not copy
  • should the above all match (per wave type)
    • what does the sum of 41k in array of 48Hz reveal? <-- is this the chunk thing?
  • CB protections list these but are not used in the current test
    • getFloatFrequencyData, getBtyeFrequencyData
    • getFloatTimeDomainData, getByteTimeDomainData
    • getFrequencyResponse

polyfill

  • brave standard, cb, chameleon are very subtle
  • can a polyfill be accurate enough for a simple sum test

@Thorin-Oakenpants
Copy link
Contributor Author

Thorin-Oakenpants commented Jun 4, 2021

@abrahamjuliot add here as you get results

blink: also see https://fingerprintjs.com/blog/audio-fingerprinting/

124.04344884395687 : chromeOS 84
124.04347527516074 : windows + android10
124.04347721464    : chromeOS 89
124.04347657808103 : macOS BigSur 11.3 + ungoogled chromium
124.0434806260746  : macOS 11
124.08074500028306 : android 7, 9
124.08075528279005 : android 10+11

firefox
hmmm that's interesting that the channel hash changes

windows 7, 64bit browser (nightly 91)
ba40f4d0c7290cd5143ac224e7f0ef363eee1e31e10e2a5bf7424ec4f1825a3b - channels
35.7383295930922
c33ad9d6e032d6998313599cab9a861401814f5740d61b2601a92010f5865018 - oscillatorNode RFP=OFF
0bbc175d5d5d7c24106a8a672a89df54da406afaf96f6baa2321885d02af078b - OscillatorNode/DynamicsCompressor RFP=OFF
7fbaffe2fb30e675a99e7c0019f873fdf3acfbcb585c3d588612dcbd3da2b7ff - oscillatorNode RFP=ON
c75f5fb5369fd65b44334164fcd8e2369f75bfacd905607e2eb519f38b9a119a - OscillatorNode/DynamicsCompressor RFP=ON

macOS BigSur 11.3 (nightly 91)
eda9581d019a3389ed8eb0b77a7c74ce2505a3fec0e2f6484687e6e80495b56d
35.7383295930922
c33ad9d6e032d6998313599cab9a861401814f5740d61b2601a92010f5865018 - oscillatorNode RFP=OFF
bf2eaae195d501f43acb9dcd384f5099cb75533a0719cec7eca1aa16dc3981dd - OscillatorNode/DynamicsCompressor RFP=ON

https://github.com/arkenfox/user.js/issues/1216#issuecomment-883590247
Android RFP ON
- 639354199cf12c28fb7f14cabdb77872a040bd93
- 35.7499681673944
- 63848d42fb8da033b1bd6861a5198ed01f4b214b [20 keys]
- 9c39676511544e169d0b40366dd8f7bf167eb437
- 7072df3640caea7df394a560e30aada4b416ca95 

Android RFP OFF
- 639354199cf12c28fb7f14cabdb77872a040bd93
- 35.7499681673944
- d908755de877d8ebd96651bc5286bcf85fbd42d3 [20 keys]
- 9c39676511544e169d0b40366dd8f7bf167eb437
- 7072df3640caea7df394a560e30aada4b416ca95

Ubuntu RFP OFF
- 4460bdcbe1cb161b6f9bd804565c8ecbaa2c4da6
- 35.73833402246237
- 506774fdd1f5cf63c96db512f3efe5f335d656b2 [20 keys]
- 247e9af1788fd5dca82f2139619cc7bd7e3be6ea
- d7db6f9e9102bc7989a56dc42ab48cd9a1be60b2

Ubuntu RFP ON
- 4460bdcbe1cb161b6f9bd804565c8ecbaa2c4da6
- 35.73833402246237
- fdb6f2cb10e8f42e073ef8b99345d739986ec390 [20 keys]
- 247e9af1788fd5dca82f2139619cc7bd7e3be6ea
- d7db6f9e9102bc7989a56dc42ab48cd9a1be60b2

FYI: current min/max

	if (isFF) {
		min = 35.738329
		max = 35.78334
	}

@Thorin-Oakenpants
Copy link
Contributor Author

reminder to self: split up the output better, so RFP protected keys are split from the rest: when I rebuild the audio section

@abrahamjuliot
Copy link
Collaborator

abrahamjuliot commented Jun 9, 2021

Here's a back door to get audio entropy using DynamicsCompressorNode.reduction. I tested in FF and Chrome on Windows, Android, and ChromeOS. It's also unprotected in Brave.

By default, it's 0, but it's rendered in the oncomplete event (line 258)

context.oncomplete = function(event) {
  const compressorGainReduction = pxi_compressor.reduction
  //...

I have not examined this yet, but the result might mirror the entropy in the sum fingerprint. So, if the reduction is a known value, we can infer the sum fingerprint.

FF on Windows:

  • compressorGainReduction: -31.509262084960938
  • sum: 35.7383295930922

Some observations in Brave...

Here's a quick function to detect Brave's standard farbling (based on the FPJS fudge factor detection):

const getNoiseFactor = () => {
	const buffer = new AudioBuffer({
		length: 1,
		sampleRate: 44100
	})
	buffer.getChannelData(0)[0] = 1
	return buffer.getChannelData(0)[0]
}
const noiseFactor = getNoiseFactor()
console.log(`Audio Noise Detected: ${noiseFactor != 1 ? noiseFactor : 'none'}`)

Brave strict mode has a max unique rate, so it too can be detected

const bins = buffer.getChannelData(0)
const numOfUniqueValues = new Set([...bins]).size // Brave strict returns the length of the buffer

@Thorin-Oakenpants
Copy link
Contributor Author

nice. I need to finish my revamped domrect first

  • clickable details for data
  • clickable shift-diff data & shift-diff spoof fingerprint
  • single result for FF, allow multi-results non-FF
  • tidy up lies, bypasses, blocks, methods, coloring up etc
  • FF: if no lies: convert to zoom resistant by using %

And then it's onto audio. I already had ideas on how other ways to detect lies, but the more in the arsenal, the better. I'm just not sure how far down this rabbit hole I want to go as I believe entropy is SFA

Will check out your code bits when I get back to this

@Thorin-Oakenpants
Copy link
Contributor Author

Thorin-Oakenpants commented Jul 3, 2021

@sgmenda - I'm not too far away from rebuilding the audio section - maybe a week

I plan on building a stand-alone test first which

  • checks that it is gecko
  • detects audio lies via prototype/proxy lies

There will be a run button, as this allows us to run audio tests behind a user gesture

  • if the checks above pass, then we will allow a submit button - that is we do not collect spoofed audio
  • the data collected also includes the OS, FF version, and if RFP is enabled
  • if there are no UA lies we'll include that as well
  • the user doesn't even need give us any info, unless they want to type in their android version or something - so an optional field
  • the data sent back on submission can be broken up any way we want in any format
    • e.g. RFP protected audioContext keys can be separate from the other 18 keys, so it's easier to analyze the differences
  • for good measure we can include the math entropy test

So something similar to the webgl test you and @tomrittervg set up , but one where we can eliminate the noise. The standalone test would be minus the submission which can be added on tom's site. And then you drill down into the data by OS, by RFP, and even by version (which shouldn't matter but can weed out old releases), and even see the correlation between the math entropy.

FWIW, it seems as if audio math results are a subset of math audio entropy [edited]

If you're interested in chipping in here and collaborating when and if you have time, rather than us all doing our own thing ... I can add you as an admin - just confirm with me via email

PS: the webgl parameters is also not far away: see

  • 40117
  • 30537#note_2710738
  • i.e ignoring images, we can split out webgl, webgl2, webgl-experimental parameters and values etc in whatever groups we like so we can map differences

@Thorin-Oakenpants
Copy link
Contributor Author

FWIW, it seems as if audio results are a subset of math entropy

that's the other way round: math is a subset of audio

@Thorin-Oakenpants
Copy link
Contributor Author

Thorin-Oakenpants commented Jul 19, 2021

OK, am onto it in theory .. getting a stable known result across all platforms, that audio randomizes are triggered into adding noise to should be totally doable with a non-sinusoidal periodic waveform .. e.g. a square wave, perhaps a sawtooth wave, or a flat line ... that said the triangle wave is also non-sinusoidal (but we don't really have any data sets on if this wave contains any entropy within a platform - but note that CB's tests include it, but for testing randomizing, not entropy)

flat wave .. I wonder how hard it would be to generate one at a specific "height" and the sum is shitloads of decimal places, you know like 4/3 = 1.333333333333333333333333333333333...

class discuss

homework for @abrahamjuliot : https://en.wikipedia.org/wiki/Rectangular_function

@Thorin-Oakenpants Thorin-Oakenpants changed the title audioLies audioLies + audio data Jul 20, 2021
@Thorin-Oakenpants
Copy link
Contributor Author

Thorin-Oakenpants commented Aug 11, 2021

alrighty .. now we're cooking

Firefox audio FPs taken from appendix C and figure 10
FF-audio

@abrahamjuliot .. you can add that paper to your collection and repo, to save me typing this shit out twice, TIA - edit, you can also add https://www.cse.chalmers.se/~andrei/secweb21.pdf which is interesting

@Thorin-Oakenpants
Copy link
Contributor Author

😀 homework for abraham: calculate Pi to 62.8tn decimal places for max entropy

Hmmm ... Pi is used in fourier transformations AFAIK, so if Pi has entropy in android ... something does in cbrt: 1p1, which is cbrt(Math.PI), so it's either Math.pow or Math.PI

	function cbrt(x) {
		let y = Math.pow(Math.abs(x), 1 / 3)
		return x < 0 ? -y : y
	}

@Thorin-Oakenpants
Copy link
Contributor Author

#67 (comment)

I now have the code they used (not sure if I can share it yet). At quick glance, it looks like it's has combined the audio tests behind user gestures e.g. OscillatorNode etc .. and I think it has also included the audioContext keys

I also have all the data, including the sums, such as 35.7383295930922, e.g, running the test matches TZP sum etc, so that's handy, all those known gecko/blink results

@sgmenda - have you built the web package yet: I'm kinda lost on how to: I just want the js

@sgmenda
Copy link

sgmenda commented Aug 26, 2021

Sorry for the late response.

#67 (comment)

@sgmenda - have you built the web package yet: I'm kinda lost on how to: I just want the js

I haven't yet had a chance to. I will try to take a look over the weekend and update here if I figure it out.

@Thorin-Oakenpants
Copy link
Contributor Author

Thorin-Oakenpants commented Sep 11, 2021

cool ... https://en.wikipedia.org/wiki/User:LucasVB/Gallery#Waves

really cool ... https://bl.ocks.org/jinroh/7524988 .. with code

@Thorin-Oakenpants
Copy link
Contributor Author

@abrahamjuliot

see arkenfox/user.js#1701 (comment) - basically mozilla have standardized the math library in audio - read https://bugzilla.mozilla.org/show_bug.cgi?id=1358149#c56 in FF118+

but in my ToDo #169 under audio I have

🟦 audio

now a lot of that can be ignored, now we know audio is RFP protected, so I don't need to do sawtooth, or other tests, but I may do a standalone more comprehensive test: I have the code from those researchers too.

but I was interested in some of creepy's code: for example I do not have these

gain: -31.502185821533203
freq: 167700.7530517578
time: 148.475412953645
trap: 0.3772195888637472

AnalyserNode.context.listener.forwardX.maxValue: undefined
BiquadFilterNode.gain.maxValue: 3.4028234663852886e+38
BiquadFilterNode.frequency.defaultValue: 350
BiquadFilterNode.frequency.maxValue: 22050
DynamicsCompressorNode.attack.defaultValue: 0.003000000026077032
DynamicsCompressorNode.knee.defaultValue: 30
DynamicsCompressorNode.knee.maxValue: 40
DynamicsCompressorNode.ratio.defaultValue: 12
DynamicsCompressorNode.ratio.maxValue: 20
DynamicsCompressorNode.release.defaultValue: 0.25
DynamicsCompressorNode.release.maxValue: 1
DynamicsCompressorNode.threshold.defaultValue: -24
DynamicsCompressorNode.threshold.minValue: -100
OscillatorNode.detune.maxValue: 3.4028234663852886e+38
OscillatorNode.detune.minValue: -3.4028234663852886e+38
OscillatorNode.frequency.defaultValue: 440
OscillatorNode.frequency.maxValue: 22050
OscillatorNode.frequency.minValue: -22050

is there any point in adding more? also what to make of #67 (comment)

@karlt FYI

@abrahamjuliot
Copy link
Collaborator

Here's a simplified concept that gets the gain, freq, time. From what I recall, all the default Node values produce no entropy connected with the audio rendering or system configuration, but there might be something there I missed.

function getRenderedAudioData() {

    // samples get filled around 200, so we could speed this up within
    // 200-5000 bins
    const context = new OfflineAudioContext(1, 5000, 44100)
    const analyser = context.createAnalyser()
    const dynamicsCompressor = context.createDynamicsCompressor()
    const oscillator = context.createOscillator()
    const biquadFilter = context.createBiquadFilter() // optional if we want the values

    oscillator.type = 'triangle'
    oscillator.frequency.value = 10000
    dynamicsCompressor.threshold.value = -50
    dynamicsCompressor.knee.value = 40
    dynamicsCompressor.attack.value = 0

    analyser.connect(context.destination);
    dynamicsCompressor.connect(analyser);
    dynamicsCompressor.connect(context.destination);
    oscillator.connect(dynamicsCompressor);

    oscillator.start(0);
    context.startRendering()

    return new Promise((resolve) => {
        context.oncomplete = (event) => {
            const channelData = event.renderedBuffer.getChannelData(0)
            const freqData = new Float32Array(analyser.frequencyBinCount)
            const timeData = new Float32Array(analyser.fftSize)
            
            analyser.getFloatFrequencyData(freqData)
            analyser.getFloatTimeDomainData(timeData)
            dynamicsCompressor.disconnect()
            oscillator.disconnect()

            // reduction gets rendered with the audio
            // value is not implemented older WebKit, so we fallback to reduction
            const { reduction } = dynamicsCompressor
            const gainReduction = Number(reduction.value || reduction) || 0;
            
            // Optionally collect or hash the values below
            /*
            analyser.channelCount
            analyser.channelCountMode
            analyser.channelInterpretation
            analyser.context.sampleRate
            analyser.fftSize
            analyser.frequencyBinCount
            analyser.maxDecibels
            analyser.minDecibels
            analyser.numberOfInputs
            analyser.numberOfOutputs
            analyser.smoothingTimeConstant
            analyser.context.listener.forwardX.maxValue
            biquadFilter.gain.maxValue
            biquadFilter.frequency.defaultValue
            biquadFilter.frequency.maxValue
            dynamicsCompressor.attack.defaultValue
            dynamicsCompressor.knee.defaultValue
            dynamicsCompressor.knee.maxValue
            dynamicsCompressor.ratio.defaultValue
            dynamicsCompressor.ratio.maxValue
            dynamicsCompressor.release.defaultValue
            dynamicsCompressor.release.maxValue
            dynamicsCompressor.threshold.defaultValue
            dynamicsCompressor.threshold.minValue
            oscillator.detune.maxValue
            oscillator.detune.minValue
            oscillator.frequency.defaultValue
            oscillator.frequency.maxValue
            oscillator.frequency.minValue
            */
            
            // Simplify to one sample per field
            return resolve([
                channelData.slice(-1)[0],
                gainReduction,
                freqData.slice(-1)[0],
                timeData.slice(-1)[0],
            ]);
        };
    });
}

getRenderedAudioData().then(data => console.log(data))

@abrahamjuliot
Copy link
Collaborator

abrahamjuliot commented Aug 22, 2023

The trap concept code is somewhat difficult to parse… I forgot what I was thinking. I added some comments to better explain it.

// Returns a random integer between min and max
const getRandFromRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min

// Copies data from an audio buffer to a float array and modifies it with randomness
// Returns an array of unique and non-zero values from the modified data
const getCopyFrom = (rand, buffer, copy) => {
  const { length } = buffer // get the length of the buffer

  const max = 20; // number of bins to modify
  const start = getRandFromRange(275, length - (max + 1)); // audio usually begins after 275
  const mid = start + max / 2; // the middle bin
  const end = start + max; // the last bin

  // Set data to randomness at the start, middle and end bins
  buffer.getChannelData(0)[start] = rand
  buffer.getChannelData(0)[mid] = rand
  buffer.getChannelData(0)[end] = rand
  buffer.copyFromChannel(copy, 0) // copy the data from the buffer to the array

  // Modify the data with randomness if it is zero at the start, middle and end bins
  const attack = [
    buffer.getChannelData(0)[start] === 0 ? Math.random() : 0,
    buffer.getChannelData(0)[mid] === 0 ? Math.random() : 0,
    buffer.getChannelData(0)[end] === 0 ? Math.random() : 0,
  ]

  // Read back unique data and filter non-zero values
  return [...new Set([...buffer.getChannelData(0), ...copy, ...attack])].filter((x) => x !== 0)
}

// Copies data from a float array to an audio buffer and modifies it with randomness
// Returns an array of values from the modified data that are different from the frequency value
const getCopyTo = (rand, buffer, copy) => {
  buffer.copyToChannel(copy.map(() => rand), 0) // copy the data from the array to the buffer with randomness
  const frequency = buffer.getChannelData(0)[0] // get the frequency value from the first bin
  const dataAttacked = [...buffer.getChannelData(0)] // get the modified data as an array
    .map((x) => x !== frequency || !x ? Math.random() : x) // modify the data with randomness if it is different from the frequency or zero
  return dataAttacked.filter((x) => x !== frequency) // filter out the frequency values
}

// Generates a noise factor based on two audio buffers and two float arrays
// Returns a number that represents the noise factor or zero if there is an error
const getNoiseFactor = () => {
  const length = 2000 // length of the audio buffers and arrays
  const rand = Math.random() // use to modify with noise
  try {
    const result = [...new Set([ // get unique values from both functions
      ...getCopyFrom(
        rand,
        new AudioBuffer({ length, sampleRate: 44100 }), // create an empty audio buffer with length and sample rate
        new Float32Array(length), // create an empty float array with length
      ),
      ...getCopyTo(
        rand,
        new AudioBuffer({ length, sampleRate: 44100 }), // create another empty audio buffer with length and sample rate
        new Float32Array(length), // create another empty float array with length
      ),
    ])]
    return Number(
      result.length !== 1 && // check if there is more than one value in the result array
      result.reduce((acc, n) => acc += +n, 0) // sum up all the values in the result array
    )
  } catch (error) {
    console.error(error)
    return 0
  }
}

const noiseFactor = getNoiseFactor()

console.log(noiseFactor)

@abrahamjuliot
Copy link
Collaborator

is there any point in adding more? also what to make of #67 (comment)

It can be useful for sanity checks, but it seems there's not much to classify if the values are genuine.

@Thorin-Oakenpants
Copy link
Contributor Author

Thanks 👍 this is now on my todo, to at least explore if they're 1. stable and 2. worth it and 3. where to add, under auto or click

by "worth it" for example, I see duplication? equivalency?

BiquadFilterNode.gain.maxValue: 3.4028234663852886e+38
OscillatorNode.detune.maxValue: 3.4028234663852886e+38
OscillatorNode.detune.minValue: -3.4028234663852886e+38

BiquadFilterNode.frequency.maxValue: 22050  // 44100 (which the test sets) / channel count ?
OscillatorNode.frequency.maxValue: 22050
OscillatorNode.frequency.minValue: -22050

some of the others look suspiciously common or related to context keys

remembering that TZP is gecko only, this is a nice to have to finish the section off for RFP FF118+ (don't care about older releases, except ESR but I'm hoping it might get backported upstream for TB, we haven't asked yet). But at this stage, I'm inclined to trust the moz engineers have hooked up all the math and we're not going to get any extra entropy. Twould be nice to close an issue for once :~p

@Thorin-Oakenpants
Copy link
Contributor Author

Thorin-Oakenpants commented Jan 14, 2024

function getRenderedAudioData()

so this is very similar to the existing onlineAudioContext test that gets the sum and channel hashes, so rather than run a separate test I can probably just piggy back on that one?

anyway, using your standalone test (on file:// scheme) I do not get the same results as creepy

context.oncomplete = (event) => {
	// snip
	let oData = {
		"freq": freqData.slice(-1)[0],
		"gain": gainReduction,
		"time": timeData.slice(-1)[0],
		"wtf_is_this": channelData.slice(-1)[0],
	}
	console.log(performance.now() - t0, oData)
	return resolve()
};

// what I get
{
	'freq': -190.46719360351562'gain': -31.502185821533203'time': -0.06294857710599899'wtf_is_this': -0.21359434723854065
}

// what creepy reports (no RFP or anything)
{
	'freq': 167700.7530517578
	'gain': -31.502185821533203
	'time': 148.475412953645
	'trap': 0.7879753706889067
}

so gain is the same but everything else is different, and I didn't hook up any trap code

@Thorin-Oakenpants
Copy link
Contributor Author

gain seems to be directly related to dynamicsCompressor.reduction

I can probably just piggy back on that one

nope, because we need the analyser

@abrahamjuliot
Copy link
Collaborator

This should align the results, but I might be missing something...

function slice(arr, start, end) {
  const collection = []
  for (let i = start; i < end; i++) {
    collection.push(arr[i])
  }
  return collection
}
function toSum(arr) {
  return !arr ? 0 : [...arr].reduce((acc, curr) => (acc += Math.abs(curr)), 0)
}

let oData = {
  "freq": toSum(freqData)
  "gain": gainReduction,
  "time": toSum(timeData),
  "wtf_is_this": toSum(slice([...channelData], 4500, bufferLen /* 5000 */)), // fpjs sum
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

3 participants