1c21a9c2fSMilanka Ringwald#!/usr/bin/env python 2c21a9c2fSMilanka Ringwaldimport numpy as np 3c21a9c2fSMilanka Ringwaldimport wave 4c21a9c2fSMilanka Ringwaldimport struct 5c21a9c2fSMilanka Ringwaldimport sys 6c21a9c2fSMilanka Ringwaldfrom sbc import * 7c21a9c2fSMilanka Ringwald 8*5c9bef5bSMilanka RingwaldX = np.zeros(shape=(2,80), dtype = np.int16) 9c21a9c2fSMilanka Ringwald 10ad470863SMilanka Ringwald 11ad470863SMilanka Ringwalddef fetch_samples_for_next_sbc_frame(fin, frame): 12*5c9bef5bSMilanka Ringwald nr_samples = frame.nr_blocks * frame.nr_subbands 131522543dSMilanka Ringwald raw_data = fin.readframes(nr_samples) # Returns byte data 14*5c9bef5bSMilanka Ringwald fmt = "%ih" % (len(raw_data) / 2) 151522543dSMilanka Ringwald data = struct.unpack(fmt, raw_data) 161522543dSMilanka Ringwald 17*5c9bef5bSMilanka Ringwald if frame.nr_channels == 2: 18*5c9bef5bSMilanka Ringwald for i in range(len(data)/2 - 1): 19*5c9bef5bSMilanka Ringwald frame.pcm[0][i] = data[2*i] 20*5c9bef5bSMilanka Ringwald frame.pcm[1][i] = data[2*i+1] 211522543dSMilanka Ringwald else: 22*5c9bef5bSMilanka Ringwald for i in range(len(data)): 23*5c9bef5bSMilanka Ringwald frame.pcm[0][i] = data[i] 24c21a9c2fSMilanka Ringwald 25c21a9c2fSMilanka Ringwald 26ad470863SMilanka Ringwalddef sbc_frame_analysis(frame, ch, blk, C): 27c21a9c2fSMilanka Ringwald global X 28ad470863SMilanka Ringwald 29c21a9c2fSMilanka Ringwald M = frame.nr_subbands 30c21a9c2fSMilanka Ringwald L = 10 * M 31c21a9c2fSMilanka Ringwald M2 = 2*M 32c21a9c2fSMilanka Ringwald L2 = 2*L 33c21a9c2fSMilanka Ringwald 34c21a9c2fSMilanka Ringwald Z = np.zeros(L) 35c21a9c2fSMilanka Ringwald Y = np.zeros(M2) 36c21a9c2fSMilanka Ringwald W = np.zeros(shape=(M, M2)) 37c21a9c2fSMilanka Ringwald S = np.zeros(M) 38c21a9c2fSMilanka Ringwald 39c21a9c2fSMilanka Ringwald for i in range(L-1, M-1, -1): 40*5c9bef5bSMilanka Ringwald X[ch][i] = X[ch][i-M] 41c21a9c2fSMilanka Ringwald for i in range(M-1, -1, -1): 42*5c9bef5bSMilanka Ringwald X[ch][i] = frame.EX[M-1-i] 43c21a9c2fSMilanka Ringwald 44c21a9c2fSMilanka Ringwald for i in range(L): 45*5c9bef5bSMilanka Ringwald Z[i] = X[ch][i] * C[i] 46c21a9c2fSMilanka Ringwald 47c21a9c2fSMilanka Ringwald for i in range(M2): 48c21a9c2fSMilanka Ringwald for k in range(5): 49af086c98SMilanka Ringwald Y[i] += Z[i+k*M2] 50c21a9c2fSMilanka Ringwald 51c21a9c2fSMilanka Ringwald for i in range(M): 52c21a9c2fSMilanka Ringwald for k in range(M2): 53af086c98SMilanka Ringwald W[i][k] = np.cos((i+0.5)*(k-M/2)*np.pi/M) 54c21a9c2fSMilanka Ringwald S[i] += W[i][k] * Y[k] 55c21a9c2fSMilanka Ringwald 56c21a9c2fSMilanka Ringwald for sb in range(M): 57c21a9c2fSMilanka Ringwald frame.sb_sample[blk][ch][sb] = S[sb] 58c21a9c2fSMilanka Ringwald 59ad470863SMilanka Ringwalddef sbc_analysis(frame): 60c21a9c2fSMilanka Ringwald if frame.nr_subbands == 4: 61ad470863SMilanka Ringwald C = Proto_4_40 62c21a9c2fSMilanka Ringwald elif frame.nr_subbands == 8: 63ad470863SMilanka Ringwald C = Proto_8_80 64c21a9c2fSMilanka Ringwald else: 65c21a9c2fSMilanka Ringwald return -1 66c21a9c2fSMilanka Ringwald 67c21a9c2fSMilanka Ringwald frame.sb_sample = np.ndarray(shape=(frame.nr_blocks, frame.nr_channels, frame.nr_subbands)) 68c21a9c2fSMilanka Ringwald for ch in range(frame.nr_channels): 69*5c9bef5bSMilanka Ringwald index = 0 70c21a9c2fSMilanka Ringwald for blk in range(frame.nr_blocks): 71c21a9c2fSMilanka Ringwald for sb in range(frame.nr_subbands): 721522543dSMilanka Ringwald frame.EX[sb] = np.int16(frame.pcm[ch][index]) 73c21a9c2fSMilanka Ringwald index+=1 74ad470863SMilanka Ringwald sbc_frame_analysis(frame, ch, blk, C) 75ad470863SMilanka Ringwald return 0 76c21a9c2fSMilanka Ringwald 77ad470863SMilanka Ringwalddef sbc_encode(frame): 78ad470863SMilanka Ringwald err = sbc_analysis(frame) 79ad470863SMilanka Ringwald if err >= 0: 80ad470863SMilanka Ringwald err = sbc_quantization(frame) 81ad470863SMilanka Ringwald return err 82c21a9c2fSMilanka Ringwald 83c21a9c2fSMilanka Ringwalddef sbc_quantization(frame): 84*5c9bef5bSMilanka Ringwald frame.scale_factor, frame.scalefactor = calculate_scalefactors(frame.nr_blocks, frame.nr_channels, frame.nr_subbands, frame.sb_sample) 85*5c9bef5bSMilanka Ringwald calculate_channel_mode(frame) 86c21a9c2fSMilanka Ringwald frame.bits = sbc_bit_allocation(frame) 87c21a9c2fSMilanka Ringwald 88c21a9c2fSMilanka Ringwald # Reconstruct the Audio Samples 89c21a9c2fSMilanka Ringwald frame.levels = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32) 90c21a9c2fSMilanka Ringwald for ch in range(frame.nr_channels): 91c21a9c2fSMilanka Ringwald for sb in range(frame.nr_subbands): 92ad470863SMilanka Ringwald frame.levels[ch][sb] = (1 << frame.bits[ch][sb]) - 1 #pow(2.0, frame.bits[ch][sb]) - 1 93c21a9c2fSMilanka Ringwald 94c21a9c2fSMilanka Ringwald frame.syncword = 156 95c21a9c2fSMilanka Ringwald frame.crc_check = calculate_crc(frame) 96c21a9c2fSMilanka Ringwald 97c21a9c2fSMilanka Ringwald for blk in range(frame.nr_blocks): 98c21a9c2fSMilanka Ringwald for ch in range(frame.nr_channels): 99c21a9c2fSMilanka Ringwald for sb in range(frame.nr_subbands): 100c21a9c2fSMilanka Ringwald if frame.levels[ch][sb] > 0: 101c21a9c2fSMilanka Ringwald SB = frame.sb_sample[blk][ch][sb] 102c21a9c2fSMilanka Ringwald L = frame.levels[ch][sb] 103ad470863SMilanka Ringwald SF = frame.scalefactor[ch][sb] 10441a4a18dSMilanka Ringwald frame.audio_sample[blk][ch][sb] = np.uint16(((SB * L / SF + L) - 1.0)/2.0) 105c21a9c2fSMilanka Ringwald else: 106c21a9c2fSMilanka Ringwald frame.audio_sample[blk][ch][sb] = 0 107c21a9c2fSMilanka Ringwald 108c21a9c2fSMilanka Ringwald return 0 109c21a9c2fSMilanka Ringwald 110ad470863SMilanka Ringwalddef sbc_write_frame(fout, sbc_encoder_frame): 111ad470863SMilanka Ringwald stream = frame_to_bitstream(sbc_encoder_frame) 112ad470863SMilanka Ringwald barray = bytearray(stream) 113ad470863SMilanka Ringwald fout.write(barray) 114ad470863SMilanka Ringwald 115ba114a98SMatthias Ringwaldif __name__ == "__main__": 116ba114a98SMatthias Ringwald usage = ''' 1175665ea35SMilanka Ringwald Usage: ./sbc_encoder.py input.wav blocks subbands bitpool allocation_method[0-LOUDNESS,1-SNR] 1185665ea35SMilanka Ringwald Example: ./sbc_encoder.py fanfare.wav 16 4 31 0 119ba114a98SMatthias Ringwald ''' 120ba114a98SMatthias Ringwald nr_blocks = 0 121ba114a98SMatthias Ringwald nr_subbands = 0 122c21a9c2fSMilanka Ringwald 123ad470863SMilanka Ringwald 1245665ea35SMilanka Ringwald if (len(sys.argv) < 6): 125ba114a98SMatthias Ringwald print(usage) 126ba114a98SMatthias Ringwald sys.exit(1) 127ba114a98SMatthias Ringwald try: 128ba114a98SMatthias Ringwald infile = sys.argv[1] 129ba114a98SMatthias Ringwald if not infile.endswith('.wav'): 130ba114a98SMatthias Ringwald print(usage) 131ba114a98SMatthias Ringwald sys.exit(1) 132ad470863SMilanka Ringwald sbcfile = infile.replace('.wav', '-encoded.sbc') 133ad470863SMilanka Ringwald 134ba114a98SMatthias Ringwald nr_blocks = int(sys.argv[2]) 135ba114a98SMatthias Ringwald nr_subbands = int(sys.argv[3]) 136ba114a98SMatthias Ringwald bitpool = int(sys.argv[4]) 1375665ea35SMilanka Ringwald allocation_method = int(sys.argv[5]) 138c21a9c2fSMilanka Ringwald 139ba114a98SMatthias Ringwald fin = wave.open(infile, 'rb') 140ad470863SMilanka Ringwald nr_channels = fin.getnchannels() 141ad470863SMilanka Ringwald sampling_frequency = fin.getframerate() 142ad470863SMilanka Ringwald nr_audio_frames = fin.getnframes() 143c21a9c2fSMilanka Ringwald 144ad470863SMilanka Ringwald subband_frame_count = 0 145ba114a98SMatthias Ringwald audio_frame_count = 0 146ad470863SMilanka Ringwald nr_samples = nr_blocks * nr_subbands 147ad470863SMilanka Ringwald fout = open(sbcfile, 'wb') 148ad470863SMilanka Ringwald while audio_frame_count < nr_audio_frames: 149ad470863SMilanka Ringwald if subband_frame_count % 200 == 0: 150ad470863SMilanka Ringwald print("== Frame %d ==" % (subband_frame_count)) 151c21a9c2fSMilanka Ringwald 1525665ea35SMilanka Ringwald sbc_encoder_frame = SBCFrame(nr_blocks, nr_subbands, nr_channels, bitpool, sampling_frequency, allocation_method) 153ad470863SMilanka Ringwald fetch_samples_for_next_sbc_frame(fin, sbc_encoder_frame) 154c21a9c2fSMilanka Ringwald 155ad470863SMilanka Ringwald sbc_encode(sbc_encoder_frame) 156ad470863SMilanka Ringwald sbc_write_frame(fout, sbc_encoder_frame) 157c21a9c2fSMilanka Ringwald 158*5c9bef5bSMilanka Ringwald # if subband_frame_count == 0: 159*5c9bef5bSMilanka Ringwald # exit(0) 160ad470863SMilanka Ringwald audio_frame_count += nr_samples 161ad470863SMilanka Ringwald subband_frame_count += 1 162c21a9c2fSMilanka Ringwald 163*5c9bef5bSMilanka Ringwald 164ad470863SMilanka Ringwald fin.close() 165ad470863SMilanka Ringwald fout.close() 166ad470863SMilanka Ringwald print("DONE, WAV file %s encoded into SBC file %s " % (infile, sbcfile)) 167c21a9c2fSMilanka Ringwald 168c21a9c2fSMilanka Ringwald 169ba114a98SMatthias Ringwald except IOError as e: 170ba114a98SMatthias Ringwald print(usage) 171ba114a98SMatthias Ringwald sys.exit(1) 172c21a9c2fSMilanka Ringwald 173c21a9c2fSMilanka Ringwald 174c21a9c2fSMilanka Ringwald 175c21a9c2fSMilanka Ringwald 176c21a9c2fSMilanka Ringwald 177