summaryrefslogtreecommitdiff
path: root/tools/pcm2pdm.py
blob: 3a1fac6338a632a74671385415ad4c9a3d6373e5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import numpy as np
import soundfile

def second_order_delta_sigma(pcm):
    # Normalize input XXX: remove normalization
    #pcm = pcm / np.max(np.abs(pcm))

    n = len(pcm)
    pdm = np.zeros(n, dtype=np.uint8)

    integrator1 = 0.0
    integrator2 = 0.0
    quantized = 0.0

    for i in range(n):
        integrator1 += pcm[i] - quantized
        integrator2 += integrator1 - quantized

        if integrator2 >= 0:
            quantized = 1.0
            pdm[i] = 1
        else:
            quantized = -1.0
            pdm[i] = 0

    return pdm

def save_pdm_bin(pdm_data, file):
    packed = np.packbits(pdm_data)
    file.write(packed)

def convert(pcm_data, oversample = 64):
    # Oversample
    pcm_upsampled = np.repeat(pcm_data, oversample)

    # --- Convert to PDM ---
    pdm_data = second_order_delta_sigma(pcm_upsampled)

    return pdm_data

def convert_file(input_file, **kwargs):
    # --- Load audio ---
    pcm_data, samplerate = soundfile.read(input_file)

    # If stereo, use one channel
    if pcm_data.ndim > 1:
        pcm_data = pcm_data[:, 0]

    pdm_data = convert(pcm_data, **kwargs)
    return pdm_data


def parse():
    import argparse

    parser = argparse.ArgumentParser(description='Process an input file and write to an output file.')
    parser.add_argument('-i', '--input', type=str, required=True, help='Path to the input file')
    parser.add_argument('-o', '--output', type=str, required=True, help='Path to the output file')
    
    args = parser.parse_args()
    return args

def main():
    args = parse()

    out_path = args.output

    pdm_data = convert_file(args.input, oversample=64)
    with open(out_path, 'wb') as f:
        save_pdm_bin(pdm_data, f)

    print('Wrote', out_path)

if __name__ == '__main__':
    main()