From ea05b6a30ac7cc51bfe4de11954863355a5780f4 Mon Sep 17 00:00:00 2001 From: zty-king <17786324919@163.com> Date: Wed, 5 Nov 2025 09:43:05 +0000 Subject: [PATCH 1/8] align_window_func_with_torch --- python/paddle/__init__.py | 7 ++ python/paddle/audio/functional/window.py | 85 ++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/python/paddle/__init__.py b/python/paddle/__init__.py index 29109ac151ccce..b79a4351b97084 100644 --- a/python/paddle/__init__.py +++ b/python/paddle/__init__.py @@ -226,6 +226,13 @@ def new_init(self, *args, **kwargs): get_autocast_gpu_dtype, is_autocast_enabled, ) +from .audio.functional.window import ( # noqa: F401 + bartlett_window, + blackman_window, + hamming_window, + hann_window, + kaiser_window, +) from .autograd import ( enable_grad, grad, diff --git a/python/paddle/audio/functional/window.py b/python/paddle/audio/functional/window.py index d0725ea9b7a741..052b7a29b6e3c8 100644 --- a/python/paddle/audio/functional/window.py +++ b/python/paddle/audio/functional/window.py @@ -445,3 +445,88 @@ def get_window( params = (win_length, *args) kwargs = {'sym': sym} return winfunc(*params, dtype=dtype, **kwargs) + + +def hamming_window( + window_length: int, + periodic: bool = True, + alpha: float = 0.54, + beta: float = 0.46, + *, + dtype: str = 'float64', + layout: None | object = None, + device: None | object = None, + pin_memory: None | bool = None, + requires_grad: None | bool = None, +): + w = get_window('hamming', window_length, fftbins=periodic, dtype=dtype) + if requires_grad is not None: + w.stop_gradient = not requires_grad + return w + + +def hann_window( + window_length: int, + periodic: bool = True, + *, + dtype: str = 'float64', + layout: None | object = None, + device: None | object = None, + pin_memory: None | bool = None, + requires_grad: None | bool = None, +): + w = get_window('hann', window_length, fftbins=periodic, dtype=dtype) + if requires_grad is not None: + w.stop_gradient = not requires_grad + return w + + +def kaiser_window( + window_length: int, + periodic: bool = True, + beta: float = 12.0, + *, + dtype: str = 'float64', + layout: None | object = None, + device: None | object = None, + pin_memory: None | bool = None, + requires_grad: None | bool = None, +): + w = get_window( + ('kaiser', beta), window_length, fftbins=periodic, dtype=dtype + ) + if requires_grad is not None: + w.stop_gradient = not requires_grad + return w + + +def blackman_window( + window_length: int, + periodic: bool = True, + *, + dtype: str = 'float64', + layout: None | object = None, + device: None | object = None, + pin_memory: None | bool = None, + requires_grad: None | bool = None, +): + w = get_window('blackman', window_length, fftbins=periodic, dtype=dtype) + if requires_grad is not None: + w.stop_gradient = not requires_grad + return w + + +def bartlett_window( + window_length: int, + periodic: bool = True, + *, + dtype: str = 'float64', + layout: None | object = None, + device: None | object = None, + pin_memory: None | bool = None, + requires_grad: None | bool = None, +): + w = get_window('bartlett', window_length, fftbins=periodic, dtype=dtype) + if requires_grad is not None: + w.stop_gradient = not requires_grad + return w From 755f1d2af1f517a75c78746a240299c40e7e4e8a Mon Sep 17 00:00:00 2001 From: zty-king <17786324919@163.com> Date: Thu, 6 Nov 2025 16:38:52 +0000 Subject: [PATCH 2/8] adapt the parameters --- python/paddle/__init__.py | 7 ++ python/paddle/audio/functional/window.py | 111 +++++++++++++++++------ test/legacy_test/CMakeLists.txt | 1 + 3 files changed, 93 insertions(+), 26 deletions(-) diff --git a/python/paddle/__init__.py b/python/paddle/__init__.py index 2fb61ae2731d23..34ab2f39b6f045 100644 --- a/python/paddle/__init__.py +++ b/python/paddle/__init__.py @@ -227,6 +227,13 @@ def new_init(self, *args, **kwargs): is_autocast_enabled, ) from .amp.auto_cast import autocast +from .audio.functional.window import ( # noqa: F401 + bartlett_window, + blackman_window, + hamming_window, + hann_window, + kaiser_window, +) from .autograd import ( enable_grad, grad, diff --git a/python/paddle/audio/functional/window.py b/python/paddle/audio/functional/window.py index 052b7a29b6e3c8..b9b1de5d194243 100644 --- a/python/paddle/audio/functional/window.py +++ b/python/paddle/audio/functional/window.py @@ -13,6 +13,7 @@ from __future__ import annotations import math +import warnings from typing import TYPE_CHECKING import numpy as np @@ -447,6 +448,40 @@ def get_window( return winfunc(*params, dtype=dtype, **kwargs) +def _apply_window_postprocess( + w: Tensor, + *, + layout: str | None = None, + device: str | None = None, + pin_memory: None | bool, + requires_grad: None | bool, +) -> Tensor: + if layout is not None: + warnings.warn("layout only supports 'strided' in Paddle; ignored") + + # device: accept PlaceLike strings like 'cpu', 'gpu:0', 'cuda:0' + if device is not None: + dev = str(device).lower() + if dev.startswith('cuda') or dev.startswith('gpu'): + idx = 0 + if ':' in dev: + try: + idx = int(dev.split(':', 1)[1]) + except ValueError: + idx = 0 + w = w.cuda(idx) + elif dev == 'cpu': + w = w.cpu() + + if pin_memory: + if w.place.is_cpu_place(): + w = w.pin_memory() + + if requires_grad is not None: + w.stop_gradient = not requires_grad + return w + + def hamming_window( window_length: int, periodic: bool = True, @@ -454,15 +489,23 @@ def hamming_window( beta: float = 0.46, *, dtype: str = 'float64', - layout: None | object = None, - device: None | object = None, + layout: str | None = None, + device: str | None = None, pin_memory: None | bool = None, requires_grad: None | bool = None, ): - w = get_window('hamming', window_length, fftbins=periodic, dtype=dtype) - if requires_grad is not None: - w.stop_gradient = not requires_grad - return w + w0 = get_window('hamming', window_length, fftbins=periodic, dtype=dtype) + alpha0, beta0 = 0.54, 0.46 + B = beta / beta0 + A = alpha - B * alpha0 + w = A + B * w0 + return _apply_window_postprocess( + w, + layout=layout, + device=device, + pin_memory=pin_memory, + requires_grad=requires_grad, + ) def hann_window( @@ -470,15 +513,19 @@ def hann_window( periodic: bool = True, *, dtype: str = 'float64', - layout: None | object = None, - device: None | object = None, + layout: str | None = None, + device: str | None = None, pin_memory: None | bool = None, requires_grad: None | bool = None, ): w = get_window('hann', window_length, fftbins=periodic, dtype=dtype) - if requires_grad is not None: - w.stop_gradient = not requires_grad - return w + return _apply_window_postprocess( + w, + layout=layout, + device=device, + pin_memory=pin_memory, + requires_grad=requires_grad, + ) def kaiser_window( @@ -487,17 +534,21 @@ def kaiser_window( beta: float = 12.0, *, dtype: str = 'float64', - layout: None | object = None, - device: None | object = None, + layout: str | None = None, + device: str | None = None, pin_memory: None | bool = None, requires_grad: None | bool = None, ): w = get_window( ('kaiser', beta), window_length, fftbins=periodic, dtype=dtype ) - if requires_grad is not None: - w.stop_gradient = not requires_grad - return w + return _apply_window_postprocess( + w, + layout=layout, + device=device, + pin_memory=pin_memory, + requires_grad=requires_grad, + ) def blackman_window( @@ -505,15 +556,19 @@ def blackman_window( periodic: bool = True, *, dtype: str = 'float64', - layout: None | object = None, - device: None | object = None, + layout: str | None = None, + device: str | None = None, pin_memory: None | bool = None, requires_grad: None | bool = None, ): w = get_window('blackman', window_length, fftbins=periodic, dtype=dtype) - if requires_grad is not None: - w.stop_gradient = not requires_grad - return w + return _apply_window_postprocess( + w, + layout=layout, + device=device, + pin_memory=pin_memory, + requires_grad=requires_grad, + ) def bartlett_window( @@ -521,12 +576,16 @@ def bartlett_window( periodic: bool = True, *, dtype: str = 'float64', - layout: None | object = None, - device: None | object = None, + layout: str | None = None, + device: str | None = None, pin_memory: None | bool = None, requires_grad: None | bool = None, ): w = get_window('bartlett', window_length, fftbins=periodic, dtype=dtype) - if requires_grad is not None: - w.stop_gradient = not requires_grad - return w + return _apply_window_postprocess( + w, + layout=layout, + device=device, + pin_memory=pin_memory, + requires_grad=requires_grad, + ) diff --git a/test/legacy_test/CMakeLists.txt b/test/legacy_test/CMakeLists.txt index cfe51c6341eaa4..c96a89fa86fb51 100644 --- a/test/legacy_test/CMakeLists.txt +++ b/test/legacy_test/CMakeLists.txt @@ -875,6 +875,7 @@ set_tests_properties(test_profiler PROPERTIES TIMEOUT 120) set_tests_properties(test_cross_entropy_loss PROPERTIES TIMEOUT 180) set_tests_properties(test_activation_nn_grad PROPERTIES TIMEOUT 250) set_tests_properties(test_empty_op PROPERTIES TIMEOUT 120) +set_tests_properties(test_align_torch_window_func PROPERTIES TIMEOUT 10) set_tests_properties(test_elementwise_div_op PROPERTIES TIMEOUT 120) set_tests_properties(test_multiclass_nms_op PROPERTIES TIMEOUT 120) if(NOT WIN32) From 747eba5959dcfdde38b6679c27d7f381b789f7cc Mon Sep 17 00:00:00 2001 From: zty-king <17786324919@163.com> Date: Fri, 7 Nov 2025 03:48:51 +0000 Subject: [PATCH 3/8] add test --- .../test_align_torch_window_func.py | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 test/legacy_test/test_align_torch_window_func.py diff --git a/test/legacy_test/test_align_torch_window_func.py b/test/legacy_test/test_align_torch_window_func.py new file mode 100644 index 00000000000000..e5aef8be21435d --- /dev/null +++ b/test/legacy_test/test_align_torch_window_func.py @@ -0,0 +1,185 @@ +# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import paddle +from paddle.audio.functional.window import get_window + + +def _has_cuda(): + return ( + paddle.is_compiled_with_cuda() and "gpu" in paddle.device.get_device() + ) + + +class TestWindowFunctions(unittest.TestCase): + def setUp(self): + paddle.set_device("cpu") + + def test_hamming_alpha_beta_transform_and_requires_grad(self): + N = 16 + w0 = get_window('hamming', N, fftbins=True, dtype='float64') + + # Custom alpha/beta, verify linear transformation A + B * w0 + alpha, beta = 0.60, 0.40 + w = paddle.hamming_window( + N, + periodic=True, + alpha=alpha, + beta=beta, + dtype='float64', + requires_grad=True, + ) + self.assertEqual(w.dtype, paddle.float64) + self.assertFalse(w.stop_gradient) + # Linear equivalence: w ≈ A + B * w0 + alpha0, beta0 = 0.54, 0.46 + B = beta / beta0 + A = alpha - B * alpha0 + self.assertTrue(paddle.allclose(w, A + B * w0, atol=1e-12)) + + def test_hamming_layout_warning_and_pin_memory_cpu(self): + N = 8 + # Pass layout != None to trigger warning branch (ignored) + w = paddle.hamming_window( + N, + periodic=False, + alpha=0.54, + beta=0.46, + dtype='float32', + layout='strided', + device='cpu', + pin_memory=True, + requires_grad=False, + ) + self.assertEqual(w.dtype, paddle.float32) + self.assertTrue(w.stop_gradient) + self.assertEqual(list(w.shape), [N]) + + @unittest.skipUnless(_has_cuda(), "GPU not available") + def test_hamming_device_gpu(self): + N = 12 + # Explicitly set device to cuda:0 / gpu:0 should work (PlaceLike supports str) + w = paddle.hamming_window( + N, + periodic=True, + alpha=0.54, + beta=0.46, + dtype='float32', + layout=None, + device='gpu:0', + pin_memory=False, + requires_grad=None, + ) + self.assertEqual(list(w.shape), [N]) + self.assertIn('gpu', str(w.place)) + + def test_hann_basic_paths(self): + N = 10 + # Pass layout=None; set requires_grad=True + w = paddle.hann_window( + N, + periodic=True, + dtype='float64', + layout=None, + device='cpu', + pin_memory=None, + requires_grad=True, + ) + self.assertEqual(list(w.shape), [N]) + self.assertFalse(w.stop_gradient) + + # Test layout != None and pin_memory=True branches + w2 = paddle.hann_window( + N, + periodic=False, + dtype='float32', + layout='strided', + device='cpu', + pin_memory=True, + requires_grad=False, + ) + self.assertEqual(w2.dtype, paddle.float32) + self.assertTrue(w2.stop_gradient) + + def test_blackman_and_bartlett_basic(self): + N = 9 + wb = paddle.blackman_window( + N, + periodic=True, + dtype='float64', + layout=None, + device=None, + pin_memory=None, + requires_grad=None, + ) + self.assertEqual(list(wb.shape), [N]) + + wl = paddle.bartlett_window( + N, + periodic=False, + dtype='float32', + layout='strided', + device='cpu', + pin_memory=True, + requires_grad=True, + ) + self.assertEqual(list(wl.shape), [N]) + self.assertFalse(wl.stop_gradient) + + def test_kaiser_beta_and_paths(self): + N = 7 + beta = 6.0 + w = paddle.kaiser_window( + N, + periodic=True, + beta=beta, + dtype='float64', + layout=None, + device=None, + pin_memory=None, + requires_grad=None, + ) + self.assertEqual(list(w.shape), [N]) + + # Test layout != None + pin_memory + requires_grad + w2 = paddle.kaiser_window( + N, + periodic=False, + beta=8.0, + dtype='float32', + layout='strided', + device='cpu', + pin_memory=True, + requires_grad=False, + ) + self.assertEqual(w2.dtype, paddle.float32) + self.assertTrue(w2.stop_gradient) + + def test_hamming_periodic_vs_symmetric(self): + # Test periodic True/False length handling (DFT symmetry/periodic) + N = 11 + w_per = paddle.hamming_window( + N, periodic=True, alpha=0.54, beta=0.46, dtype='float64' + ) + w_sym = paddle.hamming_window( + N, periodic=False, alpha=0.54, beta=0.46, dtype='float64' + ) + self.assertEqual(list(w_per.shape), [N]) + self.assertEqual(list(w_sym.shape), [N]) + + +if __name__ == '__main__': + unittest.main() From 86055aef4ffa6885a55b8a7f66c2394eefb0d5e9 Mon Sep 17 00:00:00 2001 From: zty-king <17786324919@163.com> Date: Fri, 7 Nov 2025 11:30:15 +0000 Subject: [PATCH 4/8] fix the cpu_only_paddle --- .../test_align_torch_window_func.py | 46 ++++++++----------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/test/legacy_test/test_align_torch_window_func.py b/test/legacy_test/test_align_torch_window_func.py index e5aef8be21435d..22982a7e8acb64 100644 --- a/test/legacy_test/test_align_torch_window_func.py +++ b/test/legacy_test/test_align_torch_window_func.py @@ -50,7 +50,7 @@ def test_hamming_alpha_beta_transform_and_requires_grad(self): A = alpha - B * alpha0 self.assertTrue(paddle.allclose(w, A + B * w0, atol=1e-12)) - def test_hamming_layout_warning_and_pin_memory_cpu(self): + def test_hamming_layout_warning(self): N = 8 # Pass layout != None to trigger warning branch (ignored) w = paddle.hamming_window( @@ -61,7 +61,6 @@ def test_hamming_layout_warning_and_pin_memory_cpu(self): dtype='float32', layout='strided', device='cpu', - pin_memory=True, requires_grad=False, ) self.assertEqual(w.dtype, paddle.float32) @@ -69,22 +68,23 @@ def test_hamming_layout_warning_and_pin_memory_cpu(self): self.assertEqual(list(w.shape), [N]) @unittest.skipUnless(_has_cuda(), "GPU not available") - def test_hamming_device_gpu(self): - N = 12 - # Explicitly set device to cuda:0 / gpu:0 should work (PlaceLike supports str) - w = paddle.hamming_window( - N, - periodic=True, - alpha=0.54, - beta=0.46, - dtype='float32', - layout=None, - device='gpu:0', - pin_memory=False, - requires_grad=None, - ) - self.assertEqual(list(w.shape), [N]) - self.assertIn('gpu', str(w.place)) + def test_hamming_device_gpu_pin_memory(self): + if paddle.is_compiled_with_cuda(): + N = 12 + # Explicitly set device to cuda:0 / gpu:0 should work (PlaceLike supports str) + w = paddle.hamming_window( + N, + periodic=True, + alpha=0.54, + beta=0.46, + dtype='float32', + layout=None, + device='gpu:0', + pin_memory=True, + requires_grad=None, + ) + self.assertEqual(list(w.shape), [N]) + self.assertIn('gpu', str(w.place)) def test_hann_basic_paths(self): N = 10 @@ -95,20 +95,18 @@ def test_hann_basic_paths(self): dtype='float64', layout=None, device='cpu', - pin_memory=None, requires_grad=True, ) self.assertEqual(list(w.shape), [N]) self.assertFalse(w.stop_gradient) - # Test layout != None and pin_memory=True branches + # Test layout != None w2 = paddle.hann_window( N, periodic=False, dtype='float32', layout='strided', device='cpu', - pin_memory=True, requires_grad=False, ) self.assertEqual(w2.dtype, paddle.float32) @@ -122,7 +120,6 @@ def test_blackman_and_bartlett_basic(self): dtype='float64', layout=None, device=None, - pin_memory=None, requires_grad=None, ) self.assertEqual(list(wb.shape), [N]) @@ -133,7 +130,6 @@ def test_blackman_and_bartlett_basic(self): dtype='float32', layout='strided', device='cpu', - pin_memory=True, requires_grad=True, ) self.assertEqual(list(wl.shape), [N]) @@ -149,12 +145,11 @@ def test_kaiser_beta_and_paths(self): dtype='float64', layout=None, device=None, - pin_memory=None, requires_grad=None, ) self.assertEqual(list(w.shape), [N]) - # Test layout != None + pin_memory + requires_grad + # Test layout != None + requires_grad w2 = paddle.kaiser_window( N, periodic=False, @@ -162,7 +157,6 @@ def test_kaiser_beta_and_paths(self): dtype='float32', layout='strided', device='cpu', - pin_memory=True, requires_grad=False, ) self.assertEqual(w2.dtype, paddle.float32) From a7457d0659ef1384985b6974dd3e48f40064fd38 Mon Sep 17 00:00:00 2001 From: zty-king <17786324919@163.com> Date: Wed, 12 Nov 2025 15:31:43 +0000 Subject: [PATCH 5/8] add comment --- python/paddle/audio/functional/window.py | 130 ++++++++++++++++++++++- 1 file changed, 125 insertions(+), 5 deletions(-) diff --git a/python/paddle/audio/functional/window.py b/python/paddle/audio/functional/window.py index b9b1de5d194243..82ccc6990e7133 100644 --- a/python/paddle/audio/functional/window.py +++ b/python/paddle/audio/functional/window.py @@ -492,8 +492,33 @@ def hamming_window( layout: str | None = None, device: str | None = None, pin_memory: None | bool = None, - requires_grad: None | bool = None, + requires_grad: bool = False, ): + """ + Compute a generalized Hamming window. + + Args: + window_length (int): The size of the returned window. Must be positive. + periodic (bool, optional): If True, returns a window for use as a periodic function; if False, returns a symmetric window. Defaults to True. + alpha (float, optional): The coefficient α in the equation above. Defaults to 0.54. + beta (float, optional): The coefficient β in the equation above. Defaults to 0.46. + dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. + layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. + device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). + pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. + requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + + Returns: + Tensor: A 1-D tensor of shape `(window_length,)` containing the Hamming window. + + Examples: + .. code-block:: python + + >>> import paddle + + >>> win = paddle.hamming_window(400, requires_grad=True) + >>> win = paddle.hamming_window(256, alpha=0.5, beta=0.5) + """ w0 = get_window('hamming', window_length, fftbins=periodic, dtype=dtype) alpha0, beta0 = 0.54, 0.46 B = beta / beta0 @@ -516,8 +541,31 @@ def hann_window( layout: str | None = None, device: str | None = None, pin_memory: None | bool = None, - requires_grad: None | bool = None, + requires_grad: bool = False, ): + """ + Compute a Hann window. + + Args: + window_length (int): The size of the returned window. Must be positive. + periodic (bool, optional): If True, returns a window for use as a periodic function; if False, returns a symmetric window. Defaults to True. + dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. + layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. + device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). + pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. + requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + + Returns: + Tensor: A 1-D tensor of shape `(window_length,)` containing the Hann window. + + Examples: + .. code-block:: python + + >>> import paddle + + >>> win = paddle.hann_window(512) + >>> win = paddle.hann_window(512, requires_grad=True) + """ w = get_window('hann', window_length, fftbins=periodic, dtype=dtype) return _apply_window_postprocess( w, @@ -537,8 +585,32 @@ def kaiser_window( layout: str | None = None, device: str | None = None, pin_memory: None | bool = None, - requires_grad: None | bool = None, + requires_grad: bool = False, ): + """ + Compute a Kaiser window. + + Args: + window_length (int): The size of the returned window. Must be positive. + periodic (bool, optional): If True, returns a window for use as a periodic function; if False, returns a symmetric window. Defaults to True. + beta (float, optional): Shape parameter for the window. Defaults to 12.0. + dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. + layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. + device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). + pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. + requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + + Returns: + Tensor: A 1-D tensor of shape `(window_length,)` containing the Kaiser window. + + Examples: + .. code-block:: python + + >>> import paddle + + >>> win = paddle.kaiser_window(400, beta=8.6) + >>> win = paddle.kaiser_window(400, requires_grad=True) + """ w = get_window( ('kaiser', beta), window_length, fftbins=periodic, dtype=dtype ) @@ -559,8 +631,31 @@ def blackman_window( layout: str | None = None, device: str | None = None, pin_memory: None | bool = None, - requires_grad: None | bool = None, + requires_grad: bool = False, ): + """ + Compute a Blackman window. + + Args: + window_length (int): The size of the returned window. Must be positive. + periodic (bool, optional): If True, returns a window for use as a periodic function; if False, returns a symmetric window. Defaults to True. + dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. + layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. + device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). + pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. + requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + + Returns: + Tensor: A 1-D tensor of shape `(window_length,)` containing the Blackman window. + + Examples: + .. code-block:: python + + >>> import paddle + + >>> win = paddle.blackman_window(256) + >>> win = paddle.blackman_window(256, requires_grad=True) + """ w = get_window('blackman', window_length, fftbins=periodic, dtype=dtype) return _apply_window_postprocess( w, @@ -579,8 +674,33 @@ def bartlett_window( layout: str | None = None, device: str | None = None, pin_memory: None | bool = None, - requires_grad: None | bool = None, + requires_grad: bool = False, ): + """ + Compute a Bartlett window. + + Args: + window_length (int): The size of the returned window. Must be positive. + periodic (bool, optional): If True, returns a window for use as a periodic function; if False, returns a symmetric window. Defaults to True. + dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. + layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. + device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). + pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. + requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + + Returns: + Tensor: A 1-D tensor of shape `(window_length,)` containing the Bartlett window. + + Examples: + .. code-block:: python + + >>> import paddle + + >>> n_fft = 512 + >>> win = paddle.bartlett_window(n_fft) + + >>> win = paddle.bartlett_window(n_fft, requires_grad=True) + """ w = get_window('bartlett', window_length, fftbins=periodic, dtype=dtype) return _apply_window_postprocess( w, From abc19916e903f2b837e103c374ab6e20d2924ac3 Mon Sep 17 00:00:00 2001 From: zty-king <17786324919@163.com> Date: Tue, 18 Nov 2025 05:21:42 +0000 Subject: [PATCH 6/8] fix the operate logic --- python/paddle/audio/functional/window.py | 125 +++++++++++------- test/legacy_test/CMakeLists.txt | 2 +- ...gn_torch_window_func.py => test_window.py} | 0 3 files changed, 78 insertions(+), 49 deletions(-) rename test/legacy_test/{test_align_torch_window_func.py => test_window.py} (100%) diff --git a/python/paddle/audio/functional/window.py b/python/paddle/audio/functional/window.py index 82ccc6990e7133..7a01d3aa510e2a 100644 --- a/python/paddle/audio/functional/window.py +++ b/python/paddle/audio/functional/window.py @@ -22,9 +22,17 @@ if TYPE_CHECKING: from paddle import Tensor + from paddle._typing import PlaceLike from ..features.layers import _WindowLiteral +from paddle.base.framework import ( + _current_expected_place, + _get_paddle_place, + core, + in_dynamic_or_pir_mode, +) + class WindowFunctionRegister: def __init__(self): @@ -452,33 +460,44 @@ def _apply_window_postprocess( w: Tensor, *, layout: str | None = None, - device: str | None = None, - pin_memory: None | bool, - requires_grad: None | bool, + device: PlaceLike | None = None, + pin_memory: bool = False, + requires_grad: bool = False, ) -> Tensor: if layout is not None: warnings.warn("layout only supports 'strided' in Paddle; ignored") - # device: accept PlaceLike strings like 'cpu', 'gpu:0', 'cuda:0' - if device is not None: - dev = str(device).lower() - if dev.startswith('cuda') or dev.startswith('gpu'): - idx = 0 - if ':' in dev: - try: - idx = int(dev.split(':', 1)[1]) - except ValueError: - idx = 0 - w = w.cuda(idx) - elif dev == 'cpu': - w = w.cpu() - - if pin_memory: - if w.place.is_cpu_place(): - w = w.pin_memory() - - if requires_grad is not None: - w.stop_gradient = not requires_grad + if in_dynamic_or_pir_mode(): + device = ( + _get_paddle_place(device) + if device is not None + else _current_expected_place() + ) + if ( + pin_memory + and paddle.in_dynamic_mode() + and device is not None + and not isinstance( + device, (core.CUDAPinnedPlace, core.XPUPinnedPlace) + ) + ): + if isinstance(device, core.CUDAPlace) or ( + isinstance(device, core.Place) and device.is_gpu_place() + ): + device = core.CUDAPinnedPlace() + elif isinstance(device, core.XPUPlace) or ( + isinstance(device, core.Place) and device.is_xpu_place() + ): + device = core.XPUPinnedPlace() + else: + raise RuntimeError( + f"Pinning memory is not supported for {device}" + ) + + if pin_memory and paddle.in_dynamic_mode(): + w = w.pin_memory() + if requires_grad is True: + w.stop_gradient = False return w @@ -490,8 +509,8 @@ def hamming_window( *, dtype: str = 'float64', layout: str | None = None, - device: str | None = None, - pin_memory: None | bool = None, + device: PlaceLike | None = None, + pin_memory: bool = False, requires_grad: bool = False, ): """ @@ -504,9 +523,11 @@ def hamming_window( beta (float, optional): The coefficient β in the equation above. Defaults to 0.46. dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. - device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). - pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. - requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + device(PlaceLike|None, optional): The desired device of returned tensor. + if None, uses the current device for the default tensor type (see paddle.device.set_device()). + device will be the CPU for CPU tensor types and the current CUDA device for CUDA tensor types. Default: None. + pin_memory(bool, optional): If set, return tensor would be allocated in the pinned memory. Works only for CPU tensors. Default: False + requires_grad(bool, optional): If autograd should record operations on the returned tensor. Default: False. Returns: Tensor: A 1-D tensor of shape `(window_length,)` containing the Hamming window. @@ -539,8 +560,8 @@ def hann_window( *, dtype: str = 'float64', layout: str | None = None, - device: str | None = None, - pin_memory: None | bool = None, + device: PlaceLike | None = None, + pin_memory: bool = False, requires_grad: bool = False, ): """ @@ -551,9 +572,11 @@ def hann_window( periodic (bool, optional): If True, returns a window for use as a periodic function; if False, returns a symmetric window. Defaults to True. dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. - device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). - pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. - requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + device(PlaceLike|None, optional): The desired device of returned tensor. + if None, uses the current device for the default tensor type (see paddle.device.set_device()). + device will be the CPU for CPU tensor types and the current CUDA device for CUDA tensor types. Default: None. + pin_memory(bool, optional): If set, return tensor would be allocated in the pinned memory. Works only for CPU tensors. Default: False + requires_grad(bool, optional): If autograd should record operations on the returned tensor. Default: False. Returns: Tensor: A 1-D tensor of shape `(window_length,)` containing the Hann window. @@ -583,8 +606,8 @@ def kaiser_window( *, dtype: str = 'float64', layout: str | None = None, - device: str | None = None, - pin_memory: None | bool = None, + device: PlaceLike | None = None, + pin_memory: bool = False, requires_grad: bool = False, ): """ @@ -596,9 +619,11 @@ def kaiser_window( beta (float, optional): Shape parameter for the window. Defaults to 12.0. dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. - device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). - pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. - requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + device(PlaceLike|None, optional): The desired device of returned tensor. + if None, uses the current device for the default tensor type (see paddle.device.set_device()). + device will be the CPU for CPU tensor types and the current CUDA device for CUDA tensor types. Default: None. + pin_memory(bool, optional): If set, return tensor would be allocated in the pinned memory. Works only for CPU tensors. Default: False + requires_grad(bool, optional): If autograd should record operations on the returned tensor. Default: False. Returns: Tensor: A 1-D tensor of shape `(window_length,)` containing the Kaiser window. @@ -629,8 +654,8 @@ def blackman_window( *, dtype: str = 'float64', layout: str | None = None, - device: str | None = None, - pin_memory: None | bool = None, + device: PlaceLike | None = None, + pin_memory: bool = False, requires_grad: bool = False, ): """ @@ -641,9 +666,11 @@ def blackman_window( periodic (bool, optional): If True, returns a window for use as a periodic function; if False, returns a symmetric window. Defaults to True. dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. - device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). - pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. - requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + device(PlaceLike|None, optional): The desired device of returned tensor. + if None, uses the current device for the default tensor type (see paddle.device.set_device()). + device will be the CPU for CPU tensor types and the current CUDA device for CUDA tensor types. Default: None. + pin_memory(bool, optional): If set, return tensor would be allocated in the pinned memory. Works only for CPU tensors. Default: False + requires_grad(bool, optional): If autograd should record operations on the returned tensor. Default: False. Returns: Tensor: A 1-D tensor of shape `(window_length,)` containing the Blackman window. @@ -672,8 +699,8 @@ def bartlett_window( *, dtype: str = 'float64', layout: str | None = None, - device: str | None = None, - pin_memory: None | bool = None, + device: PlaceLike | None = None, + pin_memory: bool = False, requires_grad: bool = False, ): """ @@ -684,9 +711,11 @@ def bartlett_window( periodic (bool, optional): If True, returns a window for use as a periodic function; if False, returns a symmetric window. Defaults to True. dtype (str, optional): The data type of the returned tensor. Defaults to 'float64'. layout (str, optional): Only included for API consistency with PyTorch; ignored in Paddle. Defaults to None. - device (str, optional): The device to place the returned tensor on. Defaults to None (uses the default device). - pin_memory (bool, optional): If True, returned tensor would be allocated in the pinned memory else not. Works only for CPU tensors. Defaults to None. - requires_grad (bool, optional): If True, operations on the returned tensor will be tracked by autograd for gradient computation else not. Defaults to False. + device(PlaceLike|None, optional): The desired device of returned tensor. + if None, uses the current device for the default tensor type (see paddle.device.set_device()). + device will be the CPU for CPU tensor types and the current CUDA device for CUDA tensor types. Default: None. + pin_memory(bool, optional): If set, return tensor would be allocated in the pinned memory. Works only for CPU tensors. Default: False + requires_grad(bool, optional): If autograd should record operations on the returned tensor. Default: False. Returns: Tensor: A 1-D tensor of shape `(window_length,)` containing the Bartlett window. diff --git a/test/legacy_test/CMakeLists.txt b/test/legacy_test/CMakeLists.txt index 0848db197a5ad9..ebee3a35bfa83a 100644 --- a/test/legacy_test/CMakeLists.txt +++ b/test/legacy_test/CMakeLists.txt @@ -877,7 +877,7 @@ set_tests_properties(test_cross_entropy_loss PROPERTIES TIMEOUT 180) set_tests_properties(test_legacy_loss_args PROPERTIES TIMEOUT 10) set_tests_properties(test_activation_nn_grad PROPERTIES TIMEOUT 250) set_tests_properties(test_empty_op PROPERTIES TIMEOUT 120) -set_tests_properties(test_align_torch_window_func PROPERTIES TIMEOUT 10) +set_tests_properties(test_window PROPERTIES TIMEOUT 10) set_tests_properties(test_elementwise_div_op PROPERTIES TIMEOUT 120) set_tests_properties(test_multiclass_nms_op PROPERTIES TIMEOUT 120) if(NOT WIN32) diff --git a/test/legacy_test/test_align_torch_window_func.py b/test/legacy_test/test_window.py similarity index 100% rename from test/legacy_test/test_align_torch_window_func.py rename to test/legacy_test/test_window.py From 62f3c7de992167a6c69b47c801dde55d990674f5 Mon Sep 17 00:00:00 2001 From: zty-king <17786324919@163.com> Date: Tue, 18 Nov 2025 09:02:51 +0000 Subject: [PATCH 7/8] add device process --- python/paddle/audio/functional/window.py | 2 +- test/legacy_test/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/python/paddle/audio/functional/window.py b/python/paddle/audio/functional/window.py index 7a01d3aa510e2a..bb1e2b50a849f6 100644 --- a/python/paddle/audio/functional/window.py +++ b/python/paddle/audio/functional/window.py @@ -493,7 +493,7 @@ def _apply_window_postprocess( raise RuntimeError( f"Pinning memory is not supported for {device}" ) - + w = paddle.to_tensor(w, place=device) if pin_memory and paddle.in_dynamic_mode(): w = w.pin_memory() if requires_grad is True: diff --git a/test/legacy_test/CMakeLists.txt b/test/legacy_test/CMakeLists.txt index 6cf63b16aeea40..ad6fb3070393e4 100644 --- a/test/legacy_test/CMakeLists.txt +++ b/test/legacy_test/CMakeLists.txt @@ -876,7 +876,6 @@ set_tests_properties(test_cross_entropy_loss PROPERTIES TIMEOUT 180) set_tests_properties(test_legacy_loss_args PROPERTIES TIMEOUT 10) set_tests_properties(test_activation_nn_grad PROPERTIES TIMEOUT 250) set_tests_properties(test_empty_op PROPERTIES TIMEOUT 120) -set_tests_properties(test_window PROPERTIES TIMEOUT 10) set_tests_properties(test_elementwise_div_op PROPERTIES TIMEOUT 120) set_tests_properties(test_multiclass_nms_op PROPERTIES TIMEOUT 120) if(NOT WIN32) From 6da8c0c2cbf324a37a6cfbeb991fffa3fc4332e4 Mon Sep 17 00:00:00 2001 From: zty-king <17786324919@163.com> Date: Wed, 19 Nov 2025 15:04:29 +0000 Subject: [PATCH 8/8] optimize code --- python/paddle/audio/functional/window.py | 2 +- test/legacy_test/test_window.py | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/python/paddle/audio/functional/window.py b/python/paddle/audio/functional/window.py index bb1e2b50a849f6..137ec7fca887ed 100644 --- a/python/paddle/audio/functional/window.py +++ b/python/paddle/audio/functional/window.py @@ -493,7 +493,7 @@ def _apply_window_postprocess( raise RuntimeError( f"Pinning memory is not supported for {device}" ) - w = paddle.to_tensor(w, place=device) + w = w.to(device=device) if pin_memory and paddle.in_dynamic_mode(): w = w.pin_memory() if requires_grad is True: diff --git a/test/legacy_test/test_window.py b/test/legacy_test/test_window.py index 22982a7e8acb64..3d08f56adc1fc3 100644 --- a/test/legacy_test/test_window.py +++ b/test/legacy_test/test_window.py @@ -18,12 +18,6 @@ from paddle.audio.functional.window import get_window -def _has_cuda(): - return ( - paddle.is_compiled_with_cuda() and "gpu" in paddle.device.get_device() - ) - - class TestWindowFunctions(unittest.TestCase): def setUp(self): paddle.set_device("cpu") @@ -67,7 +61,6 @@ def test_hamming_layout_warning(self): self.assertTrue(w.stop_gradient) self.assertEqual(list(w.shape), [N]) - @unittest.skipUnless(_has_cuda(), "GPU not available") def test_hamming_device_gpu_pin_memory(self): if paddle.is_compiled_with_cuda(): N = 12