diff options
author | Jon Nordby <jononor@gmail.com> | 2025-04-18 01:58:15 +0200 |
---|---|---|
committer | Martin StensgÄrd <mastensg@mastensg.net> | 2025-04-18 16:12:03 +0200 |
commit | df870d193c3ca6552ae85307abbb9f998228a776 (patch) | |
tree | 1b4b4f3dc3da8a63751f2a9f8d978c8c4f0d6eab /tools/test_pdm.py | |
parent | 61d9a812d1ab7c62b0e76903fb55a8c4d180298b (diff) |
tools: Fixup PDM reference conversion
Seems to agree pretty well with itself now
PDM bitstream also looks plausible for a sinewave
Diffstat (limited to 'tools/test_pdm.py')
-rw-r--r-- | tools/test_pdm.py | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/tools/test_pdm.py b/tools/test_pdm.py new file mode 100644 index 0000000..3bac00b --- /dev/null +++ b/tools/test_pdm.py @@ -0,0 +1,91 @@ + +import numpy +import soundfile +import numpy as np +import matplotlib.pyplot as plt + +from pcm2pdm import convert, convert_file, save_pdm_bin +from pdm2pcm import pdm_to_pcm, load_pdm_file +from testsignal import generate_test_tone + +def plot_reconstruct(pcm_in, pdm, pcm_reconstructed, sr, aspect = 4.0, height = 3.0): + # --- Plotting using OO API --- + + width = height * aspect + figheight = height * 3 + fig, axs = plt.subplots(3, 1, figsize=(width, figheight), sharex=True) + + duration = pcm_in.shape[0] / sr + print(duration) + t = np.linspace(0, duration, int(sr * duration), endpoint=False) + + # Plot original PCM + axs[0].plot(t, pcm_in, label="PCM_in", color='blue') + axs[0].set_title("Original PCM") + axs[0].set_ylabel("Amplitude") + axs[0].set_ylim(-1.2, 1.2) + axs[0].grid(True) + + # Plot PDM bitstream + time_pdm = np.linspace(0, duration, len(pdm), endpoint=False) + axs[1].step(time_pdm, pdm, where='mid', color='black') + axs[1].set_title("PDM Bitstream") + axs[1].set_ylabel("Bit") + axs[1].set_ylim(-0.2, 1.2) + axs[1].grid(True) + + # Plot reconstructed PCM + axs[2].plot(t, pcm_reconstructed[:len(t)], label="PCM_rec", color='green') + axs[2].set_title("Reconstructed PCM") + axs[2].set_ylabel("Amplitude") + axs[2].set_xlabel("Time [s]") + axs[2].set_ylim(-1.2, 1.2) + axs[2].grid(True) + + fig.tight_layout() + return fig + +def test_sine(): + + # temp files + pcm_file = 'test.wav' + pdm_file = 'test.pdm' + + # Generate test data + oversample = 32 + sample_rate = 16000 + signal = generate_test_tone(sample_rate=sample_rate, + duration_sec=1.000, freqs=[1000.0], noise_level=0.0) + pcm = signal + soundfile.write(pcm_file, signal, sample_rate) + + # Convert to PDM + + pdm_data = convert_file(pcm_file, oversample=oversample) + with open(pdm_file, 'wb') as f: + save_pdm_bin(pdm_data, f) + + pdm_loaded = load_pdm_file(pdm_file) + + numpy.testing.assert_equal(pdm_loaded, pdm_data) + + print(pdm_data) + print(pdm_loaded) + + # PDM to PCM conversion + pcm_reconstructed = pdm_to_pcm(pdm_loaded, decimation_factor=oversample) + + # Remove DC offset + pcm_reconstructed -= numpy.mean(pcm_reconstructed) + + fig = plot_reconstruct(pcm, pdm_loaded, pcm_reconstructed, sr=sample_rate) + print(fig.axes) + offset = 0.2 + fig.axes[0].set_xlim(offset+0.0010,offset+0.0020) + + plot_path = 'test.png' + fig.savefig(plot_path) + print(f'Saved {plot_path}') + +if __name__ == '__main__': + test_sine() |