docstr: `save` function produces file that is comparable with `ffmpeg` command
  
  To compare that the file produced by `save` function agains the file produced by
  the equivalent `ffmpeg` command, we need to load both files.
  But there are many formats that cannot be opened with common Python modules (like
  SciPy).
  So we use `ffmpeg` command to prepare the original data and convert the saved files
  into a format that SciPy can read (PCM wav).
  The following diagram illustrates this process. The difference is 2.1. and 3.1.
  
  This assumes that
   - loading data with SciPy preserves the data well.
   - converting the resulting files into WAV format with `ffmpeg` preserve the data well.
  
                    x
                    | 1. Generate source wav file with SciPy
                    |
                    v
    -------------- wav ----------------
   |                                   |
   | 2.1. load with scipy              | 3.1. Convert to the target
   |   then save it into the target    |      format depth with ffmpeg
   |   format with torchaudio          |
   v                                   v
  target format                       target format
   |                                   |
   | 2.2. Convert to wav with ffmpeg   | 3.2. Convert to wav with ffmpeg
   |                                   |
   v                                   v
  wav                                 wav
   |                                   |
   | 2.3. load with scipy              | 3.3. load with scipy
   |                                   |
   v                                   v
  tensor -------> compare <--------- tensor
docstr_tok: ["`","save","`","function","produces","file","that","is","comparable","with","`","ffmpeg","`","command","To","compare","that","the","file","produced","by","`","save","`","function","agains","the","file","produced","by","the","equivalent","`","ffmpeg","`","command",",","we","need","to","load","both","files",".","But","there","are","many","formats","that","can","not","be","opened","with","common","Python","modules","(","like","SciPy",")",".","So","we","use","`","ffmpeg","`","command","to","prepare","the","original","data","and","convert","the","saved","files","into","a","format","that","SciPy","can","read","(","PCM","wav",")",".","The","following","diagram","illustrates","this","process",".","The","difference","is","2.1.","and","3.1",".","This","assumes","that","-","loading","data","with","SciPy","preserves","the","data","well",".","-","converting","the","resulting","files","into","WAV","format","with","`","ffmpeg","`","preserve","the","data","well",".","x","|","1",".","Generate","source","wav","file","with","SciPy","|","v","--","--","--","--","--","--","--","wav","--","--","--","--","--","--","--","--","|","|","|","2.1.","load","with","scipy","|","3.1",".","Convert","to","the","target","|","then","save","it","into","the","target","|","format","depth","with","ffmpeg","|","format","with","torchaudio","|","v","v","target","format","target","format","|","|","|","2.2",".","Convert","to","wav","with","ffmpeg","|","3.2",".","Convert","to","wav","with","ffmpeg","|","|","v","v","wav","wav","|","|","|","2.3.","load","with","scipy","|","3.3.","load","with","scipy","|","|","v","v","tensor","--","--","--","-",">","compare","<","--","--","--","--","-","tensor"]
code: def assert_save_consistency(
      self,
      format: str,
      *,
      compression: Optional[CodecConfig] = None,
      encoding: str = None,
      bits_per_sample: int = None,
      sample_rate: float = 8000,
      num_channels: int = 2,
      num_frames: float = 3 * 8000,
      src_dtype: str = "int32",
      test_mode: str = "path",
  ):
      """`save` function produces file that is comparable with `ffmpeg` command
  
      To compare that the file produced by `save` function agains the file produced by
      the equivalent `ffmpeg` command, we need to load both files.
      But there are many formats that cannot be opened with common Python modules (like
      SciPy).
      So we use `ffmpeg` command to prepare the original data and convert the saved files
      into a format that SciPy can read (PCM wav).
      The following diagram illustrates this process. The difference is 2.1. and 3.1.
  
      This assumes that
       - loading data with SciPy preserves the data well.
       - converting the resulting files into WAV format with `ffmpeg` preserve the data well.
  
                        x
                        | 1. Generate source wav file with SciPy
                        |
                        v
        -------------- wav ----------------
       |                                   |
       | 2.1. load with scipy              | 3.1. Convert to the target
       |   then save it into the target    |      format depth with ffmpeg
       |   format with torchaudio          |
       v                                   v
      target format                       target format
       |                                   |
       | 2.2. Convert to wav with ffmpeg   | 3.2. Convert to wav with ffmpeg
       |                                   |
       v                                   v
      wav                                 wav
       |                                   |
       | 2.3. load with scipy              | 3.3. load with scipy
       |                                   |
       v                                   v
      tensor -------> compare <--------- tensor
  
      """
      src_path = self.get_temp_path("1.source.wav")
      tgt_path = self.get_temp_path(f"2.1.torchaudio.{format}")
      tst_path = self.get_temp_path("2.2.result.wav")
      sox_path = self.get_temp_path(f"3.1.ffmpeg.{format}")
      ref_path = self.get_temp_path("3.2.ref.wav")
  
      # 1. Generate original wav
      data = get_wav_data(
          src_dtype,
          num_channels,
          normalize=False,
          num_frames=num_frames,
      )
      save_wav(src_path, data, sample_rate)
  
      # 2.1. Convert the original wav to target format with torchaudio
      data = load_wav(src_path, normalize=False)[0]
      if test_mode == "path":
          ext = format
          self._save(
              tgt_path,
              data,
              sample_rate,
              compression=compression,
              format=format,
              encoding=encoding,
              bits_per_sample=bits_per_sample,
          )
      elif test_mode == "fileobj":
          ext = None
          with open(tgt_path, "bw") as file_:
              self._save(
                  file_,
                  data,
                  sample_rate,
                  compression=compression,
                  format=format,
                  encoding=encoding,
                  bits_per_sample=bits_per_sample,
              )
      elif test_mode == "bytesio":
          file_ = io.BytesIO()
          ext = None
          self._save(
              file_,
              data,
              sample_rate,
              compression=compression,
              format=format,
              encoding=encoding,
              bits_per_sample=bits_per_sample,
          )
          file_.seek(0)
          with open(tgt_path, "bw") as f:
              f.write(file_.read())
      else:
          raise ValueError(f"Unexpected test mode: {test_mode}")
      # 2.2. Convert the target format to wav with ffmpeg
      _convert_audio_file(tgt_path, tst_path, encoder="pcm_f32le")
      # 2.3. Load with SciPy
      found = load_wav(tst_path, normalize=False)[0]
  
      # 3.1. Convert the original wav to target format with ffmpeg
      muxer, encoder, sample_fmt = _parse_save_args(
          ext, format, encoding, bits_per_sample
      )
      _convert_audio_file(
          src_path,
          sox_path,
          muxer=muxer,
          encoder=encoder,
          sample_fmt=sample_fmt,
      )
      # 3.2. Convert the target format to wav with ffmpeg
      _convert_audio_file(sox_path, ref_path, encoder="pcm_f32le")
      # 3.3. Load with SciPy
      expected = load_wav(ref_path, normalize=False)[0]
  
      self.assertEqual(found, expected)
  
imports: import io
  import os
  import pathlib
  import subprocess
  import sys
  from functools import partial
  from typing import Optional
  import torch
  from parameterized import parameterized
  from torchaudio._backend.ffmpeg import _parse_save_args
  from torchaudio._backend.utils import get_save_func
  from torchaudio.io import CodecConfig
  from torchaudio_unittest.backend.dispatcher.sox.common import get_enc_params, name_func
  from torchaudio_unittest.common_utils import disabledInCI, get_wav_data, load_wav, nested_params, PytorchTestCase, save_wav, skipIfNoExec, skipIfNoFFmpeg, TempDirMixin, TorchaudioTestCase
label_desc: Use image node_id 1 for calling the SaveTestBase obj's underlying member method code with example usage: obj.assert_save_consistency(format) without return types