xref: /btstack/test/sbc/sbc_encoder_test.py (revision f25e60dece291970e0c7612fc7fda3d74ae3ceba)
1#!/usr/bin/env python3
2import numpy as np
3import wave
4import struct
5import sys
6from sbc import *
7from sbc_encoder import *
8from sbc_decoder import *
9
10error = 0.99
11max_error = -1
12
13
14def sbc_compare_subband_samples(frame_count, actual_frame, expected_frame):
15    global error, max_error
16    for blk in range(actual_frame.nr_blocks):
17        for ch in range(actual_frame.nr_channels):
18            M = mse(actual_frame.sb_sample[blk][ch], expected_frame.sb_sample[blk][ch])
19            if M > max_error:
20                max_error = M
21
22            if max_error > error:
23                print ("Frame %d: sb_sample error %f (ch %d, blk %d)" % (frame_count, max_error, ch, blk))
24                print (actual_frame.sb_sample[blk])
25                print (expected_frame.sb_sample[blk])
26                return -1
27    return 0
28
29def sbc_compare_audio_frames(frame_count, actual_frame, expected_frame):
30    global error, max_error
31
32    for blk in range(actual_frame.nr_blocks):
33        for ch in range(actual_frame.nr_channels):
34            M = mse(actual_frame.audio_sample[blk][ch], expected_frame.audio_sample[blk][ch])
35            if M > max_error:
36                max_error = M
37
38        if max_error > error:
39            print ("audio_sample error (%d, %f ) " % (frame_count, max_error))
40            print (actual_frame.audio_sample[blk])
41            print (expected_frame.audio_sample[blk])
42
43            return -1
44    return 0
45
46def sbc_compare_headers(frame_count, actual_frame, expected_frame):
47    if actual_frame.syncword != expected_frame.syncword:
48        print ("syncword wrong ", actual_frame.syncword)
49        return -1
50
51    if actual_frame.sampling_frequency != expected_frame.sampling_frequency:
52        print ("sampling_frequency wrong ", actual_frame.sampling_frequency)
53        return -1
54
55    if actual_frame.nr_blocks != expected_frame.nr_blocks:
56        print ("nr_blocks wrong ", actual_frame.nr_blocks)
57        return -1
58
59    if actual_frame.channel_mode != expected_frame.channel_mode:
60        print ("channel_mode wrong ", actual_frame.channel_mode)
61        return -1
62
63    if actual_frame.nr_channels != expected_frame.nr_channels:
64        print ("nr_channels wrong ", actual_frame.nr_channels)
65        return -1
66
67    if actual_frame.allocation_method != expected_frame.allocation_method:
68        print ("allocation_method wrong ", actual_frame.allocation_method)
69        return -1
70
71    if actual_frame.nr_subbands != expected_frame.nr_subbands:
72        print ("nr_subbands wrong ", actual_frame.nr_subbands)
73        return -1
74
75    if actual_frame.bitpool != expected_frame.bitpool:
76        print ("bitpool wrong (E: %d, D: %d)" % (actual_frame.bitpool, expected_frame.bitpool))
77        return -1
78
79    if  mse(actual_frame.join, expected_frame.join) > 0:
80        print ("join error \nE:\n %s \nD:\n %s" % (actual_frame.join, expected_frame.join))
81        return -1
82
83
84    if  mse(actual_frame.scale_factor, expected_frame.scale_factor) > 0:
85        print ("scale_factor error %d \nE:\n %s \nD:\n %s" % (frame_count, actual_frame.scale_factor, expected_frame.scale_factor))
86        return -1
87
88    if  mse(actual_frame.scalefactor, expected_frame.scalefactor) > 0:
89        print ("scalefactor error %d \nE:\n %s \nD:\n %s" % (frame_count, actual_frame.scalefactor, expected_frame.scalefactor))
90        return -1
91
92    if  mse(actual_frame.bits, expected_frame.bits) > 0:
93        print ("bits error %d \nE:\n %s \nD:\n %s" % (frame_count, actual_frame.bits, expected_frame.bits))
94        return -1
95
96    if actual_frame.crc_check != expected_frame.crc_check:
97        print ("crc_check wrong (E: %d, D: %d)" % (actual_frame.crc_check, expected_frame.crc_check))
98        return -1
99
100    return 0
101
102
103def get_actual_frame(fin, nr_blocks, nr_subbands, nr_channels, sampling_frequency, bitpool, allocation_method, force_channel_mode):
104    actual_frame = SBCFrame(nr_blocks, nr_subbands, nr_channels, sampling_frequency, bitpool, allocation_method)
105    fetch_samples_for_next_sbc_frame(fin, actual_frame)
106    sbc_encode(actual_frame, force_channel_mode)
107    return actual_frame
108
109file_size = 0
110def get_expected_frame(fin_expected):
111    global file_size
112    expected_frame = SBCFrame()
113    sbc_unpack_frame(fin_expected, file_size - fin_expected.tell(), expected_frame)
114    sbc_reconstruct_subband_samples(expected_frame)
115    return expected_frame
116
117usage = '''
118Usage:      ./sbc_encoder_test.py encoder_input.wav blocks subbands bitpool allocation_method force_channel_mode encoder_expected_output.sbc
119Example:    ./sbc_encoder_test.py fanfare.wav 16 4 31 0 2 fanfare-4sb.sbc
120'''
121
122if (len(sys.argv) < 8):
123    print(usage)
124    sys.exit(1)
125try:
126    encoder_input_wav = sys.argv[1]
127    nr_blocks = int(sys.argv[2])
128    nr_subbands = int(sys.argv[3])
129    bitpool = int(sys.argv[4])
130    allocation_method = int(sys.argv[5])
131    encoder_expected_sbc = sys.argv[6]
132    force_channel_mode = int(sys.argv[7])
133    sampling_frequency = 44100
134
135    if not encoder_input_wav.endswith('.wav'):
136        print(usage)
137        sys.exit(1)
138
139    if not encoder_expected_sbc.endswith('.sbc'):
140        print(usage)
141        sys.exit(1)
142
143    fin = wave.open(encoder_input_wav, 'rb')
144    nr_channels = fin.getnchannels()
145    sampling_frequency = fin.getframerate()
146    nr_audio_frames = fin.getnframes()
147
148    fin_expected = open(encoder_expected_sbc, 'rb')
149    fin_expected.seek(0,2)
150    file_size = fin_expected.tell()
151    fin_expected.seek(0,0)
152
153    subband_frame_count = 0
154    audio_frame_count = 0
155    nr_samples = nr_blocks * nr_subbands
156
157    while audio_frame_count < nr_audio_frames:
158        if subband_frame_count % 200 == 0:
159            print("== Frame %d ==" % (subband_frame_count))
160
161        actual_frame = get_actual_frame(fin, nr_blocks, nr_subbands, nr_channels, bitpool, sampling_frequency, allocation_method, force_channel_mode)
162        expected_frame = get_expected_frame(fin_expected)
163
164        err = sbc_compare_headers(subband_frame_count, actual_frame, expected_frame)
165        if err < 0:
166            exit(1)
167
168        err = sbc_compare_audio_frames(subband_frame_count, actual_frame, expected_frame)
169        if err < 0:
170            exit(1)
171
172        audio_frame_count += nr_samples
173        subband_frame_count += 1
174
175    print ("Max MSE audio sample error %f" % max_error)
176    fin.close()
177    fin_expected.close()
178
179except TypeError:
180    print ("Max MSE audio sample error %f" % max_error)
181    fin.close()
182    fin_expected.close()
183
184except IOError:
185    print(usage)
186    sys.exit(1)
187
188
189
190
191
192