
    AVhaN                     b   d Z ddlZddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	 ddlm
Z
 dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ  ed      ej*                  dej,                  ddfd              Z ed      ej*                  ej,                  dfd              Z ed      ej*                  dej,                  dfd              Zd Z ed      ej*                  ej6                  dddfd              Z ed      ej*                  ej6                  ddfd              Zy)z8Spectral operations (e.g. Short-time Fourier Transform).    N)constant_op)dtypes)ops)tensor_util)	array_ops)math_ops)dct_ops)fft_ops)reconstruction_ops)	shape_ops)
window_ops)dispatch)	tf_exportzsignal.stftFc                 n   t        j                  |d| ||g      5  t        j                  | d      } | j                  j	                  d       t        j                  |d      }|j                  j                  d       t        j                  |d      }|j                  j                  d       |t        |      }nt        j                  |d	      }t        j                  | |||
      }| |||j                        }||z  }t        j                  ||g      cddd       S # 1 sw Y   yxY w)aC  Computes the [Short-time Fourier Transform][stft] of `signals`.

  Implemented with TPU/GPU-compatible ops and supports gradients.

  Args:
    signals: A `[..., samples]` `float32`/`float64` `Tensor` of real-valued
      signals.
    frame_length: An integer scalar `Tensor`. The window length in samples.
    frame_step: An integer scalar `Tensor`. The number of samples to step.
    fft_length: An integer scalar `Tensor`. The size of the FFT to apply.
      If not provided, uses the smallest power of 2 enclosing `frame_length`.
    window_fn: A callable that takes a window length and a `dtype` keyword
      argument and returns a `[window_length]` `Tensor` of samples in the
      provided datatype. If set to `None`, no windowing is used.
    pad_end: Whether to pad the end of `signals` with zeros when the provided
      frame length and step produces a frame that lies partially past its end.
    name: An optional name for the operation.

  Returns:
    A `[..., frames, fft_unique_bins]` `Tensor` of `complex64`/`complex128`
    STFT values where `fft_unique_bins` is `fft_length // 2 + 1` (the unique
    components of the FFT).

  Raises:
    ValueError: If `signals` is not at least rank 1, `frame_length` is
      not scalar, or `frame_step` is not scalar.

  [stft]: https://en.wikipedia.org/wiki/Short-time_Fourier_transform
  stftsignalsname   frame_lengthr   
frame_stepN
fft_lengthpad_enddtype)r   
name_scopeconvert_to_tensorshapewith_rank_at_leastassert_has_rank_enclosing_power_of_twor   framer   r
   rfft)	r   r   r   r   	window_fnr   r   framed_signalswindows	            Y/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/signal/spectral_ops.pyr   r   "   s   D ~~dFWl%/%1 2 6##G)<GMM$$Q'((NKL&&q)&&zEJ$$Q'*<8j((,Gj__z7<N ^-A-ABfn <<516 6 6s   DD++D4zsignal.inverse_stft_window_fnc                       fd}|S )a4  Generates a window function that can be used in `inverse_stft`.

  Constructs a window that is equal to the forward window with a further
  pointwise amplitude correction.  `inverse_stft_window_fn` is equivalent to
  `forward_window_fn` in the case where it would produce an exact inverse.

  See examples in `inverse_stft` documentation for usage.

  Args:
    frame_step: An integer scalar `Tensor`. The number of samples to step.
    forward_window_fn: window_fn used in the forward transform, `stft`.
    name: An optional name for the operation.

  Returns:
    A callable that takes a window length and a `dtype` keyword argument and
      returns a `[window_length]` `Tensor` of samples in the provided datatype.
      The returned window is suitable for reconstructing original waveform in
      inverse_stft.
  c                    t        j                  dg      5  t        j                  d      }|j                  j	                  d       t        j                  | d      } | j                  j	                  d        | |      }t        j                  |      }|  |z   }t        j                  |d||z  | z
  fg      }t        j                  |||g      }t        j                  |dd      }t        j                  ||d	g      }t        j                  |||z  g      }||d
|  z  cd
d
d
       S # 1 sw Y   y
xY w)a`  Computes a window that can be used in `inverse_stft`.

    Args:
      frame_length: An integer scalar `Tensor`. The window length in samples.
      dtype: Data type of waveform passed to `stft`.

    Returns:
      A window suitable for reconstructing original waveform in `inverse_stft`.

    Raises:
      ValueError: If `frame_length` is not scalar, `forward_window_fn` is not a
      callable that takes a window length and a `dtype` keyword argument and
      returns a `[window_length]` `Tensor` of samples in the provided datatype
      `frame_step` is not scalar, or `frame_step` is not scalar.
    inverse_stft_window_fnr   r   r   r   r   T)keepdimsr   N)r   r   r   r   r!   r   squarer   padreshape
reduce_sumtile)	r   r   frame_step_forward_windowdenomoverlapsforward_window_fnr   r   s	         r(   inverse_stft_window_fn_innerz<inverse_stft_window_fn.<locals>.inverse_stft_window_fn_innerw   s0     
69J8K	L 3))*<Hk''***<nMl((+ )UCnoon-e =K/0hmmEQ;(>(M$N#OPe+'>?e!!%T:ennUXqM2e;(>'?@eeM\22!3 3 3s   DD77E  )r   r6   r   r7   s   ``` r(   r+   r+   _   s    0 3B 
&%    zsignal.inverse_stftc                 ^   t        j                  |d| g      5  t        j                  | d      } | j                  j	                  d       t        j                  |d      }|j                  j                  d       t        j                  |d      }|j                  j                  d       |t        |      }n2t        j                  |d	      }|j                  j                  d       t        j                  | |g      }t        j                  |      }|3|j                  j                  |j                  j                         d
   |dd|f   }t        j                  |      }t        j                  |      }	t        j                  t        j                   |dz
  dg|j"                        dt%        j&                  d||	d
   z
        gggd      }
t        j(                  ||
      }n|j                  j                         d
   |kD  r
|dd|f   }ny|j                  j                         d
   |k  rY||j                  j                         d
   z
  }t        j(                  |ddgg|j                  j                  dz
  z  d|ggz         }|F|j                  j                  0|j+                  dg|j                  j                  dz
  z  |gz          |# ||| j"                  j,                        }||z  }t/        j0                  ||      cddd       S # 1 sw Y   yxY w)aF	  Computes the inverse [Short-time Fourier Transform][stft] of `stfts`.

  To reconstruct an original waveform, a complementary window function should
  be used with `inverse_stft`. Such a window function can be constructed with
  `tf.signal.inverse_stft_window_fn`.
  Example:

  ```python
  frame_length = 400
  frame_step = 160
  waveform = tf.random.normal(dtype=tf.float32, shape=[1000])
  stft = tf.signal.stft(waveform, frame_length, frame_step)
  inverse_stft = tf.signal.inverse_stft(
      stft, frame_length, frame_step,
      window_fn=tf.signal.inverse_stft_window_fn(frame_step))
  ```

  If a custom `window_fn` is used with `tf.signal.stft`, it must be passed to
  `tf.signal.inverse_stft_window_fn`:

  ```python
  frame_length = 400
  frame_step = 160
  window_fn = tf.signal.hamming_window
  waveform = tf.random.normal(dtype=tf.float32, shape=[1000])
  stft = tf.signal.stft(
      waveform, frame_length, frame_step, window_fn=window_fn)
  inverse_stft = tf.signal.inverse_stft(
      stft, frame_length, frame_step,
      window_fn=tf.signal.inverse_stft_window_fn(
         frame_step, forward_window_fn=window_fn))
  ```

  Implemented with TPU/GPU-compatible ops and supports gradients.

  Args:
    stfts: A `complex64`/`complex128` `[..., frames, fft_unique_bins]`
      `Tensor` of STFT bins representing a batch of `fft_length`-point STFTs
      where `fft_unique_bins` is `fft_length // 2 + 1`
    frame_length: An integer scalar `Tensor`. The window length in samples.
    frame_step: An integer scalar `Tensor`. The number of samples to step.
    fft_length: An integer scalar `Tensor`. The size of the FFT that produced
      `stfts`. If not provided, uses the smallest power of 2 enclosing
      `frame_length`.
    window_fn: A callable that takes a window length and a `dtype` keyword
      argument and returns a `[window_length]` `Tensor` of samples in the
      provided datatype. If set to `None`, no windowing is used.
    name: An optional name for the operation.

  Returns:
    A `[..., samples]` `Tensor` of `float32`/`float64` signals representing
    the inverse STFT for each input STFT in `stfts`.

  Raises:
    ValueError: If `stfts` is not at least rank 2, `frame_length` is not scalar,
      `frame_step` is not scalar, or `fft_length` is not scalar.

  [stft]: https://en.wikipedia.org/wiki/Short-time_Fourier_transform
  inverse_stftstftsr      r   r   r   Nr   .r   r   )r   r   r   r   r    r!   r"   r
   irfftr   constant_valuendimsas_listr   rankconcatzerosr   r   maximumr.   	set_shape
real_dtyper   overlap_and_add)r<   r   r   r   r%   r   real_framesframe_length_staticreal_frames_rankreal_frames_shapepaddings
pad_amountr'   s                r(   r;   r;      s   F ~~dNUG4 4G!!%g6E	KK""1%((NKL&&q)&&zEJ$$Q'*<8j((,Gj&&q)--
|4K &44\B 	#{'8'8'>'>'F!!#B'/]l] 23k"4#//+6!!??,q0!4!-!3!35  L3DR3H$HIJKMNOQh MM+x8k 
			"	"	$R	(+>	>%9&9%9 9:k				"	"	$R	(+>	>&):):)B)B)DR)HHjMM+$%q6(k.?.?.E.E.I"J$%z?"3#45k &;+<+<+B+B+NTFk&7&7&=&=&AB012 3
 U[[-C-CDfVk--k:Fi4G 4G 4Gs   L L##L,c                 $   t        j                  |       }|ht        j                  t	        dt        j                  t        j                  |      t        j                  d      z        z        | j                        S t        j                  t        j                  dt        j                  t        j                  t        j                  | t        j                              t        j                  d      z              | j                        S )z2Return 2**N for integer N such that 2**N >= value.r=   g       @)r   r@   r   constantintnpceillogr   r   castpowr   float32)valuevalue_statics     r(   r"   r"     s    ++E2,Arwwrvvl+bffSk9::;U[[J J	ll

--ll8==?@ll3 !" $);;
0 0r9   zsignal.mdctc                    t        j                  |d| |g      5  t        j                  | d      } | j                  j	                  d       t        j                  |d      }|j                  j                  d       t        j                  |      }|8|dz  dk7  rt        d	      t        j                  |d
z  |j                        }n|d
z  }t        j                  | |||      }| |||j                        }	||	z  }n|dt        j                  d
      z  z  }t        j                  |dd      }
t        j                   |
d
   dg       |
d   z
  }|
d   t        j                   |
d   dg      z
  }t        j"                  ||fd      }t%        j&                  |d|      cddd       S # 1 sw Y   yxY w)a  Computes the [Modified Discrete Cosine Transform][mdct] of `signals`.

  Implemented with TPU/GPU-compatible ops and supports gradients.

  Args:
    signals: A `[..., samples]` `float32`/`float64` `Tensor` of real-valued
      signals.
    frame_length: An integer scalar `Tensor`. The window length in samples
      which must be divisible by 4.
    window_fn: A callable that takes a frame_length and a `dtype` keyword
      argument and returns a `[frame_length]` `Tensor` of samples in the
      provided datatype. If set to `None`, a rectangular window with a scale of
      1/sqrt(2) is used. For perfect reconstruction of a signal from `mdct`
      followed by `inverse_mdct`, please use `tf.signal.vorbis_window`,
      `tf.signal.kaiser_bessel_derived_window` or `None`. If using another
      window function, make sure that w[n]^2 + w[n + frame_length // 2]^2 = 1
      and w[n] = w[frame_length - n - 1] for n = 0,...,frame_length // 2 - 1 to
      achieve perfect reconstruction.
    pad_end: Whether to pad the end of `signals` with zeros when the provided
      frame length and step produces a frame that lies partially past its end.
    norm: If it is None, unnormalized dct4 is used, if it is "ortho"
      orthonormal dct4 is used.
    name: An optional name for the operation.

  Returns:
    A `[..., frames, frame_length // 2]` `Tensor` of `float32`/`float64`
    MDCT values where `frames` is roughly `samples // (frame_length // 2)`
    when `pad_end=False`.

  Raises:
    ValueError: If `signals` is not at least rank 1, `frame_length` is
      not scalar, or `frame_length` is not a multiple of `4`.

  [mdct]: https://en.wikipedia.org/wiki/Modified_discrete_cosine_transform
  mdctr   r   r   r   r   N   z)The frame length must be a multiple of 4.r=   r   r         ?r>   axis   typenorm)r   r   r   r   r    r!   r   r@   
ValueErrorr   r   r#   rS   sqrtr   splitreverserD   r	   dct)r   r   r%   r   rd   r   rK   r   r&   r'   split_framesframe_firsthalfframe_secondhalfframes_rearrangeds                 r(   r\   r\   #  s   N ~~dFWl$;< "=##G)<GMM$$Q'((NKL&&q)%44\B&	q	 A	%DEE(()<)A/;/A/ACj  1$j__z7<N ^-A-ABfnbggaj((n??>12>L ((a*,/ /1=aAO#A):):<?<>4*A A!((/;K)L.02 ;;(qt<E"= "= "=s   FF66F?zsignal.inverse_mdctc           	      Z   t        j                  |d| g      5  t        j                  | d      } | j                  j	                  d       t        j                  | j                  d   t        j                        }|?t        j                  || j                        }d|z  t        j                  | d	
      z  }n|dk(  rt        j                  | d	d      }t        j                  dd      }t        j                  |d   t        j                  |d   dg       t        j                  |d   dg       |d    fd      }| |d|z  | j                        }	||	z  }n|dt!        j"                  d      z  z  }t%        j&                  ||      cddd       S # 1 sw Y   yxY w)aU	  Computes the inverse modified DCT of `mdcts`.

  To reconstruct an original waveform, the same window function should
  be used with `mdct` and `inverse_mdct`.

  Example usage:

  >>> @tf.function
  ... def compare_round_trip():
  ...   samples = 1000
  ...   frame_length = 400
  ...   halflen = frame_length // 2
  ...   waveform = tf.random.normal(dtype=tf.float32, shape=[samples])
  ...   waveform_pad = tf.pad(waveform, [[halflen, 0],])
  ...   mdct = tf.signal.mdct(waveform_pad, frame_length, pad_end=True,
  ...                         window_fn=tf.signal.vorbis_window)
  ...   inverse_mdct = tf.signal.inverse_mdct(mdct,
  ...                                         window_fn=tf.signal.vorbis_window)
  ...   inverse_mdct = inverse_mdct[halflen: halflen + samples]
  ...   return waveform, inverse_mdct
  >>> waveform, inverse_mdct = compare_round_trip()
  >>> np.allclose(waveform.numpy(), inverse_mdct.numpy(), rtol=1e-3, atol=1e-4)
  True

  Implemented with TPU/GPU-compatible ops and supports gradients.

  Args:
    mdcts: A `float32`/`float64` `[..., frames, frame_length // 2]`
      `Tensor` of MDCT bins representing a batch of `frame_length // 2`-point
      MDCTs.
    window_fn: A callable that takes a frame_length and a `dtype` keyword
      argument and returns a `[frame_length]` `Tensor` of samples in the
      provided datatype. If set to `None`, a rectangular window with a scale of
      1/sqrt(2) is used. For perfect reconstruction of a signal from `mdct`
      followed by `inverse_mdct`, please use `tf.signal.vorbis_window`,
      `tf.signal.kaiser_bessel_derived_window` or `None`. If using another
      window function, make sure that w[n]^2 + w[n + frame_length // 2]^2 = 1
      and w[n] = w[frame_length - n - 1] for n = 0,...,frame_length // 2 - 1 to
      achieve perfect reconstruction.
    norm: If "ortho", orthonormal inverse DCT4 is performed, if it is None,
      a regular dct4 followed by scaling of `1/frame_length` is performed.
    name: An optional name for the operation.

  Returns:
    A `[..., samples]` `Tensor` of `float32`/`float64` signals representing
    the inverse MDCT for each input MDCT in `mdcts` where `samples` is
    `(frames - 1) * (frame_length // 2) + frame_length`.

  Raises:
    ValueError: If `mdcts` is not at least rank 2.

  [mdct]: https://en.wikipedia.org/wiki/Modified_discrete_cosine_transform
  inverse_mdctmdctsr   r=   r>   r   Ng      ?r]   )rc   orthorb   r_   r   r   r^   )r   r   r   r   r    r   rV   r   int32r   r	   ri   r   rg   rD   rh   rS   rf   r   rI   )
rp   r%   rd   r   half_lenhalf_len_floatresult_idct4split_resultrJ   r'   s
             r(   ro   ro   o  sx   v ~~dNUG4 E!!%g6E	KK""1%}}U[[_FLLAH|}}XU[[AnN*gkk%a.HHl	[[QW=l??<<L""LO%.%6%6|A%M$M%.%6%6|A%M$M%1!_$4$6 =?@K XU[[9fVkS2771:%%k--k8D/E E Es   E>F!!F*)__doc__numpyrS   tensorflow.python.frameworkr   r   r   r   tensorflow.python.opsr   r   tensorflow.python.ops.signalr	   r
   r   r   r   tensorflow.python.utilr    tensorflow.python.util.tf_exportr   add_dispatch_supporthann_windowr   r+   r;   r"   vorbis_windowr\   ro   r8   r9   r(   <module>r      sZ   ?  3 . + 3 + * 0 0 ; 2 3 + 6 =	7;))T86  86v *+	-7-C-C $7&  ,7&t  !	 !%11uG  "uGp0 =	*4*B*BTG=  G=T  !	%33PE  "PEr9   