xref: /btstack/test/sbc/sbc.py (revision 6ccd8248590f666db07dd7add13fecb4f5664fb5)
1*6ccd8248SMilanka Ringwald#!/usr/bin/env python3
2c21a9c2fSMilanka Ringwaldimport numpy as np
3c21a9c2fSMilanka Ringwaldimport wave
4c21a9c2fSMilanka Ringwaldimport struct
5c21a9c2fSMilanka Ringwaldimport sys
61bd8157eSMilanka Ringwaldimport time
71bd8157eSMilanka Ringwald
8c21a9c2fSMilanka Ringwald
9c21a9c2fSMilanka Ringwald# channel mode
10c21a9c2fSMilanka RingwaldMONO = 0
11c21a9c2fSMilanka RingwaldDUAL_CHANNEL = 1
12c21a9c2fSMilanka RingwaldSTEREO = 2
13c21a9c2fSMilanka RingwaldJOINT_STEREO = 3
14ad470863SMilanka Ringwaldchannel_modes = ["MONO", "DUAL CHANNEL", "STEREO", "JOINT STEREO"]
15c21a9c2fSMilanka Ringwald
16c21a9c2fSMilanka Ringwald# allocation method
17c21a9c2fSMilanka RingwaldLOUDNESS = 0
18c21a9c2fSMilanka RingwaldSNR = 1
19ad470863SMilanka Ringwaldallocation_methods = ["LOUDNESS", "SNR"]
20ad470863SMilanka Ringwald
21ad470863SMilanka Ringwaldsampling_frequencies = [16000, 32000, 44100, 48000]
22ad470863SMilanka Ringwaldnr_blocks = [4, 8, 12, 16]
23ad470863SMilanka Ringwaldnr_subbands = [4, 8]
24ad470863SMilanka Ringwald
251bd8157eSMilanka Ringwaldtime_ms = lambda: int(round(time.time() * 1000))
26ad470863SMilanka Ringwald
27ad470863SMilanka Ringwalddef allocation_method_to_str(allocation_method):
28ad470863SMilanka Ringwald    global allocation_methods
29ad470863SMilanka Ringwald    return allocation_methods[allocation_method]
30ad470863SMilanka Ringwald
31ad470863SMilanka Ringwalddef channel_mode_to_str(channel_mode):
32ad470863SMilanka Ringwald    global channel_modes
33ad470863SMilanka Ringwald    return channel_modes[channel_mode]
34ad470863SMilanka Ringwald
35ad470863SMilanka Ringwalddef sampling_frequency_to_str(sampling_frequency):
36ad470863SMilanka Ringwald    global sampling_frequencies
37ad470863SMilanka Ringwald    return sampling_frequencies[sampling_frequency]
38ad470863SMilanka Ringwald
39ad470863SMilanka Ringwalddef sampling_frequency_index(sampling_frequency):
40ad470863SMilanka Ringwald    global sampling_frequencies
41ad470863SMilanka Ringwald    for index, value in enumerate(sampling_frequencies):
42ad470863SMilanka Ringwald        if value == sampling_frequency:
43ad470863SMilanka Ringwald            return index
44ad470863SMilanka Ringwald    return -1
45c21a9c2fSMilanka Ringwald
46c21a9c2fSMilanka RingwaldProto_4_40 = [
47c21a9c2fSMilanka Ringwald    0.00000000E+00, 5.36548976E-04, 1.49188357E-03, 2.73370904E-03,
48c21a9c2fSMilanka Ringwald    3.83720193E-03, 3.89205149E-03, 1.86581691E-03, -3.06012286E-03,
49c21a9c2fSMilanka Ringwald    1.09137620E-02, 2.04385087E-02, 2.88757392E-02, 3.21939290E-02,
50c21a9c2fSMilanka Ringwald    2.58767811E-02, 6.13245186E-03, -2.88217274E-02, -7.76463494E-02,
51c21a9c2fSMilanka Ringwald    1.35593274E-01, 1.94987841E-01, 2.46636662E-01, 2.81828203E-01,
52c21a9c2fSMilanka Ringwald    2.94315332E-01, 2.81828203E-01, 2.46636662E-01, 1.94987841E-01,
53c21a9c2fSMilanka Ringwald    -1.35593274E-01, -7.76463494E-02, -2.88217274E-02, 6.13245186E-03,
54c21a9c2fSMilanka Ringwald    2.58767811E-02, 3.21939290E-02, 2.88757392E-02, 2.04385087E-02,
55c21a9c2fSMilanka Ringwald    -1.09137620E-02, -3.06012286E-03, 1.86581691E-03, 3.89205149E-03,
56c21a9c2fSMilanka Ringwald    3.83720193E-03, 2.73370904E-03, 1.49188357E-03, 5.36548976E-04
57c21a9c2fSMilanka Ringwald]
58c21a9c2fSMilanka Ringwald
59c21a9c2fSMilanka RingwaldProto_8_80 = [
60c21a9c2fSMilanka Ringwald    0.00000000E+00, 1.56575398E-04, 3.43256425E-04, 5.54620202E-04,
61c21a9c2fSMilanka Ringwald    8.23919506E-04, 1.13992507E-03, 1.47640169E-03, 1.78371725E-03,
62c21a9c2fSMilanka Ringwald    2.01182542E-03, 2.10371989E-03, 1.99454554E-03, 1.61656283E-03,
63c21a9c2fSMilanka Ringwald    9.02154502E-04, -1.78805361E-04, -1.64973098E-03, -3.49717454E-03,
64c21a9c2fSMilanka Ringwald    5.65949473E-03, 8.02941163E-03, 1.04584443E-02, 1.27472335E-02,
65c21a9c2fSMilanka Ringwald    1.46525263E-02, 1.59045603E-02, 1.62208471E-02, 1.53184106E-02,
66c21a9c2fSMilanka Ringwald    1.29371806E-02, 8.85757540E-03, 2.92408442E-03, -4.91578024E-03,
67c21a9c2fSMilanka Ringwald    -1.46404076E-02, -2.61098752E-02, -3.90751381E-02, -5.31873032E-02,
68c21a9c2fSMilanka Ringwald    6.79989431E-02, 8.29847578E-02, 9.75753918E-02, 1.11196689E-01,
69c21a9c2fSMilanka Ringwald    1.23264548E-01, 1.33264415E-01, 1.40753505E-01, 1.45389847E-01,
70c21a9c2fSMilanka Ringwald    1.46955068E-01, 1.45389847E-01, 1.40753505E-01, 1.33264415E-01,
71c21a9c2fSMilanka Ringwald    1.23264548E-01, 1.11196689E-01, 9.75753918E-02, 8.29847578E-02,
72c21a9c2fSMilanka Ringwald    -6.79989431E-02, -5.31873032E-02, -3.90751381E-02, -2.61098752E-02,
73c21a9c2fSMilanka Ringwald    -1.46404076E-02, -4.91578024E-03, 2.92408442E-03, 8.85757540E-03,
74c21a9c2fSMilanka Ringwald    1.29371806E-02, 1.53184106E-02, 1.62208471E-02, 1.59045603E-02,
75c21a9c2fSMilanka Ringwald    1.46525263E-02, 1.27472335E-02, 1.04584443E-02, 8.02941163E-03,
76c21a9c2fSMilanka Ringwald    -5.65949473E-03, -3.49717454E-03, -1.64973098E-03, -1.78805361E-04,
77c21a9c2fSMilanka Ringwald    9.02154502E-04, 1.61656283E-03, 1.99454554E-03, 2.10371989E-03,
78c21a9c2fSMilanka Ringwald    2.01182542E-03, 1.78371725E-03, 1.47640169E-03, 1.13992507E-03,
79c21a9c2fSMilanka Ringwald    8.23919506E-04, 5.54620202E-04, 3.43256425E-04, 1.56575398E-04
80c21a9c2fSMilanka Ringwald]
81c21a9c2fSMilanka Ringwald
82c21a9c2fSMilanka Ringwaldcrc_table = [
83c21a9c2fSMilanka Ringwald    0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53,
84c21a9c2fSMilanka Ringwald    0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB,
85c21a9c2fSMilanka Ringwald    0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E,
86c21a9c2fSMilanka Ringwald    0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76,
87c21a9c2fSMilanka Ringwald    0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4,
88c21a9c2fSMilanka Ringwald    0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
89c21a9c2fSMilanka Ringwald    0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19,
90c21a9c2fSMilanka Ringwald    0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1,
91c21a9c2fSMilanka Ringwald    0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40,
92c21a9c2fSMilanka Ringwald    0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8,
93c21a9c2fSMilanka Ringwald    0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D,
94c21a9c2fSMilanka Ringwald    0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
95c21a9c2fSMilanka Ringwald    0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7,
96c21a9c2fSMilanka Ringwald    0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F,
97c21a9c2fSMilanka Ringwald    0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A,
98c21a9c2fSMilanka Ringwald    0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2,
99c21a9c2fSMilanka Ringwald    0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75,
100c21a9c2fSMilanka Ringwald    0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
101c21a9c2fSMilanka Ringwald    0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8,
102c21a9c2fSMilanka Ringwald    0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50,
103c21a9c2fSMilanka Ringwald    0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2,
104c21a9c2fSMilanka Ringwald    0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A,
105c21a9c2fSMilanka Ringwald    0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F,
106c21a9c2fSMilanka Ringwald    0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
107c21a9c2fSMilanka Ringwald    0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66,
108c21a9c2fSMilanka Ringwald    0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E,
109c21a9c2fSMilanka Ringwald    0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB,
110c21a9c2fSMilanka Ringwald    0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43,
111c21a9c2fSMilanka Ringwald    0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1,
112c21a9c2fSMilanka Ringwald    0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
113c21a9c2fSMilanka Ringwald    0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C,
114c21a9c2fSMilanka Ringwald    0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4
115c21a9c2fSMilanka Ringwald]
116c21a9c2fSMilanka Ringwald# offset table for 4-subbands
117c21a9c2fSMilanka Ringwaldoffset4 = np.array([[ -1, 0, 0, 0 ],
118c21a9c2fSMilanka Ringwald                    [ -2, 0, 0, 1 ],
119c21a9c2fSMilanka Ringwald                    [ -2, 0, 0, 1 ],
120c21a9c2fSMilanka Ringwald                    [ -2, 0, 0, 1 ]
121c21a9c2fSMilanka Ringwald                    ])
122c21a9c2fSMilanka Ringwald
123c21a9c2fSMilanka Ringwald# offset tables for 8-subbands
124c21a9c2fSMilanka Ringwaldoffset8 = np.array([[ -2, 0, 0, 0, 0, 0, 0, 1 ],
125c21a9c2fSMilanka Ringwald                    [ -3, 0, 0, 0, 0, 0, 1, 2 ],
126c21a9c2fSMilanka Ringwald                    [ -4, 0, 0, 0, 0, 0, 1, 2 ],
127c21a9c2fSMilanka Ringwald                    [ -4, 0, 0, 0, 0, 0, 1, 2 ]
128c21a9c2fSMilanka Ringwald                    ])
129c21a9c2fSMilanka Ringwald
1301522543dSMilanka Ringwalddef calculate_scalefactor(max_subbandsample):
1311522543dSMilanka Ringwald    x = 0
1321522543dSMilanka Ringwald    while True:
133ef8a7a12SMilanka Ringwald        y = 1 << (x + 1)
1341522543dSMilanka Ringwald        if y > max_subbandsample:
1351522543dSMilanka Ringwald            break
1361522543dSMilanka Ringwald        x += 1
1371522543dSMilanka Ringwald    return (x,y)
1381522543dSMilanka Ringwald
1391522543dSMilanka Ringwald
1401522543dSMilanka Ringwalddef calculate_max_subbandsample(nr_blocks, nr_channels, nr_subbands, sb_sample):
1411522543dSMilanka Ringwald    max_subbandsample = np.zeros(shape = (nr_channels, nr_subbands))
1421522543dSMilanka Ringwald
1431522543dSMilanka Ringwald    for blk in range(nr_blocks):
1441522543dSMilanka Ringwald        for ch in range(nr_channels):
1451522543dSMilanka Ringwald            for sb in range(nr_subbands):
1461522543dSMilanka Ringwald                m = abs(sb_sample[blk][ch][sb])
1471522543dSMilanka Ringwald                if max_subbandsample[ch][sb] < m:
1481522543dSMilanka Ringwald                    max_subbandsample[ch][sb] = m
1491522543dSMilanka Ringwald    return max_subbandsample
1501522543dSMilanka Ringwald
1511522543dSMilanka Ringwalddef calculate_scalefactors(nr_blocks, nr_channels, nr_subbands, sb_sample):
1521522543dSMilanka Ringwald    scale_factor =  np.zeros(shape=(nr_channels, nr_subbands), dtype = np.int32)
1531522543dSMilanka Ringwald    scalefactor =  np.zeros(shape=(nr_channels, nr_subbands), dtype = np.int32)
1541522543dSMilanka Ringwald
1555c9bef5bSMilanka Ringwald    max_subbandsample = calculate_max_subbandsample(nr_blocks, nr_channels, nr_subbands, sb_sample)
1561522543dSMilanka Ringwald    for ch in range(nr_channels):
1571522543dSMilanka Ringwald        for sb in range(nr_subbands):
1585c9bef5bSMilanka Ringwald            (scale_factor[ch][sb], scalefactor[ch][sb]) = calculate_scalefactor(max_subbandsample[ch][sb])
1591522543dSMilanka Ringwald    return scale_factor, scalefactor
1601522543dSMilanka Ringwald
161ef8a7a12SMilanka Ringwalddef calculate_channel_mode_and_scale_factors(frame, force_channel_mode):
162c9498b12SMilanka Ringwald    frame.scale_factor, frame.scalefactor = calculate_scalefactors(frame.nr_blocks, frame.nr_channels, frame.nr_subbands, frame.sb_sample)
163c9498b12SMilanka Ringwald
1641522543dSMilanka Ringwald    if frame.nr_channels == 1:
1651522543dSMilanka Ringwald        frame.channel_mode = MONO
166c9498b12SMilanka Ringwald        return
167c9498b12SMilanka Ringwald
1685c9bef5bSMilanka Ringwald    frame.join = np.zeros(frame.nr_subbands, dtype = np.uint8)
169ba345fb8SMilanka Ringwald
170ef8a7a12SMilanka Ringwald    if force_channel_mode == STEREO:
171ef8a7a12SMilanka Ringwald        frame.channel_mode = STEREO
172ef8a7a12SMilanka Ringwald        return
173ef8a7a12SMilanka Ringwald
17457f2bc22SMilanka Ringwald    sb_sample = np.zeros(shape = (frame.nr_blocks,2,frame.nr_subbands), dtype = np.int32)
1751522543dSMilanka Ringwald    for blk in range(frame.nr_blocks):
1761522543dSMilanka Ringwald        for sb in range(frame.nr_subbands):
17757f2bc22SMilanka Ringwald            sb_sample[blk][0][sb] = (frame.sb_sample[blk][0][sb] + frame.sb_sample[blk][1][sb])/2
17857f2bc22SMilanka Ringwald            sb_sample[blk][1][sb] = (frame.sb_sample[blk][0][sb] - frame.sb_sample[blk][1][sb])/2
1791522543dSMilanka Ringwald
180c9498b12SMilanka Ringwald    scale_factor, scalefactor = calculate_scalefactors(frame.nr_blocks, frame.nr_channels, frame.nr_subbands, sb_sample)
1815c9bef5bSMilanka Ringwald
18257f2bc22SMilanka Ringwald    for sb in range(frame.nr_subbands-1):
1835c9bef5bSMilanka Ringwald        suma = frame.scale_factor[0][sb] + frame.scale_factor[1][sb]
1845c9bef5bSMilanka Ringwald        sumb = scale_factor[0][sb] + scale_factor[1][sb]
1855c9bef5bSMilanka Ringwald
186ef8a7a12SMilanka Ringwald        if suma > sumb or force_channel_mode == JOINT_STEREO:
1871522543dSMilanka Ringwald            frame.channel_mode = JOINT_STEREO
1885c9bef5bSMilanka Ringwald            frame.join[sb] = 1
1895c9bef5bSMilanka Ringwald
1905c9bef5bSMilanka Ringwald            frame.scale_factor[0][sb] = scale_factor[0][sb]
1915c9bef5bSMilanka Ringwald            frame.scale_factor[1][sb] = scale_factor[1][sb]
1925c9bef5bSMilanka Ringwald            frame.scalefactor[0][sb]  = scalefactor[0][sb]
1935c9bef5bSMilanka Ringwald            frame.scalefactor[1][sb]  = scalefactor[1][sb]
1945c9bef5bSMilanka Ringwald
1955c9bef5bSMilanka Ringwald            for blk in range(frame.nr_blocks):
196c9498b12SMilanka Ringwald                frame.sb_sample[blk][0][sb] = sb_sample[blk][0][sb]
197c9498b12SMilanka Ringwald                frame.sb_sample[blk][1][sb] = sb_sample[blk][1][sb]
1981522543dSMilanka Ringwald
1991522543dSMilanka Ringwald
200c21a9c2fSMilanka Ringwaldclass SBCFrame:
201c21a9c2fSMilanka Ringwald    syncword = 0
202c21a9c2fSMilanka Ringwald    sampling_frequency = 0
203c21a9c2fSMilanka Ringwald    nr_blocks = 0
204c21a9c2fSMilanka Ringwald    channel_mode = 0
205c21a9c2fSMilanka Ringwald    nr_channels = 0
206c21a9c2fSMilanka Ringwald    allocation_method = 0
207c21a9c2fSMilanka Ringwald    nr_subbands = 0
208c21a9c2fSMilanka Ringwald    bitpool = 0
209c21a9c2fSMilanka Ringwald    crc_check = 0
210042beff1SMatthias Ringwald    reserved_for_future_use = 0
211c21a9c2fSMilanka Ringwald    # pro subband - 1
212c21a9c2fSMilanka Ringwald    join = np.zeros(8, dtype = np.uint8)
213c21a9c2fSMilanka Ringwald    scale_factor =  np.zeros(shape=(2, 8), dtype = np.int32)
214c21a9c2fSMilanka Ringwald    scalefactor =  np.zeros(shape=(2, 8), dtype = np.int32)
215c21a9c2fSMilanka Ringwald    audio_sample = np.zeros(shape = (16,2,8), dtype = np.uint16)
216ba345fb8SMilanka Ringwald    sb_sample = np.zeros(shape = (16,2,8), dtype = np.int32)
217c21a9c2fSMilanka Ringwald    X = np.zeros(8, dtype = np.int16)
218c21a9c2fSMilanka Ringwald    EX = np.zeros(8)
2191522543dSMilanka Ringwald    pcm = np.zeros(shape=(2, 8*16), dtype = np.int16)
220c21a9c2fSMilanka Ringwald    bits    = np.zeros(shape=(2, 8))
221c21a9c2fSMilanka Ringwald    levels = np.zeros(shape=(2, 8), dtype = np.int32)
222c21a9c2fSMilanka Ringwald
223ad470863SMilanka Ringwald
224164f5121SMilanka Ringwald    def __init__(self, nr_blocks=16, nr_subbands=4, nr_channels=1, bitpool=31, sampling_frequency=44100, allocation_method = 0, force_channel_mode = 0):
225c21a9c2fSMilanka Ringwald        self.nr_blocks = nr_blocks
226c21a9c2fSMilanka Ringwald        self.nr_subbands = nr_subbands
227c21a9c2fSMilanka Ringwald        self.nr_channels = nr_channels
228ad470863SMilanka Ringwald        self.sampling_frequency = sampling_frequency_index(sampling_frequency)
229c21a9c2fSMilanka Ringwald        self.bitpool = bitpool
2305665ea35SMilanka Ringwald        self.allocation_method = allocation_method
2315c9bef5bSMilanka Ringwald        self.init(nr_blocks, nr_subbands, nr_channels)
232164f5121SMilanka Ringwald        self.channel_mode = force_channel_mode
2335c9bef5bSMilanka Ringwald        return
2345c9bef5bSMilanka Ringwald
2355c9bef5bSMilanka Ringwald    def init(self, nr_blocks, nr_subbands, nr_channels):
236c21a9c2fSMilanka Ringwald        self.scale_factor = np.zeros(shape=(nr_channels, nr_subbands), dtype = np.int32)
237c21a9c2fSMilanka Ringwald        self.scalefactor = np.zeros(shape=(nr_channels, nr_subbands), dtype = np.int32)
238c21a9c2fSMilanka Ringwald        self.audio_sample = np.zeros(shape=(nr_blocks, nr_channels, nr_subbands), dtype = np.uint16)
239ba345fb8SMilanka Ringwald        self.sb_sample = np.zeros(shape=(nr_blocks, nr_channels, nr_subbands), dtype = np.int32)
240c21a9c2fSMilanka Ringwald        self.levels = np.zeros(shape=(nr_channels, nr_subbands), dtype = np.int32)
2415c9bef5bSMilanka Ringwald        self.pcm = np.zeros(shape=(nr_channels, nr_subbands*nr_blocks), dtype = np.int16)
2425c9bef5bSMilanka Ringwald        self.join = np.zeros(nr_subbands, dtype = np.uint8)
2435c9bef5bSMilanka Ringwald        self.X = np.zeros(nr_subbands, dtype = np.int16)
244c21a9c2fSMilanka Ringwald        self.EX = np.zeros(nr_subbands)
245c21a9c2fSMilanka Ringwald
246ad470863SMilanka Ringwald    def dump_audio_samples(self, blk, ch):
247*6ccd8248SMilanka Ringwald        print(self.audio_sample[blk][ch])
248ad470863SMilanka Ringwald
249ad470863SMilanka Ringwald    def dump_subband_samples(self, blk, ch):
250*6ccd8248SMilanka Ringwald        print(self.sb_sample[blk][ch])
251ad470863SMilanka Ringwald
252ad470863SMilanka Ringwald    def dump_state(self):
253ad470863SMilanka Ringwald        res =  "SBCFrameHeader state:"
254ad470863SMilanka Ringwald        res += "\n - nr channels %d" % self.nr_channels
255ad470863SMilanka Ringwald        res += "\n - nr blocks %d" % self.nr_blocks
256ad470863SMilanka Ringwald        res += "\n - nr subbands %d" % self.nr_subbands
257ad470863SMilanka Ringwald        res += "\n - scale factors: %s" % self.scale_factor
258ad470863SMilanka Ringwald        res += "\n - levels: %s" % self.levels
259ad470863SMilanka Ringwald        res += "\n - join: %s" % self.join
260ad470863SMilanka Ringwald        res += "\n - bits: %s" % self.bits
261*6ccd8248SMilanka Ringwald        print(res)
262ad470863SMilanka Ringwald
263c21a9c2fSMilanka Ringwald    def __str__(self):
264c21a9c2fSMilanka Ringwald        res =  "SBCFrameHeader:"
265646894e8SMilanka Ringwald        res += "\n - syncword %x" % self.syncword
266ad470863SMilanka Ringwald        res += "\n - sampling frequency %d Hz" % sampling_frequency_to_str(self.sampling_frequency)
267c21a9c2fSMilanka Ringwald
268ad470863SMilanka Ringwald        res += "\n - nr channels %d" % self.nr_channels
269ad470863SMilanka Ringwald        res += "\n - nr blocks %d" % self.nr_blocks
270ad470863SMilanka Ringwald        res += "\n - nr subbands %d" % self.nr_subbands
271c21a9c2fSMilanka Ringwald
272ad470863SMilanka Ringwald        res += "\n - channel mode %s" % channel_mode_to_str(self.channel_mode)
273ad470863SMilanka Ringwald        res += "\n - allocation method %s" % allocation_method_to_str(self.allocation_method)
274c21a9c2fSMilanka Ringwald
275ad470863SMilanka Ringwald        res += "\n - bitpool %d" % self.bitpool
276646894e8SMilanka Ringwald        res += "\n - crc check %x" % self.crc_check
277c21a9c2fSMilanka Ringwald        return res
278c21a9c2fSMilanka Ringwald
279c21a9c2fSMilanka Ringwald
2801522543dSMilanka Ringwalddef sbc_bit_allocation_stereo_joint(frame):
2811522543dSMilanka Ringwald    bitneed = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
2821522543dSMilanka Ringwald    bits    = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
2831522543dSMilanka Ringwald
284c21a9c2fSMilanka Ringwald    loudness = 0
285c21a9c2fSMilanka Ringwald
286c21a9c2fSMilanka Ringwald    if frame.allocation_method == SNR:
287c21a9c2fSMilanka Ringwald        for ch in range(frame.nr_channels):
288c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
289c21a9c2fSMilanka Ringwald                bitneed[ch][sb] = frame.scale_factor[ch][sb]
290c21a9c2fSMilanka Ringwald    else:
291c21a9c2fSMilanka Ringwald        for ch in range(frame.nr_channels):
292c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
293c21a9c2fSMilanka Ringwald                if frame.scale_factor[ch][sb] == 0:
294c21a9c2fSMilanka Ringwald                    bitneed[ch][sb] = -5
295c21a9c2fSMilanka Ringwald                else:
296c21a9c2fSMilanka Ringwald                    if frame.nr_subbands == 4:
297c9498b12SMilanka Ringwald                        loudness = frame.scale_factor[ch][sb] - offset4[frame.sampling_frequency][sb]
298c21a9c2fSMilanka Ringwald                    else:
299c21a9c2fSMilanka Ringwald                        loudness = frame.scale_factor[ch][sb] - offset8[frame.sampling_frequency][sb]
3001522543dSMilanka Ringwald
301c21a9c2fSMilanka Ringwald                    if loudness > 0:
302c21a9c2fSMilanka Ringwald                        bitneed[ch][sb] = loudness/2
303c21a9c2fSMilanka Ringwald                    else:
304c21a9c2fSMilanka Ringwald                        bitneed[ch][sb] = loudness
305c21a9c2fSMilanka Ringwald
306c21a9c2fSMilanka Ringwald    # search the maximum bitneed index
307c21a9c2fSMilanka Ringwald    max_bitneed = 0
308c21a9c2fSMilanka Ringwald    for ch in range(frame.nr_channels):
309c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
310c21a9c2fSMilanka Ringwald            if bitneed[ch][sb] > max_bitneed:
311c21a9c2fSMilanka Ringwald                max_bitneed = bitneed[ch][sb]
312c21a9c2fSMilanka Ringwald
3139462b3daSMilanka Ringwald
314c21a9c2fSMilanka Ringwald    # calculate how many bitslices fit into the bitpool
315c21a9c2fSMilanka Ringwald    bitcount = 0
316c21a9c2fSMilanka Ringwald    slicecount = 0
317c21a9c2fSMilanka Ringwald    bitslice = max_bitneed + 1 #/* init just above the largest sf */
318c21a9c2fSMilanka Ringwald
319c21a9c2fSMilanka Ringwald    while True:
3201522543dSMilanka Ringwald        bitslice -= 1
3211522543dSMilanka Ringwald        bitcount += slicecount
322c21a9c2fSMilanka Ringwald        slicecount = 0
323c21a9c2fSMilanka Ringwald        for ch in range(frame.nr_channels):
324c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
325c21a9c2fSMilanka Ringwald                if (bitneed[ch][sb] > bitslice+1) and (bitneed[ch][sb] < bitslice+16):
3261522543dSMilanka Ringwald                    slicecount += 1
327c21a9c2fSMilanka Ringwald                elif bitneed[ch][sb] == bitslice + 1:
3281522543dSMilanka Ringwald                    slicecount += 2
329c21a9c2fSMilanka Ringwald        if bitcount + slicecount >= frame.bitpool:
330c21a9c2fSMilanka Ringwald            break
331c21a9c2fSMilanka Ringwald
332c21a9c2fSMilanka Ringwald    if bitcount + slicecount == frame.bitpool:
3331522543dSMilanka Ringwald        bitcount += slicecount
3341522543dSMilanka Ringwald        bitslice -= 1
335c21a9c2fSMilanka Ringwald
336c21a9c2fSMilanka Ringwald    # bits are distributed until the last bitslice is reached
337c21a9c2fSMilanka Ringwald    for ch in range(frame.nr_channels):
338c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
339c21a9c2fSMilanka Ringwald            if bitneed[ch][sb] < bitslice+2:
340c9498b12SMilanka Ringwald                bits[ch][sb]=0
341c21a9c2fSMilanka Ringwald            else:
342c21a9c2fSMilanka Ringwald                bits[ch][sb] = min(bitneed[ch][sb]-bitslice,16)
343c21a9c2fSMilanka Ringwald
344c21a9c2fSMilanka Ringwald    ch = 0
345c21a9c2fSMilanka Ringwald    sb = 0
346c21a9c2fSMilanka Ringwald    while bitcount < frame.bitpool and sb < frame.nr_subbands:
347c21a9c2fSMilanka Ringwald        if bits[ch][sb] >= 2 and bits[ch][sb] < 16:
3481522543dSMilanka Ringwald            bits[ch][sb] += 1
3491522543dSMilanka Ringwald            bitcount += 1
350c21a9c2fSMilanka Ringwald        elif (bitneed[ch][sb] == bitslice+1) and (frame.bitpool > bitcount+1):
351c21a9c2fSMilanka Ringwald            bits[ch][sb] = 2
352c21a9c2fSMilanka Ringwald            bitcount += 2
353c21a9c2fSMilanka Ringwald        if ch == 1:
354c21a9c2fSMilanka Ringwald            ch = 0
3551522543dSMilanka Ringwald            sb += 1
356c21a9c2fSMilanka Ringwald        else:
357c21a9c2fSMilanka Ringwald            ch = 1
358c21a9c2fSMilanka Ringwald
359f08a674bSMilanka Ringwald
360f08a674bSMilanka Ringwald    ch = 0
361f08a674bSMilanka Ringwald    sb = 0
362f08a674bSMilanka Ringwald    while bitcount < frame.bitpool and sb < frame.nr_subbands:
363f08a674bSMilanka Ringwald        if bits[ch][sb] < 16:
364f08a674bSMilanka Ringwald            bits[ch][sb]+=1
365f08a674bSMilanka Ringwald            bitcount+=1
366f08a674bSMilanka Ringwald        if ch == 1:
367f08a674bSMilanka Ringwald            ch = 0
368f08a674bSMilanka Ringwald            sb += 1
369f08a674bSMilanka Ringwald        else:
370f08a674bSMilanka Ringwald            ch = 1
371f08a674bSMilanka Ringwald
372ef8a7a12SMilanka Ringwald
373f08a674bSMilanka Ringwald    if bits.sum() != frame.bitpool:
374*6ccd8248SMilanka Ringwald        print("bit allocation failed, bitpool %d, allocated %d" % (bits.sum() , frame.bitpool))
375f08a674bSMilanka Ringwald        exit(1)
376c21a9c2fSMilanka Ringwald    return bits
377c21a9c2fSMilanka Ringwald
378c21a9c2fSMilanka Ringwald
379c21a9c2fSMilanka Ringwalddef sbc_bit_allocation_mono_dual(frame):
380*6ccd8248SMilanka Ringwald    #print("Bit allocation for mono/dual channel" )
381c21a9c2fSMilanka Ringwald    bitneed = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
382c21a9c2fSMilanka Ringwald    bits    = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
383c21a9c2fSMilanka Ringwald    loudness = 0
384c21a9c2fSMilanka Ringwald
385c21a9c2fSMilanka Ringwald    for ch in range(frame.nr_channels):
386c21a9c2fSMilanka Ringwald        # bitneed values are derived from the scale factors
387c21a9c2fSMilanka Ringwald        if frame.allocation_method == SNR:
388c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
389c21a9c2fSMilanka Ringwald                bitneed[ch][sb] = frame.scale_factor[ch][sb]
390c21a9c2fSMilanka Ringwald        else:
391c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
392c21a9c2fSMilanka Ringwald                if frame.scale_factor[ch][sb] == 0:
393c21a9c2fSMilanka Ringwald                    bitneed[ch][sb] = -5
394c21a9c2fSMilanka Ringwald                else:
395c21a9c2fSMilanka Ringwald                    if frame.nr_subbands == 4:
396c21a9c2fSMilanka Ringwald                        loudness = frame.scale_factor[ch][sb] - offset4[frame.sampling_frequency][sb]
397c21a9c2fSMilanka Ringwald                    else:
398c21a9c2fSMilanka Ringwald                        loudness = frame.scale_factor[ch][sb] - offset8[frame.sampling_frequency][sb]
399c21a9c2fSMilanka Ringwald                    if loudness > 0:
400c21a9c2fSMilanka Ringwald                        bitneed[ch][sb] = loudness/2
401c21a9c2fSMilanka Ringwald                    else:
402c21a9c2fSMilanka Ringwald                        bitneed[ch][sb] = loudness
403c21a9c2fSMilanka Ringwald
404c21a9c2fSMilanka Ringwald        # search the maximum bitneed index
405c21a9c2fSMilanka Ringwald        max_bitneed = 0
406c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
407c21a9c2fSMilanka Ringwald            if bitneed[ch][sb] > max_bitneed:
408c21a9c2fSMilanka Ringwald                max_bitneed = bitneed[ch][sb]
409c21a9c2fSMilanka Ringwald
410c21a9c2fSMilanka Ringwald        # calculate how many bitslices fit into the bitpool
411c21a9c2fSMilanka Ringwald        bitcount = 0
412c21a9c2fSMilanka Ringwald        slicecount = 0
41341a4a18dSMilanka Ringwald        bitslice = max_bitneed + 1
414c21a9c2fSMilanka Ringwald
415c21a9c2fSMilanka Ringwald        while True:
416c21a9c2fSMilanka Ringwald            bitslice = bitslice - 1
417c21a9c2fSMilanka Ringwald            bitcount = bitcount + slicecount
418c21a9c2fSMilanka Ringwald            slicecount = 0
419c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
420c21a9c2fSMilanka Ringwald                if (bitneed[ch][sb] > bitslice+1) and (bitneed[ch][sb] < bitslice+16):
421c21a9c2fSMilanka Ringwald                    slicecount = slicecount + 1
422c21a9c2fSMilanka Ringwald                elif bitneed[ch][sb] == bitslice + 1:
423c21a9c2fSMilanka Ringwald                    slicecount = slicecount + 2
424c21a9c2fSMilanka Ringwald            if bitcount + slicecount >= frame.bitpool:
425c21a9c2fSMilanka Ringwald                break
426c21a9c2fSMilanka Ringwald
427c21a9c2fSMilanka Ringwald        if bitcount + slicecount == frame.bitpool:
428c21a9c2fSMilanka Ringwald            bitcount = bitcount + slicecount
429c21a9c2fSMilanka Ringwald            bitslice = bitslice - 1
430c21a9c2fSMilanka Ringwald
431c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
432c21a9c2fSMilanka Ringwald            if bitneed[ch][sb] < bitslice+2 :
433c21a9c2fSMilanka Ringwald               bits[ch][sb]=0;
434c21a9c2fSMilanka Ringwald            else:
435c21a9c2fSMilanka Ringwald                bits[ch][sb] = min(bitneed[ch][sb]-bitslice,16)
436c21a9c2fSMilanka Ringwald
437c21a9c2fSMilanka Ringwald        sb = 0
438c21a9c2fSMilanka Ringwald        while bitcount < frame.bitpool and sb < frame.nr_subbands:
439c21a9c2fSMilanka Ringwald            if bits[ch][sb] >= 2 and bits[ch][sb] < 16:
440c21a9c2fSMilanka Ringwald                   bits[ch][sb] = bits[ch][sb] + 1
441c21a9c2fSMilanka Ringwald                   bitcount = bitcount + 1
442c21a9c2fSMilanka Ringwald
443c21a9c2fSMilanka Ringwald            elif (bitneed[ch][sb] == bitslice+1) and (frame.bitpool > bitcount+1):
444c21a9c2fSMilanka Ringwald                bits[ch][sb] = 2
445c21a9c2fSMilanka Ringwald                bitcount += 2
446c21a9c2fSMilanka Ringwald
447c21a9c2fSMilanka Ringwald            sb = sb + 1
448c21a9c2fSMilanka Ringwald
449c21a9c2fSMilanka Ringwald        sb = 0
450c21a9c2fSMilanka Ringwald        while bitcount < frame.bitpool and sb < frame.nr_subbands:
451c21a9c2fSMilanka Ringwald            if bits[ch][sb] < 16:
452c21a9c2fSMilanka Ringwald                bits[ch][sb] = bits[ch][sb] + 1
453c21a9c2fSMilanka Ringwald                bitcount = bitcount + 1
454c21a9c2fSMilanka Ringwald            sb = sb + 1
455c21a9c2fSMilanka Ringwald
456c21a9c2fSMilanka Ringwald    return bits
457c21a9c2fSMilanka Ringwald
458c21a9c2fSMilanka Ringwalddef sbc_bit_allocation(frame):
459c21a9c2fSMilanka Ringwald    if frame.channel_mode == MONO or frame.channel_mode == DUAL_CHANNEL:
460c21a9c2fSMilanka Ringwald        return sbc_bit_allocation_mono_dual(frame)
461c21a9c2fSMilanka Ringwald    elif frame.channel_mode == STEREO or frame.channel_mode == JOINT_STEREO:
462c21a9c2fSMilanka Ringwald        return sbc_bit_allocation_stereo_joint(frame)
463c21a9c2fSMilanka Ringwald    else:
464*6ccd8248SMilanka Ringwald        print("Wrong channel mode ", frame.channel_mode)
465c21a9c2fSMilanka Ringwald        return -1
466c21a9c2fSMilanka Ringwald
467c21a9c2fSMilanka Ringwalddef sbc_sampling_frequency_index(sample_rate):
468c21a9c2fSMilanka Ringwald    sbc_sampling_frequency_index = 0
469c21a9c2fSMilanka Ringwald    for i in range(len(sampling_frequency)):
470c21a9c2fSMilanka Ringwald        if sample_rate == sampling_frequency[i]:
471c21a9c2fSMilanka Ringwald            sbc_sampling_frequency_index = i
472c21a9c2fSMilanka Ringwald            break
473c21a9c2fSMilanka Ringwald    return sbc_sampling_frequency_index
474c21a9c2fSMilanka Ringwald
475c21a9c2fSMilanka Ringwald
476c21a9c2fSMilanka Ringwalddef sbc_crc8(data, data_len):
477c21a9c2fSMilanka Ringwald    crc = 0x0f
478c21a9c2fSMilanka Ringwald    j = 0
479c21a9c2fSMilanka Ringwald    for i in range(data_len / 8):
480c21a9c2fSMilanka Ringwald        crc = crc_table[crc ^ data[i]]
481c21a9c2fSMilanka Ringwald        j = i + 1
482c21a9c2fSMilanka Ringwald
483c21a9c2fSMilanka Ringwald    bits_left = data_len%8
484c21a9c2fSMilanka Ringwald    if bits_left:
485c21a9c2fSMilanka Ringwald        octet = data[j]
486c21a9c2fSMilanka Ringwald        for i in range(data_len%8):
487c21a9c2fSMilanka Ringwald            bit = ((octet ^ crc) & 0x80) >> 7
488c21a9c2fSMilanka Ringwald            if bit:
489c21a9c2fSMilanka Ringwald                bit = 0x1d
490c21a9c2fSMilanka Ringwald            crc = ((crc & 0x7f) << 1) ^ bit
491c21a9c2fSMilanka Ringwald            octet = octet << 1
492c21a9c2fSMilanka Ringwald    return crc
493c21a9c2fSMilanka Ringwald
494c21a9c2fSMilanka Ringwald
495ad470863SMilanka Ringwaldbitstream = None
496c21a9c2fSMilanka Ringwaldbitstream_index = -1
497c21a9c2fSMilanka Ringwaldbitstream_bits_available = 0
498c21a9c2fSMilanka Ringwald
499c21a9c2fSMilanka Ringwalddef init_bitstream():
500c21a9c2fSMilanka Ringwald    global bitstream, bitstream_bits_available, bitstream_index
501c21a9c2fSMilanka Ringwald    bitstream = []
502c21a9c2fSMilanka Ringwald    bitstream_index = -1
503c21a9c2fSMilanka Ringwald    bitstream_bits_available = 0
504c21a9c2fSMilanka Ringwald
505c21a9c2fSMilanka Ringwalddef add_bit(bit):
506c21a9c2fSMilanka Ringwald    global bitstream, bitstream_bits_available, bitstream_index
507c21a9c2fSMilanka Ringwald    if bitstream_bits_available == 0:
508c21a9c2fSMilanka Ringwald        bitstream.append(0)
509c21a9c2fSMilanka Ringwald        bitstream_bits_available = 8
510c21a9c2fSMilanka Ringwald        bitstream_index += 1
511c21a9c2fSMilanka Ringwald
512c21a9c2fSMilanka Ringwald    bitstream[bitstream_index] |= bit << (bitstream_bits_available - 1)
513c21a9c2fSMilanka Ringwald    bitstream_bits_available -= 1
514c21a9c2fSMilanka Ringwald
515c21a9c2fSMilanka Ringwald
516c21a9c2fSMilanka Ringwalddef add_bits(bits, len):
517c21a9c2fSMilanka Ringwald    global bitstream, bitstream_bits_available
518c21a9c2fSMilanka Ringwald    for i in range(len):
519c21a9c2fSMilanka Ringwald        add_bit((bits >> (len-1-i)) & 1)
520c21a9c2fSMilanka Ringwald
521ad470863SMilanka Ringwaldibuffer = None
522ad470863SMilanka Ringwaldibuffer_count = 0
523ad470863SMilanka Ringwald
524ad470863SMilanka Ringwalddef get_bit(fin):
525ad470863SMilanka Ringwald    global ibuffer, ibuffer_count
526ad470863SMilanka Ringwald    if ibuffer_count == 0:
527ad470863SMilanka Ringwald        ibuffer = ord(fin.read(1))
528ad470863SMilanka Ringwald        ibuffer_count = 8
529ad470863SMilanka Ringwald
530ad470863SMilanka Ringwald    bit = (ibuffer >> 7) & 1
531ad470863SMilanka Ringwald    ibuffer = ibuffer << 1
532ad470863SMilanka Ringwald    ibuffer_count = ibuffer_count - 1
533ad470863SMilanka Ringwald    return bit
534ad470863SMilanka Ringwald
535ad470863SMilanka Ringwalddef drop_remaining_bits():
536ad470863SMilanka Ringwald    global ibuffer_count
537*6ccd8248SMilanka Ringwald    #print("dropping %d bits" % ibuffer_count)
538ad470863SMilanka Ringwald    ibuffer_count = 0
539ad470863SMilanka Ringwald
540ad470863SMilanka Ringwalddef get_bits(fin, bit_count):
541ad470863SMilanka Ringwald    bits = 0
542ad470863SMilanka Ringwald    for i in range(bit_count):
543ad470863SMilanka Ringwald        bits = (bits << 1) | get_bit(fin)
544*6ccd8248SMilanka Ringwald    # print("get bits: %d -> %02x" %(bit_count, bits))
545ad470863SMilanka Ringwald    return bits
546ad470863SMilanka Ringwald
547c21a9c2fSMilanka Ringwald
548c21a9c2fSMilanka Ringwalddef calculate_crc(frame):
549c21a9c2fSMilanka Ringwald    global bitstream, bitstream_bits_available, bitstream_index
550c21a9c2fSMilanka Ringwald    init_bitstream()
551c21a9c2fSMilanka Ringwald
552c21a9c2fSMilanka Ringwald    add_bits(frame.sampling_frequency, 2)
553c21a9c2fSMilanka Ringwald    add_bits(frame.nr_blocks/4-1, 2)
554c21a9c2fSMilanka Ringwald    add_bits(frame.channel_mode, 2)
555c21a9c2fSMilanka Ringwald    add_bits(frame.allocation_method, 1)
556c21a9c2fSMilanka Ringwald    add_bits(frame.nr_subbands/4-1, 1)
557c21a9c2fSMilanka Ringwald    add_bits(frame.bitpool, 8)
558c21a9c2fSMilanka Ringwald    if frame.channel_mode == JOINT_STEREO:
559c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
560c21a9c2fSMilanka Ringwald            add_bits(frame.join[sb],1)
561c21a9c2fSMilanka Ringwald
562c21a9c2fSMilanka Ringwald    for ch in range(frame.nr_channels):
563c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
564c21a9c2fSMilanka Ringwald            add_bits(frame.scale_factor[ch][sb], 4)
56541a4a18dSMilanka Ringwald
566c21a9c2fSMilanka Ringwald    bitstream_len = (bitstream_index + 1) * 8
567c21a9c2fSMilanka Ringwald    if bitstream_bits_available:
5685c9bef5bSMilanka Ringwald        bitstream_len -= bitstream_bits_available
5695c9bef5bSMilanka Ringwald
570c21a9c2fSMilanka Ringwald    return sbc_crc8(bitstream, bitstream_len)
571c21a9c2fSMilanka Ringwald
572042beff1SMatthias Ringwalddef calculate_crc_mSBC(frame):
573042beff1SMatthias Ringwald    init_bitstream()
574042beff1SMatthias Ringwald    add_bits(frame.reserved_for_future_use, 16)
575042beff1SMatthias Ringwald    for sb in range(8):
576042beff1SMatthias Ringwald        add_bits(frame.scale_factor[0][sb], 4)
577042beff1SMatthias Ringwald    bitstream_len = (bitstream_index + 1) * 8
578042beff1SMatthias Ringwald    if bitstream_bits_available:
579042beff1SMatthias Ringwald        bitstream_len -= bitstream_bits_available
580042beff1SMatthias Ringwald    return sbc_crc8(bitstream, bitstream_len)
581c21a9c2fSMilanka Ringwald
582ad470863SMilanka Ringwalddef frame_to_bitstream(frame):
583ad470863SMilanka Ringwald    global bitstream, bitstream_bits_available, bitstream_index
584ad470863SMilanka Ringwald    init_bitstream()
585c21a9c2fSMilanka Ringwald
586ad470863SMilanka Ringwald    add_bits(frame.syncword, 8)
587ad470863SMilanka Ringwald    add_bits(frame.sampling_frequency, 2)
588ad470863SMilanka Ringwald    add_bits(frame.nr_blocks/4-1, 2)
589ad470863SMilanka Ringwald    add_bits(frame.channel_mode, 2)
590ad470863SMilanka Ringwald    add_bits(frame.allocation_method, 1)
591ad470863SMilanka Ringwald    add_bits(frame.nr_subbands/4-1, 1)
592ad470863SMilanka Ringwald    add_bits(frame.bitpool, 8)
593ad470863SMilanka Ringwald    add_bits(frame.crc_check, 8)
594c21a9c2fSMilanka Ringwald
595ad470863SMilanka Ringwald    if frame.channel_mode == JOINT_STEREO:
596ad470863SMilanka Ringwald        for sb in range(frame.nr_subbands-1):
597ad470863SMilanka Ringwald            add_bits(frame.join[sb],1)
598ad470863SMilanka Ringwald        add_bits(0,1)
599ad470863SMilanka Ringwald
600ad470863SMilanka Ringwald    for ch in range(frame.nr_channels):
601ad470863SMilanka Ringwald        for sb in range(frame.nr_subbands):
602ad470863SMilanka Ringwald            add_bits(frame.scale_factor[ch][sb], 4)
603ad470863SMilanka Ringwald
604ad470863SMilanka Ringwald    for blk in range(frame.nr_blocks):
605ad470863SMilanka Ringwald        for ch in range(frame.nr_channels):
606ad470863SMilanka Ringwald            for sb in range(frame.nr_subbands):
607ad470863SMilanka Ringwald                add_bits(frame.audio_sample[blk][ch][sb], frame.bits[ch][sb])
608ad470863SMilanka Ringwald
609ad470863SMilanka Ringwald    bitstream_bits_available = 0
610ad470863SMilanka Ringwald    return bitstream
611ad470863SMilanka Ringwald
612ad470863SMilanka Ringwalddef mse(a,b):
613ad470863SMilanka Ringwald    count = 1
614ad470863SMilanka Ringwald    for i in a.shape:
615ad470863SMilanka Ringwald        count *= i
616ad470863SMilanka Ringwald    delta = a - b
617ad470863SMilanka Ringwald    sqr = delta ** 2
618ad470863SMilanka Ringwald    res = sqr.sum()*1.0/count
619ad470863SMilanka Ringwald    # res = ((a - b) ** 2).mean()
620ad470863SMilanka Ringwald    return res
621