-1

I'm developing a webapp for audio calibration using google polymer 3. Some process are running well untill I realized the audio channel data result is different to the expectation. I reference my expectation result to the octave software.

I created the sample repo for the experiment on https://github.com/mahdiridho/decodeAudioData

The client app result like so :

0: 0.738193154335022
1: 0.17993010580539703
2: 0.143886536359787
3: -0.49501433968544006
4: -0.581611156463623
5: -0.07922420650720596
6: 0.25858914852142334
7: 0.42484045028686523
8: 0.12840349972248077
9: -0.15169838070869446
10: -0.27878567576408386
11: -0.13389098644256592
12: 0.07916242629289627
13: 0.18276247382164001
14: 0.11339849978685379
15: -0.03214486315846443
16: -0.11864637583494186
17: -0.08897825330495834
18: 0.006309896241873503
19: 0.07485105097293854

while, the octave reference is like so :

1.000000
-0.059232
0.408143
-0.503169
-0.554996
-0.336158
0.122070
0.389484
0.336810
0.057144
-0.204190
-0.268489
-0.131052
0.069502
0.179210
0.140048
0.010775
-0.098861
-0.115960
-0.047979

We can see both are different nor identical nor scaled right?

My logic code should work with the result that same or identical to octave reference. What's the exactly problem here? How do you will fix this differences?

Best

Mahdi Ridho
  • 264
  • 1
  • 8

1 Answers1

1

I don't know Octave nor its audioread method, but BaseAudioContext.decodeAudioData does "[resample the audio data] to the AudioContext's sampling rate."

This means that two AudioContexts instance can return different audio data from this method.

Currently, the sampleRate of an AudioContext can only be set manually in Firefox and Chrome 74+, the other browsers defaulting to the preferred value of the current hardware; so below Snippet should currently be ran from Firefox browser or Chrome 74+.

const AudioContext = window.AudioContext || window.webkitAudioContext;
const ctx1 = new AudioContext({
  sampleRate: 8000
});
const ctx2 = new AudioContext({
  sampleRate: 44100
});

if (ctx1.sampleRate !== 8000 || ctx2.sampleRate !== 44100) {
  console.error("your browser doesn't support sampleRate option, please try again from Firefox or Chrome 74+");
} else {
  fetch('https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3')
    .then(r => r.arrayBuffer())
    .then(buf => Promise.all([
      ctx1.decodeAudioData(buf.slice()),
      ctx2.decodeAudioData(buf.slice())
    ])).then(([data1, data2]) => {
      console.log('8000Hz', data1.getChannelData(0).slice(0, 5));
      console.log('44100Hz', data2.getChannelData(0).slice(0, 5));
    })
    .catch(console.error);
}

Output from my Firefox:

8000Hz {
  "0": 0.005487468093633652,
  "1": 0.006598024629056454,
  "2": 0.009341353550553322,
  "3": 0.003335932269692421,
  "4": 0.002990187844261527
}
44100Hz {
  "0": 0.011174305342137814,
  "1": 0.016991807147860527,
  "2": 0.016990941017866135,
  "3": 0.01010976918041706,
  "4": 0.0003506771754473448
}

Note that my Chrome 76 with the same sampleRate does return something else.

So you can get that you should not expect this method to return any hard-coded data, and certainly not the same as the one Octave did return.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • Oh I see. So we have to know the audio file sample rate first to set it on audiocontext instance. I have updated the repo to simulate it where I have 2 audio files with different sampleRate : 1. h.wav 48000 2. h.441.wav 44100 However to test this simulation, I need to get the file sampleRate manually from the octave console by printout the fs, something like : ` [h,fs]=audioread('./audiofile/h.wav'); fs ` So, it's still pending case until now. The question now will be how to know the audio file sample rate loaded into the browser? – Mahdi Ridho Apr 24 '19 at 07:23
  • No, even with the same sampleRate, two browsers will come out with two different values. You should simply not rely on this method to return any fixed value. – Kaiido Apr 24 '19 at 07:30