2

I am using web audio API to stream audio to my remote server. I am using OfflineAudioContext. The code works fine in chrome and firefox but in safari, it gives the above mentioned error when trying to use OfflineAudioContext. I have tried adding webkit prefix to OfflineAudioContext, then it gives me this error:

SyntaxError: The string did not match the expected pattern.

I have tried adding different values to the OfflineAudioContext constructor but its always giving me the same error.

I went through Mozilla developers page for browser compatibility and I found this :

enter image description here

So, here its mentioned that for OfflineAudioContext constructor the compatibility is unknown for edge and safari. So, is this the reason, why I am not able to use OfflineAudioContext in safari? Is it not supported yet? or Am I doing it wrong? Or Is there another way to solve this in safari?

This is the first time I am using the Web Audio API. So, I hope somebody can clear my doubt if I missed out somewhere. Thank You.

Code of OfflineAudioContext added below:

let sourceAudioBuffer = e.inputBuffer; // directly received by the audioprocess event from the microphone in the browser

let TARGET_SAMPLE_RATE = 16000;
let OfflineAudioContext =
  window.OfflineAudioContext || window.webkitOfflineAudioContext;
let offlineCtx = new OfflineAudioContext(
  sourceAudioBuffer.numberOfChannels,
  sourceAudioBuffer.duration *
    sourceAudioBuffer.numberOfChannels *
    TARGET_SAMPLE_RATE,
  TARGET_SAMPLE_RATE
);

(if more code is needed of the js file to know the problem better. Just comment for it. I will add that but I thought the snippet is enough to understand the problem)

Ron Daulagupu
  • 423
  • 6
  • 18
  • Possible duplicate of [OfflineAudioContext and FFT in Safari](https://stackoverflow.com/questions/46621954/offlineaudiocontext-and-fft-in-safari) – StudioTime Mar 06 '19 at 10:48
  • @DarrenSweeney its not a duplicate. Please see the problem context in both. I have gone through that link before posting this question. – Ron Daulagupu Mar 06 '19 at 10:50

1 Answers1

1

It's a bit confusing, but a SyntaxError is what Safari throws if it doesn't like the arguments. And unfortunately Safari doesn't like a wide range of arguments which should normally be supported.

As far as I know Safari only accepts a first parameter from 1 to 10. That's the parameter for numberOfChannels.

The second parameter (the length) just needs to be positive.

The sampleRate can only be a number between 44100 and 96000.

However it is possible to translate all the computations from 16kHz to another sampleRate which then works in Safari. Let's say this is the computation you would like to do at 16kHz:

const oac = new OfflineAudioContext(1, 10, 16000);
const osciallator = oac.createOscillator();

osciallator.frequency.value = 400;

osciallator.connect(oac.destination);
osciallator.start(0);

oac.startRendering()
    .then((renderedBuffer) => {
        console.log(renderedBuffer.sampleRate);
        console.log(renderedBuffer.getChannelData(0));
    });

You can do almost the same at 48kHz. Only the sampleRate will be different but the channelData of the rendered AudioBuffer will be the same.

const oac = new webkitOfflineAudioContext(1, 10, 48000);
const osciallator = oac.createOscillator();

osciallator.frequency.value = 1200;

osciallator.connect(oac.destination);
osciallator.start(0);

oac.oncomplete = (event) => {
    console.log(event.renderedBuffer.sampleRate);
    console.log(event.renderedBuffer.getChannelData(0));
};
oac.startRendering();

Aside: Since I'm the author of standardized-audio-context which is a library that tries to ease out inconsistencies between browser implementations, I have to mention it here. :-) It won't help with the parameter restrictions in Safari, but it will at least throw the expected error if the parameter is out of range.

Also please note that the length is independent of the numberOfChannels. If IfsourceAudioBuffer.duration in your example is the duration in seconds, then you just have to multiply it with the TARGET_SAMPLE_RATE to get the desired length.

chrisguttandin
  • 7,025
  • 15
  • 21
  • So, I have multiplied the duration with TARGET_SAMPLE_RATE. So, is the sample rate the issue here? coz my sample rate is 16000 and you are saying that the sample rate has to be between 44100 to 96000. – Ron Daulagupu Mar 06 '19 at 12:18
  • Yes, you need to change the sampleRate to at least 44100 Hz to get Safari to accept it. But you could for example use 48 kHz to make the conversion a bit simpler in your case. – chrisguttandin Mar 06 '19 at 12:31
  • actually, I need the 16000 sample rate for my use case. Is it not possible to somehow use 16000 as my sample rate?? – Ron Daulagupu Mar 06 '19 at 12:36
  • The short and depressing answer is "No". Apple hasn't updated the Web Audio implementation for a long time and there seems to be no activity at all on their end. – chrisguttandin Mar 06 '19 at 12:59
  • But in case of an OfflineAudioContext the sampleRate is just a unit. You can translate everything from 16 kHz to 48 kHz and back again. That's of course cumbersome. – chrisguttandin Mar 06 '19 at 13:00
  • I am sorry but I did not get your last comment. what do you mean by changing 16 KHz to 48KHz and back again? Do you mean I can use 16 KHz in OfflineAudioContext or what is it? – Ron Daulagupu Mar 06 '19 at 13:16
  • I added an example translation from 16 kHz to 48 kHz to my answer. I hope it helps. – chrisguttandin Mar 06 '19 at 13:39
  • but that code will give me bytes at 48kHz sample rate. What I want is audio bytes in 16KHz sample rate. What can I do for that? can't I directly used 16KHz to generate that bytes?? – Ron Daulagupu Mar 06 '19 at 13:44
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189526/discussion-between-chrisguttandin-and-ron-daulagupu). – chrisguttandin Mar 06 '19 at 13:49