Microphone feedback noise and can I use the output to recognise?

I recently released my first ShazamKit app, but there is one thing that still bothers me.

When I started I followed the steps as documented by Apple right here : https://developer.apple.com/documentation/shazamkit/shsession/matching_audio_using_the_built-in_microphone

however when I was running this on iPad I receive a lot of high pitched feedback noise when I ran my app with this configuration. I got it to work by commenting out the output node and format and only use the input.

But now I want to be able to recognise the song that’s playing from the device that has my app open and was wondering if I need the output nodes for that or if I can do something else to prevent the Mic. Feedback from happening.

In short:

  1. What can I do to prevent feedback from happening
  2. Can I use the output of a device to recognise songs or do I just need to make sure that the microphone can run at the same time as playing music?

Other than that I really love the ShazamKit API and can highly recommend to have a go with it!

This is the code as documented in the above link (I just added the comments of what broke it for me)

func configureAudioEngine() {
    // Get the native audio format of the engine's input bus.
    let inputFormat = audioEngine.inputNode.inputFormat(forBus: 0)
    
    // THIS CREATES FEEDBACK ON IPAD PRO
    let outputFormat = AVAudioFormat(standardFormatWithSampleRate: 48000, channels: 1)
    
    // Create a mixer node to convert the input.
    audioEngine.attach(mixerNode)

    // Attach the mixer to the microphone input and the output of the audio engine.
    audioEngine.connect(audioEngine.inputNode, to: mixerNode, format: inputFormat)

    // THIS CREATES FEEDBACK ON IPAD PRO
    audioEngine.connect(mixerNode, to: audioEngine.outputNode, format: outputFormat)
        
    // Install a tap on the mixer node to capture the microphone audio.
    mixerNode.installTap(onBus: 0,
                         bufferSize: 8192,
                         format: outputFormat) { buffer, audioTime in
        // Add captured audio to the buffer used for making a match.
        self.addAudio(buffer: buffer, audioTime: audioTime)
    }
}

Replies

The output node is only required for playback and as you are recording only, I assume you do not require this.

The mainMixer is automatically connected to the output node and is created the first time that you refer to it so you are correct in using only the input node in isolation.

So in essence

  1. Keep just using the input node
  2. You don't need the output node, this will only contain the output from your process, not the system, so should not be of any use to you.

Good luck and congratulations on your app

  • Thanks for clarifying this! What would be the best way to let the user play and recognize music from the same phone or tablet speakers?

    I've tried multiple AVAudioSession.Category and AVAudioSession.CategoryOptions but thisfar without success.

    So in short: What are the recommended AVAudioSession settings to be able to recognize the song from the phone speakers?

Add a Comment

See comments (also, how do I delete this comment? haha)

Did you ever get recording audio and playing audio through the internal speakers and microphone to work at the same time? My app will stop playing the audio while recording even though my category is playAndRecord