docstr: Test calculation of IPD spatial features for multi-channel audio.
          
docstr_tok: ["Test","calculation","of","IPD","spatial","features","for","multi-channel","audio","."]
code: def test_ipd(self, fft_length: int, num_channels: int):
      """Test calculation of IPD spatial features for multi-channel audio."""
      atol = 1e-5
      batch_size = 8
      num_samples = fft_length * 50
      num_examples = 10
      random_seed = 42
  
      _rng = np.random.default_rng(seed=random_seed)
  
      hop_length = fft_length // 4
      audio2spec = AudioToSpectrogram(
          fft_length=fft_length, hop_length=hop_length
      )
  
      spec2feat = SpectrogramToMultichannelFeatures(
          num_subbands=audio2spec.num_subbands,
          mag_reduction="rms",
          use_ipd=True,
          mag_normalization=None,
          ipd_normalization=None,
      )
  
      for n in range(num_examples):
          x = _rng.normal(size=(batch_size, num_channels, num_samples))
  
          spec, spec_len = audio2spec(
              input=torch.Tensor(x),
              input_length=torch.Tensor([num_samples] * batch_size),
          )
  
          # UUT output
          feat, _ = spec2feat(input=spec, input_length=spec_len)
          feat_np = feat.cpu().detach().numpy()
          ipd = feat_np[..., audio2spec.num_subbands :, :]
  
          # Golden output
          spec_np = spec.cpu().detach().numpy()
          spec_mean = np.mean(spec_np, axis=1, keepdims=True)
          ipd_golden = np.angle(spec_np) - np.angle(spec_mean)
          ipd_golden = (
              np.remainder(ipd_golden + np.pi, 2 * np.pi) - np.pi
          )
  
          # Compare shape
          assert (
              ipd.shape == ipd_golden.shape
          ), f"Feature shape not matching for example {n}"
  
          # Compare values
          assert np.allclose(
              ipd, ipd_golden, atol=atol
          ), f"Features not matching for example {n}"
  
imports: import importlib
  from typing import Optional
  import numpy
  import pytest
  import torch
  from nemo.collections.asr.modules.audio_modules import MaskBasedDereverbWPE, MaskEstimatorFlexChannels, MaskEstimatorGSS, MaskReferenceChannel, SpectrogramToMultichannelFeatures, WPEFilter
  from nemo.collections.asr.modules.audio_preprocessing import AudioToSpectrogram
  from nemo.collections.asr.parts.utils.audio_utils import convmtx_mc_numpy
  from nemo.utils import logging
label_desc: Use image node_id 2 for calling the TestSpectrogramToMultichannelFeatures obj's underlying member method code with example usage: obj.test_ipd(fft_length, num_channels) without return types