xref: /btstack/test/sbc/sbc.py (revision 1bd8157e8c1d5bbfe83038c2ea9e6b99d35fcb36)
1c21a9c2fSMilanka Ringwald#!/usr/bin/env python
2c21a9c2fSMilanka Ringwaldimport numpy as np
3c21a9c2fSMilanka Ringwaldimport wave
4c21a9c2fSMilanka Ringwaldimport struct
5c21a9c2fSMilanka Ringwaldimport sys
6*1bd8157eSMilanka Ringwaldimport time
7*1bd8157eSMilanka 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
25*1bd8157eSMilanka 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
210c21a9c2fSMilanka Ringwald    # pro subband - 1
211c21a9c2fSMilanka Ringwald    join = np.zeros(8, dtype = np.uint8)
212c21a9c2fSMilanka Ringwald    scale_factor =  np.zeros(shape=(2, 8), dtype = np.int32)
213c21a9c2fSMilanka Ringwald    scalefactor =  np.zeros(shape=(2, 8), dtype = np.int32)
214c21a9c2fSMilanka Ringwald    audio_sample = np.zeros(shape = (16,2,8), dtype = np.uint16)
215ba345fb8SMilanka Ringwald    sb_sample = np.zeros(shape = (16,2,8), dtype = np.int32)
216c21a9c2fSMilanka Ringwald    X = np.zeros(8, dtype = np.int16)
217c21a9c2fSMilanka Ringwald    EX = np.zeros(8)
2181522543dSMilanka Ringwald    pcm = np.zeros(shape=(2, 8*16), dtype = np.int16)
219c21a9c2fSMilanka Ringwald    bits    = np.zeros(shape=(2, 8))
220c21a9c2fSMilanka Ringwald    levels = np.zeros(shape=(2, 8), dtype = np.int32)
221c21a9c2fSMilanka Ringwald
222ad470863SMilanka Ringwald
2235665ea35SMilanka Ringwald    def __init__(self, nr_blocks=16, nr_subbands=4, nr_channels=1, bitpool=31, sampling_frequency=44100, allocation_method = 0):
224c21a9c2fSMilanka Ringwald        self.nr_blocks = nr_blocks
225c21a9c2fSMilanka Ringwald        self.nr_subbands = nr_subbands
226c21a9c2fSMilanka Ringwald        self.nr_channels = nr_channels
227ad470863SMilanka Ringwald        self.sampling_frequency = sampling_frequency_index(sampling_frequency)
228c21a9c2fSMilanka Ringwald        self.bitpool = bitpool
2295665ea35SMilanka Ringwald        self.allocation_method = allocation_method
2305c9bef5bSMilanka Ringwald        self.init(nr_blocks, nr_subbands, nr_channels)
2315c9bef5bSMilanka Ringwald        return
2325c9bef5bSMilanka Ringwald
2335c9bef5bSMilanka Ringwald    def init(self, nr_blocks, nr_subbands, nr_channels):
234c21a9c2fSMilanka Ringwald        self.scale_factor = np.zeros(shape=(nr_channels, nr_subbands), dtype = np.int32)
235c21a9c2fSMilanka Ringwald        self.scalefactor = np.zeros(shape=(nr_channels, nr_subbands), dtype = np.int32)
236c21a9c2fSMilanka Ringwald        self.audio_sample = np.zeros(shape=(nr_blocks, nr_channels, nr_subbands), dtype = np.uint16)
237ba345fb8SMilanka Ringwald        self.sb_sample = np.zeros(shape=(nr_blocks, nr_channels, nr_subbands), dtype = np.int32)
238c21a9c2fSMilanka Ringwald        self.levels = np.zeros(shape=(nr_channels, nr_subbands), dtype = np.int32)
2395c9bef5bSMilanka Ringwald        self.pcm = np.zeros(shape=(nr_channels, nr_subbands*nr_blocks), dtype = np.int16)
2405c9bef5bSMilanka Ringwald        self.join = np.zeros(nr_subbands, dtype = np.uint8)
2415c9bef5bSMilanka Ringwald        self.X = np.zeros(nr_subbands, dtype = np.int16)
242c21a9c2fSMilanka Ringwald        self.EX = np.zeros(nr_subbands)
243c21a9c2fSMilanka Ringwald
244ad470863SMilanka Ringwald    def dump_audio_samples(self, blk, ch):
245ad470863SMilanka Ringwald        print self.audio_sample[blk][ch]
246ad470863SMilanka Ringwald
247ad470863SMilanka Ringwald    def dump_subband_samples(self, blk, ch):
248ad470863SMilanka Ringwald        print self.sb_sample[blk][ch]
249ad470863SMilanka Ringwald
250ad470863SMilanka Ringwald    def dump_state(self):
251ad470863SMilanka Ringwald        res =  "SBCFrameHeader state:"
252ad470863SMilanka Ringwald        res += "\n - nr channels %d" % self.nr_channels
253ad470863SMilanka Ringwald        res += "\n - nr blocks %d" % self.nr_blocks
254ad470863SMilanka Ringwald        res += "\n - nr subbands %d" % self.nr_subbands
255ad470863SMilanka Ringwald        res += "\n - scale factors: %s" % self.scale_factor
256ad470863SMilanka Ringwald        res += "\n - levels: %s" % self.levels
257ad470863SMilanka Ringwald        res += "\n - join: %s" % self.join
258ad470863SMilanka Ringwald        res += "\n - bits: %s" % self.bits
259ad470863SMilanka Ringwald        print res
260ad470863SMilanka Ringwald
261c21a9c2fSMilanka Ringwald    def __str__(self):
262c21a9c2fSMilanka Ringwald        res =  "SBCFrameHeader:"
263ad470863SMilanka Ringwald        res += "\n - syncword %d" % self.syncword
264ad470863SMilanka Ringwald        res += "\n - sampling frequency %d Hz" % sampling_frequency_to_str(self.sampling_frequency)
265c21a9c2fSMilanka Ringwald
266ad470863SMilanka Ringwald        res += "\n - nr channels %d" % self.nr_channels
267ad470863SMilanka Ringwald        res += "\n - nr blocks %d" % self.nr_blocks
268ad470863SMilanka Ringwald        res += "\n - nr subbands %d" % self.nr_subbands
269c21a9c2fSMilanka Ringwald
270ad470863SMilanka Ringwald        res += "\n - channel mode %s" % channel_mode_to_str(self.channel_mode)
271ad470863SMilanka Ringwald        res += "\n - allocation method %s" % allocation_method_to_str(self.allocation_method)
272c21a9c2fSMilanka Ringwald
273ad470863SMilanka Ringwald        res += "\n - bitpool %d" % self.bitpool
274ad470863SMilanka Ringwald        res += "\n - crc check %d" % self.crc_check
275c21a9c2fSMilanka Ringwald        return res
276c21a9c2fSMilanka Ringwald
277c21a9c2fSMilanka Ringwald
2781522543dSMilanka Ringwalddef sbc_bit_allocation_stereo_joint(frame):
2791522543dSMilanka Ringwald    bitneed = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
2801522543dSMilanka Ringwald    bits    = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
2811522543dSMilanka Ringwald
282c21a9c2fSMilanka Ringwald    loudness = 0
283c21a9c2fSMilanka Ringwald
284c21a9c2fSMilanka Ringwald    if frame.allocation_method == SNR:
285c21a9c2fSMilanka Ringwald        for ch in range(frame.nr_channels):
286c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
287c21a9c2fSMilanka Ringwald                bitneed[ch][sb] = frame.scale_factor[ch][sb]
288c21a9c2fSMilanka Ringwald    else:
289c21a9c2fSMilanka Ringwald        for ch in range(frame.nr_channels):
290c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
291c21a9c2fSMilanka Ringwald                if frame.scale_factor[ch][sb] == 0:
292c21a9c2fSMilanka Ringwald                    bitneed[ch][sb] = -5
293c21a9c2fSMilanka Ringwald                else:
294c21a9c2fSMilanka Ringwald                    if frame.nr_subbands == 4:
295c9498b12SMilanka Ringwald                        loudness = frame.scale_factor[ch][sb] - offset4[frame.sampling_frequency][sb]
296c21a9c2fSMilanka Ringwald                    else:
297c21a9c2fSMilanka Ringwald                        loudness = frame.scale_factor[ch][sb] - offset8[frame.sampling_frequency][sb]
2981522543dSMilanka Ringwald
299c21a9c2fSMilanka Ringwald                    if loudness > 0:
300c21a9c2fSMilanka Ringwald                        bitneed[ch][sb] = loudness/2
301c21a9c2fSMilanka Ringwald                    else:
302c21a9c2fSMilanka Ringwald                        bitneed[ch][sb] = loudness
303c21a9c2fSMilanka Ringwald
304c21a9c2fSMilanka Ringwald    # search the maximum bitneed index
305c21a9c2fSMilanka Ringwald    max_bitneed = 0
306c21a9c2fSMilanka Ringwald    for ch in range(frame.nr_channels):
307c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
308c21a9c2fSMilanka Ringwald            if bitneed[ch][sb] > max_bitneed:
309c21a9c2fSMilanka Ringwald                max_bitneed = bitneed[ch][sb]
310c21a9c2fSMilanka Ringwald
3119462b3daSMilanka Ringwald
312c21a9c2fSMilanka Ringwald    # calculate how many bitslices fit into the bitpool
313c21a9c2fSMilanka Ringwald    bitcount = 0
314c21a9c2fSMilanka Ringwald    slicecount = 0
315c21a9c2fSMilanka Ringwald    bitslice = max_bitneed + 1 #/* init just above the largest sf */
316c21a9c2fSMilanka Ringwald
317c21a9c2fSMilanka Ringwald    while True:
3181522543dSMilanka Ringwald        bitslice -= 1
3191522543dSMilanka Ringwald        bitcount += slicecount
320c21a9c2fSMilanka Ringwald        slicecount = 0
321c21a9c2fSMilanka Ringwald        for ch in range(frame.nr_channels):
322c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
323c21a9c2fSMilanka Ringwald                if (bitneed[ch][sb] > bitslice+1) and (bitneed[ch][sb] < bitslice+16):
3241522543dSMilanka Ringwald                    slicecount += 1
325c21a9c2fSMilanka Ringwald                elif bitneed[ch][sb] == bitslice + 1:
3261522543dSMilanka Ringwald                    slicecount += 2
327c21a9c2fSMilanka Ringwald        if bitcount + slicecount >= frame.bitpool:
328c21a9c2fSMilanka Ringwald            break
329c21a9c2fSMilanka Ringwald
330c21a9c2fSMilanka Ringwald    if bitcount + slicecount == frame.bitpool:
3311522543dSMilanka Ringwald        bitcount += slicecount
3321522543dSMilanka Ringwald        bitslice -= 1
333c21a9c2fSMilanka Ringwald
334c21a9c2fSMilanka Ringwald    # bits are distributed until the last bitslice is reached
335c21a9c2fSMilanka Ringwald    for ch in range(frame.nr_channels):
336c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
337c21a9c2fSMilanka Ringwald            if bitneed[ch][sb] < bitslice+2:
338c9498b12SMilanka Ringwald                bits[ch][sb]=0
339c21a9c2fSMilanka Ringwald            else:
340c21a9c2fSMilanka Ringwald                bits[ch][sb] = min(bitneed[ch][sb]-bitslice,16)
341c21a9c2fSMilanka Ringwald
342c21a9c2fSMilanka Ringwald    ch = 0
343c21a9c2fSMilanka Ringwald    sb = 0
344c21a9c2fSMilanka Ringwald    while bitcount < frame.bitpool and sb < frame.nr_subbands:
345c21a9c2fSMilanka Ringwald        if bits[ch][sb] >= 2 and bits[ch][sb] < 16:
3461522543dSMilanka Ringwald            bits[ch][sb] += 1
3471522543dSMilanka Ringwald            bitcount += 1
348c21a9c2fSMilanka Ringwald        elif (bitneed[ch][sb] == bitslice+1) and (frame.bitpool > bitcount+1):
349c21a9c2fSMilanka Ringwald            bits[ch][sb] = 2
350c21a9c2fSMilanka Ringwald            bitcount += 2
351c21a9c2fSMilanka Ringwald        if ch == 1:
352c21a9c2fSMilanka Ringwald            ch = 0
3531522543dSMilanka Ringwald            sb += 1
354c21a9c2fSMilanka Ringwald        else:
355c21a9c2fSMilanka Ringwald            ch = 1
356c21a9c2fSMilanka Ringwald
357f08a674bSMilanka Ringwald
358f08a674bSMilanka Ringwald    ch = 0
359f08a674bSMilanka Ringwald    sb = 0
360f08a674bSMilanka Ringwald    while bitcount < frame.bitpool and sb < frame.nr_subbands:
361f08a674bSMilanka Ringwald        if bits[ch][sb] < 16:
362f08a674bSMilanka Ringwald            bits[ch][sb]+=1
363f08a674bSMilanka Ringwald            bitcount+=1
364f08a674bSMilanka Ringwald        if ch == 1:
365f08a674bSMilanka Ringwald            ch = 0
366f08a674bSMilanka Ringwald            sb += 1
367f08a674bSMilanka Ringwald        else:
368f08a674bSMilanka Ringwald            ch = 1
369f08a674bSMilanka Ringwald
370ef8a7a12SMilanka Ringwald
371f08a674bSMilanka Ringwald    if bits.sum() != frame.bitpool:
372f08a674bSMilanka Ringwald        print "bit allocation failed, bitpool %d, allocated %d" % (bits.sum() , frame.bitpool)
373f08a674bSMilanka Ringwald        exit(1)
374c21a9c2fSMilanka Ringwald    return bits
375c21a9c2fSMilanka Ringwald
376c21a9c2fSMilanka Ringwald
377c21a9c2fSMilanka Ringwalddef sbc_bit_allocation_mono_dual(frame):
378c21a9c2fSMilanka Ringwald    #print "Bit allocation for mono/dual channel"
379c21a9c2fSMilanka Ringwald    bitneed = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
380c21a9c2fSMilanka Ringwald    bits    = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
381c21a9c2fSMilanka Ringwald    loudness = 0
382c21a9c2fSMilanka Ringwald
383c21a9c2fSMilanka Ringwald    for ch in range(frame.nr_channels):
384c21a9c2fSMilanka Ringwald        # bitneed values are derived from the scale factors
385c21a9c2fSMilanka Ringwald        if frame.allocation_method == SNR:
386c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
387c21a9c2fSMilanka Ringwald                bitneed[ch][sb] = frame.scale_factor[ch][sb]
388c21a9c2fSMilanka Ringwald        else:
389c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
390c21a9c2fSMilanka Ringwald                if frame.scale_factor[ch][sb] == 0:
391c21a9c2fSMilanka Ringwald                    bitneed[ch][sb] = -5
392c21a9c2fSMilanka Ringwald                else:
393c21a9c2fSMilanka Ringwald                    if frame.nr_subbands == 4:
394c21a9c2fSMilanka Ringwald                        loudness = frame.scale_factor[ch][sb] - offset4[frame.sampling_frequency][sb]
395c21a9c2fSMilanka Ringwald                    else:
396c21a9c2fSMilanka Ringwald                        loudness = frame.scale_factor[ch][sb] - offset8[frame.sampling_frequency][sb]
397c21a9c2fSMilanka Ringwald                    if loudness > 0:
398c21a9c2fSMilanka Ringwald                        bitneed[ch][sb] = loudness/2
399c21a9c2fSMilanka Ringwald                    else:
400c21a9c2fSMilanka Ringwald                        bitneed[ch][sb] = loudness
401c21a9c2fSMilanka Ringwald
402c21a9c2fSMilanka Ringwald        # search the maximum bitneed index
403c21a9c2fSMilanka Ringwald        max_bitneed = 0
404c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
405c21a9c2fSMilanka Ringwald            if bitneed[ch][sb] > max_bitneed:
406c21a9c2fSMilanka Ringwald                max_bitneed = bitneed[ch][sb]
407c21a9c2fSMilanka Ringwald
408c21a9c2fSMilanka Ringwald        # calculate how many bitslices fit into the bitpool
409c21a9c2fSMilanka Ringwald        bitcount = 0
410c21a9c2fSMilanka Ringwald        slicecount = 0
41141a4a18dSMilanka Ringwald        bitslice = max_bitneed + 1
412c21a9c2fSMilanka Ringwald
413c21a9c2fSMilanka Ringwald        while True:
414c21a9c2fSMilanka Ringwald            bitslice = bitslice - 1
415c21a9c2fSMilanka Ringwald            bitcount = bitcount + slicecount
416c21a9c2fSMilanka Ringwald            slicecount = 0
417c21a9c2fSMilanka Ringwald            for sb in range(frame.nr_subbands):
418c21a9c2fSMilanka Ringwald                if (bitneed[ch][sb] > bitslice+1) and (bitneed[ch][sb] < bitslice+16):
419c21a9c2fSMilanka Ringwald                    slicecount = slicecount + 1
420c21a9c2fSMilanka Ringwald                elif bitneed[ch][sb] == bitslice + 1:
421c21a9c2fSMilanka Ringwald                    slicecount = slicecount + 2
422c21a9c2fSMilanka Ringwald            if bitcount + slicecount >= frame.bitpool:
423c21a9c2fSMilanka Ringwald                break
424c21a9c2fSMilanka Ringwald
425c21a9c2fSMilanka Ringwald        if bitcount + slicecount == frame.bitpool:
426c21a9c2fSMilanka Ringwald            bitcount = bitcount + slicecount
427c21a9c2fSMilanka Ringwald            bitslice = bitslice - 1
428c21a9c2fSMilanka Ringwald
429c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
430c21a9c2fSMilanka Ringwald            if bitneed[ch][sb] < bitslice+2 :
431c21a9c2fSMilanka Ringwald               bits[ch][sb]=0;
432c21a9c2fSMilanka Ringwald            else:
433c21a9c2fSMilanka Ringwald                bits[ch][sb] = min(bitneed[ch][sb]-bitslice,16)
434c21a9c2fSMilanka Ringwald
435c21a9c2fSMilanka Ringwald        sb = 0
436c21a9c2fSMilanka Ringwald        while bitcount < frame.bitpool and sb < frame.nr_subbands:
437c21a9c2fSMilanka Ringwald            if bits[ch][sb] >= 2 and bits[ch][sb] < 16:
438c21a9c2fSMilanka Ringwald                   bits[ch][sb] = bits[ch][sb] + 1
439c21a9c2fSMilanka Ringwald                   bitcount = bitcount + 1
440c21a9c2fSMilanka Ringwald
441c21a9c2fSMilanka Ringwald            elif (bitneed[ch][sb] == bitslice+1) and (frame.bitpool > bitcount+1):
442c21a9c2fSMilanka Ringwald                bits[ch][sb] = 2
443c21a9c2fSMilanka Ringwald                bitcount += 2
444c21a9c2fSMilanka Ringwald
445c21a9c2fSMilanka Ringwald            sb = sb + 1
446c21a9c2fSMilanka Ringwald
447c21a9c2fSMilanka Ringwald        sb = 0
448c21a9c2fSMilanka Ringwald        while bitcount < frame.bitpool and sb < frame.nr_subbands:
449c21a9c2fSMilanka Ringwald            if bits[ch][sb] < 16:
450c21a9c2fSMilanka Ringwald                bits[ch][sb] = bits[ch][sb] + 1
451c21a9c2fSMilanka Ringwald                bitcount = bitcount + 1
452c21a9c2fSMilanka Ringwald            sb = sb + 1
453c21a9c2fSMilanka Ringwald
454c21a9c2fSMilanka Ringwald    return bits
455c21a9c2fSMilanka Ringwald
456c21a9c2fSMilanka Ringwalddef sbc_bit_allocation(frame):
457c21a9c2fSMilanka Ringwald    if frame.channel_mode == MONO or frame.channel_mode == DUAL_CHANNEL:
458c21a9c2fSMilanka Ringwald        return sbc_bit_allocation_mono_dual(frame)
459c21a9c2fSMilanka Ringwald    elif frame.channel_mode == STEREO or frame.channel_mode == JOINT_STEREO:
460c21a9c2fSMilanka Ringwald        return sbc_bit_allocation_stereo_joint(frame)
461c21a9c2fSMilanka Ringwald    else:
462c21a9c2fSMilanka Ringwald        print "Wrong channel mode ", frame.channel_mode
463c21a9c2fSMilanka Ringwald        return -1
464c21a9c2fSMilanka Ringwald
465c21a9c2fSMilanka Ringwalddef sbc_sampling_frequency_index(sample_rate):
466c21a9c2fSMilanka Ringwald    sbc_sampling_frequency_index = 0
467c21a9c2fSMilanka Ringwald    for i in range(len(sampling_frequency)):
468c21a9c2fSMilanka Ringwald        if sample_rate == sampling_frequency[i]:
469c21a9c2fSMilanka Ringwald            sbc_sampling_frequency_index = i
470c21a9c2fSMilanka Ringwald            break
471c21a9c2fSMilanka Ringwald    return sbc_sampling_frequency_index
472c21a9c2fSMilanka Ringwald
473c21a9c2fSMilanka Ringwald
474c21a9c2fSMilanka Ringwalddef sbc_crc8(data, data_len):
475c21a9c2fSMilanka Ringwald    crc = 0x0f
476c21a9c2fSMilanka Ringwald    j = 0
477c21a9c2fSMilanka Ringwald    for i in range(data_len / 8):
478c21a9c2fSMilanka Ringwald        crc = crc_table[crc ^ data[i]]
479c21a9c2fSMilanka Ringwald        j = i + 1
480c21a9c2fSMilanka Ringwald
481c21a9c2fSMilanka Ringwald    bits_left = data_len%8
482c21a9c2fSMilanka Ringwald    if bits_left:
483c21a9c2fSMilanka Ringwald        octet = data[j]
484c21a9c2fSMilanka Ringwald        for i in range(data_len%8):
485c21a9c2fSMilanka Ringwald            bit = ((octet ^ crc) & 0x80) >> 7
486c21a9c2fSMilanka Ringwald            if bit:
487c21a9c2fSMilanka Ringwald                bit = 0x1d
488c21a9c2fSMilanka Ringwald            crc = ((crc & 0x7f) << 1) ^ bit
489c21a9c2fSMilanka Ringwald            octet = octet << 1
490c21a9c2fSMilanka Ringwald    return crc
491c21a9c2fSMilanka Ringwald
492c21a9c2fSMilanka Ringwald
493ad470863SMilanka Ringwaldbitstream = None
494c21a9c2fSMilanka Ringwaldbitstream_index = -1
495c21a9c2fSMilanka Ringwaldbitstream_bits_available = 0
496c21a9c2fSMilanka Ringwald
497c21a9c2fSMilanka Ringwalddef init_bitstream():
498c21a9c2fSMilanka Ringwald    global bitstream, bitstream_bits_available, bitstream_index
499c21a9c2fSMilanka Ringwald    bitstream = []
500c21a9c2fSMilanka Ringwald    bitstream_index = -1
501c21a9c2fSMilanka Ringwald    bitstream_bits_available = 0
502c21a9c2fSMilanka Ringwald
503c21a9c2fSMilanka Ringwalddef add_bit(bit):
504c21a9c2fSMilanka Ringwald    global bitstream, bitstream_bits_available, bitstream_index
505c21a9c2fSMilanka Ringwald    if bitstream_bits_available == 0:
506c21a9c2fSMilanka Ringwald        bitstream.append(0)
507c21a9c2fSMilanka Ringwald        bitstream_bits_available = 8
508c21a9c2fSMilanka Ringwald        bitstream_index += 1
509c21a9c2fSMilanka Ringwald
510c21a9c2fSMilanka Ringwald    bitstream[bitstream_index] |= bit << (bitstream_bits_available - 1)
511c21a9c2fSMilanka Ringwald    bitstream_bits_available -= 1
512c21a9c2fSMilanka Ringwald
513c21a9c2fSMilanka Ringwald
514c21a9c2fSMilanka Ringwalddef add_bits(bits, len):
515c21a9c2fSMilanka Ringwald    global bitstream, bitstream_bits_available
516c21a9c2fSMilanka Ringwald    for i in range(len):
517c21a9c2fSMilanka Ringwald        add_bit((bits >> (len-1-i)) & 1)
518c21a9c2fSMilanka Ringwald
519ad470863SMilanka Ringwaldibuffer = None
520ad470863SMilanka Ringwaldibuffer_count = 0
521ad470863SMilanka Ringwald
522ad470863SMilanka Ringwalddef get_bit(fin):
523ad470863SMilanka Ringwald    global ibuffer, ibuffer_count
524ad470863SMilanka Ringwald    if ibuffer_count == 0:
525ad470863SMilanka Ringwald        ibuffer = ord(fin.read(1))
526ad470863SMilanka Ringwald        ibuffer_count = 8
527ad470863SMilanka Ringwald
528ad470863SMilanka Ringwald    bit = (ibuffer >> 7) & 1
529ad470863SMilanka Ringwald    ibuffer = ibuffer << 1
530ad470863SMilanka Ringwald    ibuffer_count = ibuffer_count - 1
531ad470863SMilanka Ringwald    return bit
532ad470863SMilanka Ringwald
533ad470863SMilanka Ringwalddef drop_remaining_bits():
534ad470863SMilanka Ringwald    global ibuffer_count
535f08a674bSMilanka Ringwald    #print "dropping %d bits" % ibuffer_count
536ad470863SMilanka Ringwald    ibuffer_count = 0
537ad470863SMilanka Ringwald
538ad470863SMilanka Ringwalddef get_bits(fin, bit_count):
539ad470863SMilanka Ringwald    bits = 0
540ad470863SMilanka Ringwald    for i in range(bit_count):
541ad470863SMilanka Ringwald        bits = (bits << 1) | get_bit(fin)
542f08a674bSMilanka Ringwald    # print "get bits: %d -> %02x" %(bit_count, bits)
543ad470863SMilanka Ringwald    return bits
544ad470863SMilanka Ringwald
545c21a9c2fSMilanka Ringwald
546c21a9c2fSMilanka Ringwalddef calculate_crc(frame):
547c21a9c2fSMilanka Ringwald    global bitstream, bitstream_bits_available, bitstream_index
548c21a9c2fSMilanka Ringwald    init_bitstream()
549c21a9c2fSMilanka Ringwald
550c21a9c2fSMilanka Ringwald    add_bits(frame.sampling_frequency, 2)
551c21a9c2fSMilanka Ringwald    add_bits(frame.nr_blocks/4-1, 2)
552c21a9c2fSMilanka Ringwald    add_bits(frame.channel_mode, 2)
553c21a9c2fSMilanka Ringwald    add_bits(frame.allocation_method, 1)
554c21a9c2fSMilanka Ringwald    add_bits(frame.nr_subbands/4-1, 1)
555c21a9c2fSMilanka Ringwald    add_bits(frame.bitpool, 8)
556c21a9c2fSMilanka Ringwald    if frame.channel_mode == JOINT_STEREO:
557c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
558c21a9c2fSMilanka Ringwald            add_bits(frame.join[sb],1)
559c21a9c2fSMilanka Ringwald
560c21a9c2fSMilanka Ringwald    for ch in range(frame.nr_channels):
561c21a9c2fSMilanka Ringwald        for sb in range(frame.nr_subbands):
562c21a9c2fSMilanka Ringwald            add_bits(frame.scale_factor[ch][sb], 4)
56341a4a18dSMilanka Ringwald
564c21a9c2fSMilanka Ringwald    bitstream_len = (bitstream_index + 1) * 8
565c21a9c2fSMilanka Ringwald    if bitstream_bits_available:
5665c9bef5bSMilanka Ringwald        bitstream_len -= bitstream_bits_available
5675c9bef5bSMilanka Ringwald
568c21a9c2fSMilanka Ringwald    return sbc_crc8(bitstream, bitstream_len)
569c21a9c2fSMilanka Ringwald
570c21a9c2fSMilanka Ringwald
571c21a9c2fSMilanka Ringwald
572ad470863SMilanka Ringwalddef frame_to_bitstream(frame):
573ad470863SMilanka Ringwald    global bitstream, bitstream_bits_available, bitstream_index
574ad470863SMilanka Ringwald    init_bitstream()
575c21a9c2fSMilanka Ringwald
576ad470863SMilanka Ringwald    add_bits(frame.syncword, 8)
577ad470863SMilanka Ringwald    add_bits(frame.sampling_frequency, 2)
578ad470863SMilanka Ringwald    add_bits(frame.nr_blocks/4-1, 2)
579ad470863SMilanka Ringwald    add_bits(frame.channel_mode, 2)
580ad470863SMilanka Ringwald    add_bits(frame.allocation_method, 1)
581ad470863SMilanka Ringwald    add_bits(frame.nr_subbands/4-1, 1)
582ad470863SMilanka Ringwald    add_bits(frame.bitpool, 8)
583ad470863SMilanka Ringwald    add_bits(frame.crc_check, 8)
584c21a9c2fSMilanka Ringwald
585ad470863SMilanka Ringwald    if frame.channel_mode == JOINT_STEREO:
586ad470863SMilanka Ringwald        for sb in range(frame.nr_subbands-1):
587ad470863SMilanka Ringwald            add_bits(frame.join[sb],1)
588ad470863SMilanka Ringwald        add_bits(0,1)
589ad470863SMilanka Ringwald
590ad470863SMilanka Ringwald    for ch in range(frame.nr_channels):
591ad470863SMilanka Ringwald        for sb in range(frame.nr_subbands):
592ad470863SMilanka Ringwald            add_bits(frame.scale_factor[ch][sb], 4)
593ad470863SMilanka Ringwald
594ad470863SMilanka Ringwald    for blk in range(frame.nr_blocks):
595ad470863SMilanka Ringwald        for ch in range(frame.nr_channels):
596ad470863SMilanka Ringwald            for sb in range(frame.nr_subbands):
597ad470863SMilanka Ringwald                add_bits(frame.audio_sample[blk][ch][sb], frame.bits[ch][sb])
598ad470863SMilanka Ringwald
599ad470863SMilanka Ringwald    bitstream_bits_available = 0
600ad470863SMilanka Ringwald    return bitstream
601ad470863SMilanka Ringwald
602ad470863SMilanka Ringwalddef mse(a,b):
603ad470863SMilanka Ringwald    count = 1
604ad470863SMilanka Ringwald    for i in a.shape:
605ad470863SMilanka Ringwald        count *= i
606ad470863SMilanka Ringwald    delta = a - b
607ad470863SMilanka Ringwald    sqr = delta ** 2
608ad470863SMilanka Ringwald    res = sqr.sum()*1.0/count
609ad470863SMilanka Ringwald    # res = ((a - b) ** 2).mean()
610ad470863SMilanka Ringwald    return res
611