Search code examples
ioscordovacore-audioweb-audio-api

Web audio on ios conflicting with audio queue, only on device


I have a Cordova plugin that records audio, using CoreAudio. It processes the audio samples, and also replays the recorded audio, still using CoreAudio. The application also plays some audio using web audio.

Everything works well in the ios simulator but on the device, the issue is as follows: record/replay works well until one call to the web audio is made, in that case, one subsequent call to CoreAudio fails.

If I re-use the AudioQueue, and try to restart it after it was stopped (and after some audio playback using web audio), the call to AudioQueueStart returns 560034163 which is "!aqs". I could not find what that means.

for (i = 0; i < kNumberBuffers; ++i) {
    XThrowIfError(AudioQueueEnqueueBuffer(audioQueue, audioBuffers[i], 0, NULL),
          "AudioQueueEnqueueBuffer failed");
  }
// That returns !aqs
XThrowIfError(AudioQueueStart(audioQueue, NULL), "AudioQueueStart failed");

Or if I dispose the queue when recording stops, then if I restart with creating a new Queue, the call to AudioQueueStart will return -50, which I read means that some parameters are invalid. Only parameter is the queue which was apparently created successfully. Again, this error only arise if I played web audio.

XThrowIfError(AudioQueueNewInput(&recordFormat, RecordingCallback,
              this /* userData */, NULL /* run loop */, NULL /* run loop mode */,
              0 /* flags */, &audioQueue), "AudioQueueNewInput failed");

  int bufferByteSize = 2 * 1024;
  int i;
  for (i = 0; i < kNumberBuffers; ++i) {
    XThrowIfError(AudioQueueAllocateBuffer(audioQueue, bufferByteSize, audioBuffers[i]),
                  "AudioQueueAllocateBuffer failed");
    XThrowIfError(AudioQueueEnqueueBuffer(audioQueue, audioBuffers[i], 0, NULL),
                  "AudioQueueEnqueueBuffer failed");
  }
  XThrowIfError(AudioQueueStart(audioQueue, NULL), "AudioQueueStart failed");

As I said, all these work well except if I am on device and after I play some audio using web audio. Also, replaying the recorded audio, using another AudioQueue for playback still works well after playing audio with web audio.

Any idea of what is going on? Or any idea on how to further debug?


Solution

  • The issue seems to be with the Audio Session category which needs to be set at AVAudioSessionCategoryPlayAndRecord, and with AVPlayer (which is probably what is internally used for playing back audio from a URL using the Media plugin or the web audio API). Apparently with AVAudioPlayer, there is no such issue, but I need to play a file on the web.

    Unfortunatly, setting

    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error: nil]; 
    

    in my plugin did not fix the issue, so I had to implement the playback function inside my plugin, using AVPlayer, and make sure the category was set when the plugin is initialized.

    These fixed my problem. Thanks to that SO issue.