15f21c38aSMilanka Ringwald#!/usr/bin/env python 25f21c38aSMilanka Ringwaldimport numpy as np 35f21c38aSMilanka Ringwaldimport wave 45f21c38aSMilanka Ringwaldimport struct 55f21c38aSMilanka Ringwaldimport sys 65f21c38aSMilanka Ringwaldfrom sbc import * 75f21c38aSMilanka Ringwaldfrom sbc_encoder import * 85f21c38aSMilanka Ringwaldfrom sbc_decoder import * 95f21c38aSMilanka Ringwald 105f21c38aSMilanka Ringwalderror = 0.99 115f21c38aSMilanka Ringwaldmax_error = -1 125f21c38aSMilanka Ringwald 135f21c38aSMilanka Ringwalddef sbc_compare_pcm(frame_count, actual_frame, expected_frame): 145f21c38aSMilanka Ringwald global error, max_error 151522543dSMilanka Ringwald for ch in range(actual_frame.nr_channels): 161522543dSMilanka Ringwald M = mse(actual_frame.pcm[ch], expected_frame.pcm[ch]) 175f21c38aSMilanka Ringwald if M > max_error: 185f21c38aSMilanka Ringwald max_error = M 195f21c38aSMilanka Ringwald 20*ef8a7a12SMilanka Ringwald if max_error > error: 21*ef8a7a12SMilanka Ringwald print "pcm error (%d, %f ) " % (frame_count, max_error) 225f21c38aSMilanka Ringwald return -1 235f21c38aSMilanka Ringwald return 0 245f21c38aSMilanka Ringwald 255f21c38aSMilanka Ringwald 265f21c38aSMilanka Ringwalddef sbc_compare_headers(frame_count, actual_frame, expected_frame): 275f21c38aSMilanka Ringwald if actual_frame.sampling_frequency != expected_frame.sampling_frequency: 285f21c38aSMilanka Ringwald print "sampling_frequency wrong ", actual_frame.sampling_frequency 295f21c38aSMilanka Ringwald return -1 305f21c38aSMilanka Ringwald 315f21c38aSMilanka Ringwald if actual_frame.nr_blocks != expected_frame.nr_blocks: 325f21c38aSMilanka Ringwald print "nr_blocks wrong ", actual_frame.nr_blocks 335f21c38aSMilanka Ringwald return -1 345f21c38aSMilanka Ringwald 355f21c38aSMilanka Ringwald if actual_frame.channel_mode != expected_frame.channel_mode: 365f21c38aSMilanka Ringwald print "channel_mode wrong ", actual_frame.channel_mode 375f21c38aSMilanka Ringwald return -1 385f21c38aSMilanka Ringwald 395f21c38aSMilanka Ringwald if actual_frame.nr_channels != expected_frame.nr_channels: 405f21c38aSMilanka Ringwald print "nr_channels wrong ", actual_frame.nr_channels 415f21c38aSMilanka Ringwald return -1 425f21c38aSMilanka Ringwald 435f21c38aSMilanka Ringwald if actual_frame.allocation_method != expected_frame.allocation_method: 445f21c38aSMilanka Ringwald print "allocation_method wrong ", actual_frame.allocation_method 455f21c38aSMilanka Ringwald return -1 465f21c38aSMilanka Ringwald 475f21c38aSMilanka Ringwald if actual_frame.nr_subbands != expected_frame.nr_subbands: 485f21c38aSMilanka Ringwald print "nr_subbands wrong ", actual_frame.nr_subbands 495f21c38aSMilanka Ringwald return -1 505f21c38aSMilanka Ringwald 515f21c38aSMilanka Ringwald if actual_frame.bitpool != expected_frame.bitpool: 525f21c38aSMilanka Ringwald print "bitpool wrong (E: %d, D: %d)" % (actual_frame.bitpool, expected_frame.bitpool) 535f21c38aSMilanka Ringwald return -1 545f21c38aSMilanka Ringwald 555f21c38aSMilanka Ringwald return 0 565f21c38aSMilanka Ringwald 574771dcb8SMilanka Ringwaldfile_size = 0 585f21c38aSMilanka Ringwalddef get_actual_frame(fin): 594771dcb8SMilanka Ringwald global file_size 605f21c38aSMilanka Ringwald actual_frame = SBCFrame() 614771dcb8SMilanka Ringwald sbc_unpack_frame(fin, file_size - fin.tell(), actual_frame) 625f21c38aSMilanka Ringwald sbc_reconstruct_subband_samples(actual_frame) 635f21c38aSMilanka Ringwald sbc_synthesis(actual_frame) 645f21c38aSMilanka Ringwald return actual_frame 655f21c38aSMilanka Ringwald 665665ea35SMilanka Ringwalddef get_expected_frame(fin_expected, nr_blocks, nr_subbands, nr_channels, sampling_frequency, bitpool, allocation_method): 675665ea35SMilanka Ringwald expected_frame = SBCFrame(nr_blocks, nr_subbands, nr_channels, sampling_frequency, bitpool, allocation_method) 685f21c38aSMilanka Ringwald fetch_samples_for_next_sbc_frame(fin_expected, expected_frame) 69*ef8a7a12SMilanka Ringwald calculate_channel_mode_and_scale_factors(expected_frame) 705f21c38aSMilanka Ringwald return expected_frame 715f21c38aSMilanka Ringwald 725f21c38aSMilanka Ringwaldusage = ''' 735f21c38aSMilanka RingwaldUsage: ./sbc_decoder_test.py decoder_input.sbc decoder_expected_output.wav 745f21c38aSMilanka RingwaldExample: ./sbc_decoder_test.py fanfare-4sb.sbc fanfare-4sb-decoded.wav 755f21c38aSMilanka Ringwald''' 765f21c38aSMilanka Ringwald 775f21c38aSMilanka Ringwaldif (len(sys.argv) < 3): 785f21c38aSMilanka Ringwald print(usage) 795f21c38aSMilanka Ringwald sys.exit(1) 805f21c38aSMilanka Ringwaldtry: 815f21c38aSMilanka Ringwald decoder_input_sbc = sys.argv[1] 825f21c38aSMilanka Ringwald decoder_expected_wav = sys.argv[2] 835f21c38aSMilanka Ringwald 845f21c38aSMilanka Ringwald if not decoder_input_sbc.endswith('.sbc'): 855f21c38aSMilanka Ringwald print(usage) 865f21c38aSMilanka Ringwald sys.exit(1) 875f21c38aSMilanka Ringwald 885f21c38aSMilanka Ringwald if not decoder_expected_wav.endswith('.wav'): 895f21c38aSMilanka Ringwald print(usage) 905f21c38aSMilanka Ringwald sys.exit(1) 915f21c38aSMilanka Ringwald 925f21c38aSMilanka Ringwald fin_expected = wave.open(decoder_expected_wav, 'rb') 935f21c38aSMilanka Ringwald nr_channels, sampwidth, sampling_frequency, nr_audio_frames, comptype, compname = fin_expected.getparams() 945f21c38aSMilanka Ringwald 955f21c38aSMilanka Ringwald with open(decoder_input_sbc, 'rb') as fin: 965f21c38aSMilanka Ringwald try: 975f21c38aSMilanka Ringwald subband_frame_count = 0 984771dcb8SMilanka Ringwald fin.seek(0,2) 994771dcb8SMilanka Ringwald file_size = fin.tell() 1004771dcb8SMilanka Ringwald fin.seek(0,0) 1014771dcb8SMilanka Ringwald 1025f21c38aSMilanka Ringwald while True: 1035f21c38aSMilanka Ringwald if subband_frame_count % 200 == 0: 1044771dcb8SMilanka Ringwald print ("== Frame %d ==" % subband_frame_count) 1055f21c38aSMilanka Ringwald 106f08a674bSMilanka Ringwald 1075f21c38aSMilanka Ringwald actual_frame = get_actual_frame(fin) 1085f21c38aSMilanka Ringwald 1094771dcb8SMilanka Ringwald 1105f21c38aSMilanka Ringwald expected_frame = get_expected_frame(fin_expected, actual_frame.nr_blocks, 1115f21c38aSMilanka Ringwald actual_frame.nr_subbands, nr_channels, 1125665ea35SMilanka Ringwald actual_frame.bitpool, sampling_frequency, 1135665ea35SMilanka Ringwald actual_frame.allocation_method) 1145f21c38aSMilanka Ringwald 1155f21c38aSMilanka Ringwald err = sbc_compare_headers(subband_frame_count, actual_frame, expected_frame) 116f08a674bSMilanka Ringwald 1175f21c38aSMilanka Ringwald if err < 0: 1184771dcb8SMilanka Ringwald print ("Headers differ \n%s\n%s" % (actual_frame, expected_frame)) 119*ef8a7a12SMilanka Ringwald sys.exit(1) 1205f21c38aSMilanka Ringwald 1215f21c38aSMilanka Ringwald err = sbc_compare_pcm(subband_frame_count, actual_frame, expected_frame) 1225f21c38aSMilanka Ringwald if err < 0: 1234771dcb8SMilanka Ringwald print ("PCMs differ \n%s\n%s" % (actual_frame.pcm, expected_frame.pcm)) 124*ef8a7a12SMilanka Ringwald sys.exit(1) 1255f21c38aSMilanka Ringwald 1265665ea35SMilanka Ringwald if subband_frame_count == 0: 1274771dcb8SMilanka Ringwald print actual_frame, expected_frame 1285665ea35SMilanka Ringwald 1295f21c38aSMilanka Ringwald subband_frame_count += 1 1305f21c38aSMilanka Ringwald 1315f21c38aSMilanka Ringwald except TypeError: 1325f21c38aSMilanka Ringwald fin_expected.close() 1335f21c38aSMilanka Ringwald fin.close() 134f08a674bSMilanka Ringwald print ("DONE, max MSE PCM error %f" % max_error) 1355f21c38aSMilanka Ringwald 1365f21c38aSMilanka Ringwaldexcept IOError as e: 1375f21c38aSMilanka Ringwald print(usage) 1385f21c38aSMilanka Ringwald sys.exit(1) 1395f21c38aSMilanka Ringwald 1405f21c38aSMilanka Ringwald 1415f21c38aSMilanka Ringwald 1425f21c38aSMilanka Ringwald 1435f21c38aSMilanka Ringwald 144