//  [python]
def torch_calc_spectrograms(waves, window_lengths, spectral_diffs=(0, 1),
                      window_name='hann', use_mel_scale=True,
                      proj_method='matmul', num_spec_bins=256,
                      random_crop=True):
    """Calculate spectrograms with multiple window sizes for list of input waves.

    Args:
      waves: List of float tensors of shape [batch, length] or [batch, length, 1].
      window_lengths: List of Int. Window sizes (frame lengths) to use for
        computing the spectrograms.
      spectral_diffs: Int. order of finite diff. to take before computing specs.
      window_name: Str. Name of the window to use when computing the spectrograms.
        Supports 'hann' and None.
      use_mel_scale: Bool. Whether or not to project to mel-scale frequencies.
      proj_method: Str. Spectral projection method implementation to use.
        Supported are 'fft' and 'matmul'.
      num_spec_bins: Int. Number of bins in the spectrogram.
      random_crop: Bool. Take random crop or not.

    Returns:
      Tuple of lists of magnitude spectrograms, with output[i][j] being the
        spectrogram for input wave i, computed for window length j.
    """
    # waves = [tf.squeeze(w, axis=-1) for w in waves]
    waves = [torch.squeeze(w, dim=-1) for w in waves]

    if window_name == 'hann':
        # windows = [tf.reshape(tf.signal.hann_window(wl, periodic=False), [1, 1, -1])
        #            for wl in window_lengths]
        windows = [torch.reshape(torch.from_numpy(W.hann(wl)), [1, 1, -1])
                   for wl in window_lengths]
    elif window_name is None:
        windows = [None] * len(window_lengths)
    else:
        raise ValueError('Unknown window function (%s).' % window_name)

    spec_len_wave = []
    for d in spectral_diffs:
        for length, window in zip(window_lengths, windows):

            wave_crops = waves
            for _ in range(d):
                wave_crops = [w[:, 1:] - w[:, :-1] for w in wave_crops]

            if random_crop:
                # wave_crops = aligned_random_crop(wave_crops, length)
                wave_crops = torch_aligned_random_crop(wave_crops, length)

            # frames = [tf.signal.frame(wc, length, length // 2) for wc in wave_crops]
            frames = [torch.tensor(librosa.util.frame(wc.numpy(),length,length//2)) for wc in wave_crops]
            # TODO: Whether this method is feasible (in the gradient part) remains to be verified
            if window is not None:
                frames = [f * window for f in frames]

            if proj_method == 'fft':
                # ffts = [tf.signal.rfft(f)[:, :, 1:] for f in frames]
                ffts = [torch.rfft(f,signal_ndim=1)[:, :, 1:] for f in frames]
            elif proj_method == 'matmul':
                # mat = get_spectral_matrix(length, num_spec_bins=num_spec_bins,
                #                           use_mel_scale=use_mel_scale)
                # ffts = [matmul_real_with_complex(f, mat) for f in frames]
                mat = torch_get_spectral_matrix(length, num_spec_bins=num_spec_bins,
                                          use_mel_scale=use_mel_scale)
                ffts = [torch_matmul_real_with_complex(f, mat) for f in frames]

            #sq_mag = lambda x: tf.square(tf.math.real(x)) + tf.square(tf.math.imag(x))
            sq_mag = lambda x: (torch.view_as_real(x)[:,0])**2 + (torch.view_as_real(x)[:,1])**2
            # torch.view_as_real() opreation need the last release edition of Pytorch 1.6.0
            specs_sq = [sq_mag(f) for f in ffts]

            if use_mel_scale and proj_method == 'fft':
                sample_rate = 24000
                upper_edge_hertz = sample_rate / 2.
                lower_edge_hertz = sample_rate / length
                # lin_to_mel = tf.signal.linear_to_mel_weight_matrix(
                #     num_mel_bins=num_spec_bins,
                #     num_spectrogram_bins=length // 2 + 1,
                #     sample_rate=sample_rate,
                #     lower_edge_hertz=lower_edge_hertz,
                #     upper_edge_hertz=upper_edge_hertz,
                #     dtype=tf.dtypes.float32)[1:]
                # specs_sq = [tf.matmul(s, lin_to_mel) for s in specs_sq]
                lin_to_mel = torch_build_mel_basis(
                    num_mel_bins=num_spec_bins,
                    num_spectrogram_bins=length,
                    sample_rate=sample_rate,
                    lower_edge_hertz=lower_edge_hertz,
                    upper_edge_hertz=upper_edge_hertz,
                    dtype=torch.float32)
                # TODO: I use librosa to build the mel filters here to instead, and i'm not sure whether this method works or not
                specs_sq = [torch.matmul(s, lin_to_mel) for s in specs_sq]

            # specs = [tf.sqrt(s+EPSILON) for s in specs_sq]
            specs = [torch.sqrt(s+EPSILON) for s in specs_sq]

            spec_len_wave.append(specs)

    spec_wave_len = zip(*spec_len_wave)
    return spec_wave_len