xref: /btstack/test/sbc/sbc_decoder_test.py (revision 4771dcb8bbb128f1a2264324662f0c69d4e4d9eb)
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
155f21c38aSMilanka Ringwald
165f21c38aSMilanka Ringwald    M = mse(actual_frame.pcm, expected_frame.pcm)
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
57*4771dcb8SMilanka Ringwaldfile_size = 0
585f21c38aSMilanka Ringwalddef get_actual_frame(fin):
59*4771dcb8SMilanka Ringwald    global file_size
605f21c38aSMilanka Ringwald    actual_frame = SBCFrame()
61*4771dcb8SMilanka 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)
695f21c38aSMilanka Ringwald    return expected_frame
705f21c38aSMilanka Ringwald
715f21c38aSMilanka Ringwaldusage = '''
725f21c38aSMilanka RingwaldUsage:      ./sbc_decoder_test.py decoder_input.sbc decoder_expected_output.wav
735f21c38aSMilanka RingwaldExample:    ./sbc_decoder_test.py fanfare-4sb.sbc fanfare-4sb-decoded.wav
745f21c38aSMilanka Ringwald'''
755f21c38aSMilanka Ringwald
765f21c38aSMilanka Ringwaldif (len(sys.argv) < 3):
775f21c38aSMilanka Ringwald    print(usage)
785f21c38aSMilanka Ringwald    sys.exit(1)
795f21c38aSMilanka Ringwaldtry:
805f21c38aSMilanka Ringwald    decoder_input_sbc = sys.argv[1]
815f21c38aSMilanka Ringwald    decoder_expected_wav = sys.argv[2]
825f21c38aSMilanka Ringwald
835f21c38aSMilanka Ringwald    if not decoder_input_sbc.endswith('.sbc'):
845f21c38aSMilanka Ringwald        print(usage)
855f21c38aSMilanka Ringwald        sys.exit(1)
865f21c38aSMilanka Ringwald
875f21c38aSMilanka Ringwald    if not decoder_expected_wav.endswith('.wav'):
885f21c38aSMilanka Ringwald        print(usage)
895f21c38aSMilanka Ringwald        sys.exit(1)
905f21c38aSMilanka Ringwald
915f21c38aSMilanka Ringwald    fin_expected = wave.open(decoder_expected_wav, 'rb')
925f21c38aSMilanka Ringwald    nr_channels, sampwidth, sampling_frequency, nr_audio_frames, comptype, compname =  fin_expected.getparams()
935f21c38aSMilanka Ringwald
945f21c38aSMilanka Ringwald    with open(decoder_input_sbc, 'rb') as fin:
955f21c38aSMilanka Ringwald        try:
965f21c38aSMilanka Ringwald            subband_frame_count = 0
97*4771dcb8SMilanka Ringwald            fin.seek(0,2)
98*4771dcb8SMilanka Ringwald            file_size = fin.tell()
99*4771dcb8SMilanka Ringwald            fin.seek(0,0)
100*4771dcb8SMilanka Ringwald
1015f21c38aSMilanka Ringwald            while True:
1025f21c38aSMilanka Ringwald                if subband_frame_count % 200 == 0:
103*4771dcb8SMilanka Ringwald                    print ("== Frame %d ==" % subband_frame_count)
1045f21c38aSMilanka Ringwald
1055f21c38aSMilanka Ringwald                actual_frame = get_actual_frame(fin)
1065f21c38aSMilanka Ringwald
107*4771dcb8SMilanka Ringwald
1085f21c38aSMilanka Ringwald                expected_frame = get_expected_frame(fin_expected, actual_frame.nr_blocks,
1095f21c38aSMilanka Ringwald                                                actual_frame.nr_subbands, nr_channels,
1105665ea35SMilanka Ringwald                                                actual_frame.bitpool, sampling_frequency,
1115665ea35SMilanka Ringwald                                                actual_frame.allocation_method)
1125f21c38aSMilanka Ringwald
1135f21c38aSMilanka Ringwald
1145f21c38aSMilanka Ringwald                err = sbc_compare_headers(subband_frame_count, actual_frame, expected_frame)
1155f21c38aSMilanka Ringwald                if err < 0:
116*4771dcb8SMilanka Ringwald                    print ("Headers differ \n%s\n%s" % (actual_frame, expected_frame))
1175f21c38aSMilanka Ringwald                    exit(1)
1185f21c38aSMilanka Ringwald
1195f21c38aSMilanka Ringwald                err = sbc_compare_pcm(subband_frame_count, actual_frame, expected_frame)
1205f21c38aSMilanka Ringwald                if err < 0:
121*4771dcb8SMilanka Ringwald                    print ("PCMs differ \n%s\n%s" % (actual_frame.pcm, expected_frame.pcm))
1225f21c38aSMilanka Ringwald                    exit(1)
1235f21c38aSMilanka Ringwald
1245665ea35SMilanka Ringwald                if subband_frame_count == 0:
125*4771dcb8SMilanka Ringwald                    print actual_frame, expected_frame
1265665ea35SMilanka Ringwald
1275f21c38aSMilanka Ringwald                subband_frame_count += 1
1285f21c38aSMilanka Ringwald
1295f21c38aSMilanka Ringwald        except TypeError:
1305f21c38aSMilanka Ringwald            fin_expected.close()
1315f21c38aSMilanka Ringwald            fin.close()
132*4771dcb8SMilanka Ringwald            print ("DONE, max MSE PCM error %d" % max_error)
1335f21c38aSMilanka Ringwald            exit(0)
1345f21c38aSMilanka Ringwald
1355f21c38aSMilanka Ringwaldexcept IOError as e:
1365f21c38aSMilanka Ringwald    print(usage)
1375f21c38aSMilanka Ringwald    sys.exit(1)
1385f21c38aSMilanka Ringwald
1395f21c38aSMilanka Ringwald
1405f21c38aSMilanka Ringwald
1415f21c38aSMilanka Ringwald
1425f21c38aSMilanka Ringwald
143