xref: /btstack/test/sbc/sbc_decoder_test.py (revision f08a674b88cd54d27621208e04242ed1acac4ed1)
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
205f21c38aSMilanka Ringwald        if M > error:
215f21c38aSMilanka Ringwald            print "pcm error (%d, %d ) " % (frame_count, M)
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)
691522543dSMilanka Ringwald    calculate_scalefactors_and_channel_mode(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
106*f08a674bSMilanka 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)
116*f08a674bSMilanka Ringwald                print ("%03d : %s %s"%( subband_frame_count,
117*f08a674bSMilanka Ringwald                                    channel_mode_to_str(actual_frame.channel_mode),
118*f08a674bSMilanka Ringwald                                    channel_mode_to_str(expected_frame.channel_mode)))
119*f08a674bSMilanka Ringwald
1205f21c38aSMilanka Ringwald                if err < 0:
1214771dcb8SMilanka Ringwald                    print ("Headers differ \n%s\n%s" % (actual_frame, expected_frame))
1225f21c38aSMilanka Ringwald                    exit(1)
1235f21c38aSMilanka Ringwald
1245f21c38aSMilanka Ringwald                err = sbc_compare_pcm(subband_frame_count, actual_frame, expected_frame)
1255f21c38aSMilanka Ringwald                if err < 0:
1264771dcb8SMilanka Ringwald                    print ("PCMs differ \n%s\n%s" % (actual_frame.pcm, expected_frame.pcm))
1275f21c38aSMilanka Ringwald                    exit(1)
1285f21c38aSMilanka Ringwald
1295665ea35SMilanka Ringwald                if subband_frame_count == 0:
1304771dcb8SMilanka Ringwald                    print actual_frame, expected_frame
1315665ea35SMilanka Ringwald
1325f21c38aSMilanka Ringwald                subband_frame_count += 1
1335f21c38aSMilanka Ringwald
1345f21c38aSMilanka Ringwald        except TypeError:
1355f21c38aSMilanka Ringwald            fin_expected.close()
1365f21c38aSMilanka Ringwald            fin.close()
137*f08a674bSMilanka Ringwald            print ("DONE, max MSE PCM error %f" % max_error)
1385f21c38aSMilanka Ringwald            exit(0)
1395f21c38aSMilanka Ringwald
1405f21c38aSMilanka Ringwaldexcept IOError as e:
1415f21c38aSMilanka Ringwald    print(usage)
1425f21c38aSMilanka Ringwald    sys.exit(1)
1435f21c38aSMilanka Ringwald
1445f21c38aSMilanka Ringwald
1455f21c38aSMilanka Ringwald
1465f21c38aSMilanka Ringwald
1475f21c38aSMilanka Ringwald
148