xref: /btstack/test/sbc/sbc_encoder_test.py (revision 5f21c38a78d3e0e2f0de80d07e8677062955ba30)
1*5f21c38aSMilanka Ringwald#!/usr/bin/env python
2*5f21c38aSMilanka Ringwaldimport numpy as np
3*5f21c38aSMilanka Ringwaldimport wave
4*5f21c38aSMilanka Ringwaldimport struct
5*5f21c38aSMilanka Ringwaldimport sys
6*5f21c38aSMilanka Ringwaldfrom sbc import *
7*5f21c38aSMilanka Ringwaldfrom sbc_encoder import *
8*5f21c38aSMilanka Ringwaldfrom sbc_decoder import *
9*5f21c38aSMilanka Ringwald
10*5f21c38aSMilanka Ringwalderror = 0.99
11*5f21c38aSMilanka Ringwaldmax_error = -1
12*5f21c38aSMilanka Ringwald
13*5f21c38aSMilanka Ringwalddef sbc_compare_audio_frames(frame_count, actual_frame, expected_frame):
14*5f21c38aSMilanka Ringwald    global error, max_error
15*5f21c38aSMilanka Ringwald
16*5f21c38aSMilanka Ringwald    M = mse(actual_frame.audio_sample, expected_frame.audio_sample)
17*5f21c38aSMilanka Ringwald    if M > max_error:
18*5f21c38aSMilanka Ringwald        max_error = M
19*5f21c38aSMilanka Ringwald
20*5f21c38aSMilanka Ringwald    if M > error:
21*5f21c38aSMilanka Ringwald        print "audio_sample error (%d, %d ) " % (frame_count, M)
22*5f21c38aSMilanka Ringwald        return -1
23*5f21c38aSMilanka Ringwald    return 0
24*5f21c38aSMilanka Ringwald
25*5f21c38aSMilanka Ringwald
26*5f21c38aSMilanka Ringwalddef sbc_compare_headers(frame_count, actual_frame, expected_frame):
27*5f21c38aSMilanka Ringwald    if actual_frame.syncword != expected_frame.syncword:
28*5f21c38aSMilanka Ringwald        print "syncword wrong ", actual_frame.syncword
29*5f21c38aSMilanka Ringwald        return -1
30*5f21c38aSMilanka Ringwald
31*5f21c38aSMilanka Ringwald    if actual_frame.sampling_frequency != expected_frame.sampling_frequency:
32*5f21c38aSMilanka Ringwald        print "sampling_frequency wrong ", actual_frame.sampling_frequency
33*5f21c38aSMilanka Ringwald        return -1
34*5f21c38aSMilanka Ringwald
35*5f21c38aSMilanka Ringwald    if actual_frame.nr_blocks != expected_frame.nr_blocks:
36*5f21c38aSMilanka Ringwald        print "nr_blocks wrong ", actual_frame.nr_blocks
37*5f21c38aSMilanka Ringwald        return -1
38*5f21c38aSMilanka Ringwald
39*5f21c38aSMilanka Ringwald    if actual_frame.channel_mode != expected_frame.channel_mode:
40*5f21c38aSMilanka Ringwald        print "channel_mode wrong ", actual_frame.channel_mode
41*5f21c38aSMilanka Ringwald        return -1
42*5f21c38aSMilanka Ringwald
43*5f21c38aSMilanka Ringwald    if actual_frame.nr_channels != expected_frame.nr_channels:
44*5f21c38aSMilanka Ringwald        print "nr_channels wrong ", actual_frame.nr_channels
45*5f21c38aSMilanka Ringwald        return -1
46*5f21c38aSMilanka Ringwald
47*5f21c38aSMilanka Ringwald    if actual_frame.allocation_method != expected_frame.allocation_method:
48*5f21c38aSMilanka Ringwald        print "allocation_method wrong ", actual_frame.allocation_method
49*5f21c38aSMilanka Ringwald        return -1
50*5f21c38aSMilanka Ringwald
51*5f21c38aSMilanka Ringwald    if actual_frame.nr_subbands != expected_frame.nr_subbands:
52*5f21c38aSMilanka Ringwald        print "nr_subbands wrong ", actual_frame.nr_subbands
53*5f21c38aSMilanka Ringwald        return -1
54*5f21c38aSMilanka Ringwald
55*5f21c38aSMilanka Ringwald    if actual_frame.bitpool != expected_frame.bitpool:
56*5f21c38aSMilanka Ringwald        print "bitpool wrong (E: %d, D: %d)" % (actual_frame.bitpool, expected_frame.bitpool)
57*5f21c38aSMilanka Ringwald        return -1
58*5f21c38aSMilanka Ringwald
59*5f21c38aSMilanka Ringwald    if  mse(actual_frame.join, expected_frame.join) > 0:
60*5f21c38aSMilanka Ringwald        print "join error \nE:\n %s \nD:\n %s" % (actual_frame.join, expected_frame.join)
61*5f21c38aSMilanka Ringwald        return -1
62*5f21c38aSMilanka Ringwald
63*5f21c38aSMilanka Ringwald    if  mse(actual_frame.scale_factor, expected_frame.scale_factor) > 0:
64*5f21c38aSMilanka Ringwald        print "scale_factor error \nE:\n %s \nD:\n %s" % (actual_frame.scale_factor, expected_frame.scale_factor)
65*5f21c38aSMilanka Ringwald        return -1
66*5f21c38aSMilanka Ringwald
67*5f21c38aSMilanka Ringwald    if  mse(actual_frame.scalefactor, expected_frame.scalefactor) > 0:
68*5f21c38aSMilanka Ringwald        print "scalefactor error \nE:\n %s \nD:\n %s" % (actual_frame.scalefactor, expected_frame.scalefactor)
69*5f21c38aSMilanka Ringwald        return -1
70*5f21c38aSMilanka Ringwald
71*5f21c38aSMilanka Ringwald    if  mse(actual_frame.bits, expected_frame.bits) > 0:
72*5f21c38aSMilanka Ringwald        print "bits error \nE:\n %s \nD:\n %s" % (actual_frame.bits, expected_frame.bits)
73*5f21c38aSMilanka Ringwald        return -1
74*5f21c38aSMilanka Ringwald
75*5f21c38aSMilanka Ringwald    if actual_frame.crc_check != expected_frame.crc_check:
76*5f21c38aSMilanka Ringwald        print "crc_check wrong (E: %d, D: %d)" % (actual_frame.crc_check, expected_frame.crc_check)
77*5f21c38aSMilanka Ringwald        return -1
78*5f21c38aSMilanka Ringwald
79*5f21c38aSMilanka Ringwald    return 0
80*5f21c38aSMilanka Ringwald
81*5f21c38aSMilanka Ringwald
82*5f21c38aSMilanka Ringwalddef get_actual_frame(fin, nr_blocks, nr_subbands, nr_channels, sampling_frequency, bitpool):
83*5f21c38aSMilanka Ringwald    actual_frame = SBCFrame(nr_blocks, nr_subbands, nr_channels, sampling_frequency, bitpool)
84*5f21c38aSMilanka Ringwald    fetch_samples_for_next_sbc_frame(fin, actual_frame)
85*5f21c38aSMilanka Ringwald    sbc_encode(actual_frame)
86*5f21c38aSMilanka Ringwald    return actual_frame
87*5f21c38aSMilanka Ringwald
88*5f21c38aSMilanka Ringwalddef get_expected_frame(fin_expected):
89*5f21c38aSMilanka Ringwald    expected_frame = SBCFrame()
90*5f21c38aSMilanka Ringwald    sbc_unpack_frame(fin_expected, expected_frame)
91*5f21c38aSMilanka Ringwald    return expected_frame
92*5f21c38aSMilanka Ringwald
93*5f21c38aSMilanka Ringwaldusage = '''
94*5f21c38aSMilanka RingwaldUsage:      ./sbc_encoder_test.py encoder_input.wav blocks subbands bitpool encoder_expected_output.sbc
95*5f21c38aSMilanka RingwaldExample:    ./sbc_encoder_test.py fanfare.wav 16 4 31 fanfare-4sb.sbc
96*5f21c38aSMilanka Ringwald'''
97*5f21c38aSMilanka Ringwald
98*5f21c38aSMilanka Ringwaldif (len(sys.argv) < 6):
99*5f21c38aSMilanka Ringwald    print(usage)
100*5f21c38aSMilanka Ringwald    sys.exit(1)
101*5f21c38aSMilanka Ringwaldtry:
102*5f21c38aSMilanka Ringwald    encoder_input_wav = sys.argv[1]
103*5f21c38aSMilanka Ringwald    nr_blocks = int(sys.argv[2])
104*5f21c38aSMilanka Ringwald    nr_subbands = int(sys.argv[3])
105*5f21c38aSMilanka Ringwald    bitpool = int(sys.argv[4])
106*5f21c38aSMilanka Ringwald    encoder_expected_sbc = sys.argv[5]
107*5f21c38aSMilanka Ringwald    sampling_frequency = 44100
108*5f21c38aSMilanka Ringwald
109*5f21c38aSMilanka Ringwald    if not encoder_input_wav.endswith('.wav'):
110*5f21c38aSMilanka Ringwald        print(usage)
111*5f21c38aSMilanka Ringwald        sys.exit(1)
112*5f21c38aSMilanka Ringwald
113*5f21c38aSMilanka Ringwald    if not encoder_expected_sbc.endswith('.sbc'):
114*5f21c38aSMilanka Ringwald        print(usage)
115*5f21c38aSMilanka Ringwald        sys.exit(1)
116*5f21c38aSMilanka Ringwald
117*5f21c38aSMilanka Ringwald    fin = wave.open(encoder_input_wav, 'rb')
118*5f21c38aSMilanka Ringwald    nr_channels = fin.getnchannels()
119*5f21c38aSMilanka Ringwald    sampling_frequency = fin.getframerate()
120*5f21c38aSMilanka Ringwald    nr_audio_frames = fin.getnframes()
121*5f21c38aSMilanka Ringwald
122*5f21c38aSMilanka Ringwald    fin_expected = open(encoder_expected_sbc, 'rb')
123*5f21c38aSMilanka Ringwald    subband_frame_count = 0
124*5f21c38aSMilanka Ringwald    audio_frame_count = 0
125*5f21c38aSMilanka Ringwald    nr_samples = nr_blocks * nr_subbands
126*5f21c38aSMilanka Ringwald
127*5f21c38aSMilanka Ringwald    while audio_frame_count < nr_audio_frames:
128*5f21c38aSMilanka Ringwald        if subband_frame_count % 200 == 0:
129*5f21c38aSMilanka Ringwald            print("== Frame %d ==" % (subband_frame_count))
130*5f21c38aSMilanka Ringwald
131*5f21c38aSMilanka Ringwald        actual_frame = get_actual_frame(fin, nr_blocks, nr_subbands, nr_channels, bitpool, sampling_frequency)
132*5f21c38aSMilanka Ringwald        expected_frame = get_expected_frame(fin_expected)
133*5f21c38aSMilanka Ringwald
134*5f21c38aSMilanka Ringwald        err = sbc_compare_headers(subband_frame_count, actual_frame, expected_frame)
135*5f21c38aSMilanka Ringwald        if err < 0:
136*5f21c38aSMilanka Ringwald            exit(1)
137*5f21c38aSMilanka Ringwald
138*5f21c38aSMilanka Ringwald        err = sbc_compare_audio_frames(subband_frame_count, actual_frame, expected_frame)
139*5f21c38aSMilanka Ringwald        if err < 0:
140*5f21c38aSMilanka Ringwald            exit(1)
141*5f21c38aSMilanka Ringwald        audio_frame_count += nr_samples
142*5f21c38aSMilanka Ringwald        subband_frame_count += 1
143*5f21c38aSMilanka Ringwald
144*5f21c38aSMilanka Ringwald    print "DONE, max MSE audio sample error %d", max_error
145*5f21c38aSMilanka Ringwald    fin.close()
146*5f21c38aSMilanka Ringwald    fin_expected.close()
147*5f21c38aSMilanka Ringwald
148*5f21c38aSMilanka Ringwaldexcept IOError:
149*5f21c38aSMilanka Ringwald    print(usage)
150*5f21c38aSMilanka Ringwald    sys.exit(1)
151*5f21c38aSMilanka Ringwald
152*5f21c38aSMilanka Ringwald
153*5f21c38aSMilanka Ringwald
154*5f21c38aSMilanka Ringwald
155*5f21c38aSMilanka Ringwald
156