Re: [Bluez-devel] sbc analysis code

Brad Midgley
2007-10-11T16:48:19Z

[-- Attachment #1: Type: text/plain, Size: 194 bytes --]

Marcel

it is currently in its own autoconf harness but I would just use the one c file.

> can I see the code first please. So post it to the mailing list and then
> I have a look at it.

Brad

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: sbctester.c --]
[-- Type: text/x-csrc; name="sbctester.c", Size: 8711 bytes --]

/* *
* Copyright (C) 2007 by Frédéric Dalleau *
* fdalleau@free.fr *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

/*

A2DP Test Specification Chapter 4.6 (p 25)
namely SBC codec conformance test
This is a test procedure for SBC

*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sndfile.h>
#include <math.h>
#include <string.h>

#define MAXCHANNELS 2
#define MAXFRAMESTESTED infostst->frames
#define TSTSAMPLEFACTOR(x) (x)
#define DEFACCURACY 7

void usage()
{
printf("usage: sbctester <reference> <filetocheck>\t\tCheck sbc decoded file against spec\n");
printf("usage: sbctester <integer>\t\tTest normalize fonction\n");
}

double sampletobits(short sample16, int verbose)
{
double bits = 0;
int i;

if(verbose)
printf("=======> sampletobits(%hd, %04hX)\n", sample16, sample16);

// Bit 0 is MSB
if(sample16 < 0) {
bits = -1;
}
if(verbose)
printf("%d", (sample16 < 0)?1:0);

// Bit 15 is LSB
for(i=1; i<16; i++)
{
unsigned short bit = (unsigned short)sample16;
bit >>= 15-i;
bit %= 2;
if(verbose)
printf("%d", bit);

if(bit)
bits += (1.0/pow(2.0, i));
}
if(verbose)
printf("\n");
return bits;
}

int calculate_rms_level(SNDFILE* sndref, SF_INFO* infosref, SNDFILE* sndtst, SF_INFO* infostst, int accuracy, char* csvname)
{
int i, j, verdict = 0;
short refsample[MAXCHANNELS], tstsample[MAXCHANNELS];
double refbits, tstbits;
double rms;
double rms_accu[MAXCHANNELS];
double rms_level[MAXCHANNELS];
double rms_limit = 1.0/(pow(2.0, accuracy-1)*pow(12.0,0.5));
FILE* csv = NULL;

if(csvname) {
csv = fopen(csvname, "wt");
}

if(csv) {
fprintf(csv, "num;");
for(j = 0; j<infostst->channels; j++)
{
fprintf(csv,"ref channel %d;tst channel %d;", j, j);
}
fprintf(csv,"\r\n");
}

sf_seek(sndref, 0, SEEK_SET);
sf_seek(sndtst, 0, SEEK_SET);
memset(rms_accu, 0, sizeof(rms_accu));
memset(rms_level, 0, sizeof(rms_level));

for(i = 0; i<MAXFRAMESTESTED; i++)
{
int r1;
if(csv)
fprintf(csv,"%d;", i);
r1 = sf_read_short(sndref, refsample, infostst->channels);
if(r1==infostst->channels) {
int r2 = sf_read_short(sndtst, tstsample, infostst->channels);
if(r2==infostst->channels) {
for(j = 0; j<infostst->channels; j++)
{
if(csv)
fprintf(csv,"%d;%d;", refsample[j], tstsample[j]);

refbits = sampletobits(refsample[j], 0);
tstbits = sampletobits(TSTSAMPLEFACTOR(tstsample[j]), 0);

rms_accu[j] += pow(tstbits - refbits, 2.0);
}
} else {
printf("Failed to read test data:%s (r2=%d, channels=%d)\n", sf_strerror(sndtst), r2, infostst->channels);
exit(0);
}
} else {
printf("Failed to read reference data:%s (r1=%d, channels=%d)", sf_strerror(sndref), r1, infostst->channels);
exit(0);
}

if(csv)
fprintf(csv,"\r\n");
}

if(csv)
fclose(csv);

printf("Limit: %f\n", rms_limit);

for(j = 0; j<infostst->channels; j++)
{
printf("Channel %d\n", j);
printf("Accumulated %f\n", rms_accu[j]);
rms_accu[j] /= (double)infostst->frames;
printf("Accumulated / %f = %f\n", (double)infostst->frames, rms_accu[j]);
rms_level[j] = sqrt(rms_accu[j]);
printf("Level = %f (%f x %f = %f)\n", rms_level[j], rms_level[j], rms_level[j], rms_level[j]*rms_level[j]);
}

verdict = 1;
for(j = 0; j<infostst->channels; j++)
{
printf("Channel %d: %f\n", j, rms_level[j]);

if(rms_level[j] > rms_limit)
verdict = 0;
}

printf("%s return %d\n", __FUNCTION__, verdict);
return verdict;
}

int check_absolute_diff(SNDFILE* sndref, SF_INFO* infosref, SNDFILE* sndtst, SF_INFO* infostst, int accuracy)
{
int i, j, verdict = 0;
short refsample[MAXCHANNELS], tstsample[MAXCHANNELS], refmax[MAXCHANNELS], tstmax[MAXCHANNELS];
double refbits, tstbits;
double rms_absolute = 1.0/(pow(2, accuracy-2));
double calc_max[MAXCHANNELS];
int calc_count = 0;

memset(&refmax, 0, sizeof(refmax));
memset(&tstmax, 0, sizeof(tstmax));
memset(&calc_max, 0, sizeof(calc_max));

verdict = 1;
sf_seek(sndref, 0, SEEK_SET);
sf_seek(sndtst, 0, SEEK_SET);

printf("Absolute max: %f\n", rms_absolute);
for(i = 0; i<MAXFRAMESTESTED; i++)
{
short r1;
r1 = sf_read_short(sndref, refsample, infostst->channels);
if(r1==infostst->channels) {
int r2 = sf_read_short(sndtst, tstsample, infostst->channels);
if(r2==infostst->channels) {
for(j = 0; j<infostst->channels; j++)
{
double cur_diff;

refbits = sampletobits(refsample[j], 0);
tstbits = sampletobits(TSTSAMPLEFACTOR(tstsample[j]), 0);

cur_diff = fabs(tstbits-refbits);

if(cur_diff > rms_absolute) {
calc_count ++;
//printf("Channel %d exceeded : fabs(%f - %f) = %f > %f\n", j, tstbits, refbits, cur_diff, rms_absolute);
verdict = 0;
}
if(cur_diff > calc_max[j]) {
calc_max[j] = cur_diff;
refmax[j] = refsample[j];
tstmax[j] = tstsample[j];
}
}
} else {
printf("Failed to read test data:%s (r2=%d, channels=%d)\n", sf_strerror(sndtst), r2, infostst->channels);
exit(0);
}
} else {
printf("Failed to read reference data:%s (r1=%d, channels=%d)", sf_strerror(sndref), r1, infostst->channels);
exit(0);
}
}

for(j = 0; j<infostst->channels; j++) {
printf("Calculated max: %f (%hd-%hd=%hd)\n", calc_max[j], tstmax[j], refmax[j], tstmax[j]-refmax[j]);
}

printf("%s return %d\n", __FUNCTION__, verdict);
return verdict;
}

int main(int argc, char *argv[])
{
char* ref;
char* tst;
SNDFILE* sndref;
SNDFILE* sndtst;
SF_INFO infosref;
SF_INFO infostst;

if(argc==2)
{
double db;
printf("Test sampletobits\n");
db = sampletobits((short)atoi(argv[1]), 1);
printf("db = %f\n", db);
exit(0);
}

if(argc<3)
{
usage();
exit(1);
}

ref = argv[1];
tst = argv[2];

// open both files
printf("opening reference %s\n", ref);

sndref = sf_open(ref, SFM_READ, &infosref);
if(sndref)
{
printf("opening testfile %s\n", tst);
sndtst = sf_open(tst, SFM_READ, &infostst) ;
if(sndtst)
{
printf("reference:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", (int)infosref.frames, (int)infosref.samplerate, (int)infosref.channels);
printf("testfile:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", (int)infostst.frames, (int)infostst.samplerate, (int)infostst.channels);

// check number of channels
if(infosref.channels <= 2 && infostst.channels <= 2)
{
// compare number of samples
if(/*infosref.frames == infostst.frames && */infosref.samplerate == infostst.samplerate && infosref.channels == infostst.channels)
{
int accuracy = DEFACCURACY;
printf("Accuracy: %d\n", accuracy);
int rms_absolute, pass_rms, pass_absolute, pass;

// Condition 1 rms level
pass_rms = calculate_rms_level(sndref, &infosref, sndtst, &infostst, accuracy, "out.csv");

// Condition 2 absolute difference
pass_absolute = check_absolute_diff(sndref, &infosref, sndtst, &infostst, accuracy);

// Verdict
pass = pass_rms && pass_absolute;
printf("Verdict: %s\n", pass ? "pass" : "fail");
}
else
{
printf("Cannot compare files with different charasteristics\n");
}
}
else
{
printf("Too many channels\n");
}
sf_close(sndtst);
}
else
{
printf("Failed to open test file\n");
}
sf_close(sndref);
}
else
{
printf("Failed to open reference file\n");
}

return EXIT_SUCCESS;
}

[-- Attachment #3: Type: text/plain, Size: 314 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/

[-- Attachment #4: Type: text/plain, Size: 164 bytes --]