153 lines
4.9 KiB
Python
153 lines
4.9 KiB
Python
# Copyright (c) 2026 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.
|
|
|
|
"""
|
|
信号处理高级测试 / Advanced Signal Processing Tests
|
|
|
|
测试目标 / Test Target:
|
|
paddle.signal 和 paddle.fft 信号处理
|
|
|
|
覆盖的模块 / Covered Modules:
|
|
- paddle.signal.stft: 短时傅里叶变换
|
|
- paddle.signal.istft: 逆短时傅里叶变换
|
|
- paddle.fft 高级用法
|
|
|
|
作用 / Purpose:
|
|
补充信号处理API的测试,提升覆盖率。
|
|
"""
|
|
|
|
import unittest
|
|
|
|
import numpy as np
|
|
|
|
import paddle
|
|
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestSTFT(unittest.TestCase):
|
|
"""测试短时傅里叶变换 / Test STFT"""
|
|
|
|
def test_stft_basic(self):
|
|
"""测试基本STFT / Test basic STFT"""
|
|
# Signal length
|
|
signal_len = 1024
|
|
x = paddle.randn([signal_len])
|
|
n_fft = 128
|
|
hop_length = 64
|
|
result = paddle.signal.stft(
|
|
x, n_fft=n_fft, hop_length=hop_length, win_length=128
|
|
)
|
|
# Expected freq bins: n_fft//2 + 1
|
|
expected_freq = n_fft // 2 + 1
|
|
self.assertEqual(result.shape[0], expected_freq)
|
|
|
|
def test_stft_batched(self):
|
|
"""测试批量STFT / Test batched STFT"""
|
|
x = paddle.randn([4, 512])
|
|
n_fft = 64
|
|
hop_length = 32
|
|
result = paddle.signal.stft(x, n_fft=n_fft, hop_length=hop_length)
|
|
expected_freq = n_fft // 2 + 1
|
|
self.assertEqual(result.shape[0], 4)
|
|
self.assertEqual(result.shape[1], expected_freq)
|
|
|
|
def test_stft_with_window(self):
|
|
"""测试带窗函数的STFT / Test STFT with window"""
|
|
x = paddle.randn([256])
|
|
window = paddle.hann_window(64)
|
|
result = paddle.signal.stft(
|
|
x, n_fft=64, hop_length=32, win_length=64, window=window
|
|
)
|
|
self.assertIsNotNone(result)
|
|
|
|
|
|
class TestFFTAdvanced(unittest.TestCase):
|
|
"""测试高级FFT操作 / Test advanced FFT operations"""
|
|
|
|
def test_fft_shift(self):
|
|
"""测试FFT移位 / Test FFT shift"""
|
|
x = paddle.randn([16])
|
|
fft_result = paddle.fft.fft(x)
|
|
shifted = paddle.fft.fftshift(fft_result)
|
|
unshifted = paddle.fft.ifftshift(shifted)
|
|
np.testing.assert_allclose(
|
|
fft_result.numpy().real, unshifted.numpy().real, rtol=1e-5
|
|
)
|
|
|
|
def test_rfft_output_size(self):
|
|
"""测试RFFT输出大小 / Test RFFT output size"""
|
|
for n in [8, 16, 32]:
|
|
x = paddle.randn([n])
|
|
result = paddle.fft.rfft(x)
|
|
self.assertEqual(result.shape[0], n // 2 + 1)
|
|
|
|
def test_irfft_roundtrip(self):
|
|
"""测试IRFFT往返 / Test IRFFT round-trip"""
|
|
x = paddle.randn([32])
|
|
fft = paddle.fft.rfft(x)
|
|
recovered = paddle.fft.irfft(fft, n=32)
|
|
np.testing.assert_allclose(x.numpy(), recovered.numpy(), rtol=1e-5)
|
|
|
|
def test_fft2_2d(self):
|
|
"""测试2D FFT / Test 2D FFT"""
|
|
x = paddle.randn([8, 8])
|
|
result = paddle.fft.fft2(x)
|
|
self.assertEqual(result.shape, [8, 8])
|
|
|
|
def test_ifft2_roundtrip(self):
|
|
"""测试2D IFFT往返 / Test 2D IFFT round-trip"""
|
|
x = paddle.randn([8, 8])
|
|
fft = paddle.fft.fft2(x)
|
|
recovered = paddle.fft.ifft2(fft)
|
|
np.testing.assert_allclose(
|
|
x.numpy(), recovered.numpy().real, rtol=1e-4, atol=1e-6
|
|
)
|
|
|
|
def test_fft_frequencies(self):
|
|
"""测试FFT频率 / Test FFT frequencies"""
|
|
freqs = paddle.fft.fftfreq(8, d=1.0)
|
|
self.assertEqual(freqs.shape[0], 8)
|
|
|
|
def test_rfft_frequencies(self):
|
|
"""测试RFFT频率 / Test RFFT frequencies"""
|
|
freqs = paddle.fft.rfftfreq(8, d=1.0)
|
|
self.assertEqual(freqs.shape[0], 5) # 8//2 + 1
|
|
|
|
|
|
class TestHannWindow(unittest.TestCase):
|
|
"""测试Hann窗函数 / Test Hann window function"""
|
|
|
|
def test_hann_window(self):
|
|
"""测试Hann窗 / Test Hann window"""
|
|
window = paddle.hann_window(64)
|
|
self.assertEqual(window.shape[0], 64)
|
|
# Hann window center should be max
|
|
center = int(window.argmax().numpy())
|
|
self.assertAlmostEqual(center, 32, delta=1)
|
|
|
|
def test_hamming_window(self):
|
|
"""测试Hamming窗 / Test Hamming window"""
|
|
window = paddle.hamming_window(64)
|
|
self.assertEqual(window.shape[0], 64)
|
|
|
|
def test_blackman_window(self):
|
|
"""测试Blackman窗 / Test Blackman window"""
|
|
window = paddle.blackman_window(64)
|
|
self.assertEqual(window.shape[0], 64)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|