Skip to content
Snippets Groups Projects
Unverified Commit 8e6e049f authored by Jean-Marc Valin's avatar Jean-Marc Valin
Browse files

Refactoring opus_custom_demo

Makes it possible to just encode or just decode using the same format as
opus_demo
parent 7db26934
No related branches found
No related tags found
1 merge request!126Misc fixes, mostly CELT-related
......@@ -39,172 +39,345 @@
#define MAX_PACKET 1275
static void print_usage(char **argv) {
fprintf (stderr, "Usage: %s [-e | -d] <rate> <channels> <frame size> "
" [<bytes per packet>] [-complexity <0-10>] [-loss <packet loss percent>] "
"<input> <output>\n", argv[0]);
fprintf (stderr, " -e encode only (default is encode and decode)\n");
fprintf (stderr, " -d decode only (default is encode and decode)\n");
fprintf (stderr, " <bytes per packet>: required only when encoding\n");
fprintf (stderr, " -complexity <0-10>: optional only when encoding\n");
fprintf (stderr, " -loss <packet loss percent>: encoding (robsutness setting) and decoding (simulating loss)\n");
}
static void int_to_char(opus_uint32 i, unsigned char ch[4])
{
ch[0] = i>>24;
ch[1] = (i>>16)&0xFF;
ch[2] = (i>>8)&0xFF;
ch[3] = i&0xFF;
}
static opus_uint32 char_to_int(unsigned char ch[4])
{
return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16)
| ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3];
}
#define check_encoder_option(decode_only, opt) do {if (decode_only) {fprintf(stderr, "option %s is only for encoding\n", opt); goto failure;}} while(0)
#define check_decoder_option(encode_only, opt) do {if (encode_only) {fprintf(stderr, "option %s is only for decoding\n", opt); goto failure;}} while(0)
int main(int argc, char *argv[])
{
int err;
int ret=1;
int args;
opus_uint32 enc_final_range;
opus_uint32 dec_final_range;
int encode_only=0, decode_only=0;
char *inFile, *outFile;
FILE *fin, *fout;
FILE *fin=NULL, *fout=NULL;
OpusCustomMode *mode=NULL;
OpusCustomEncoder *enc;
OpusCustomDecoder *dec;
OpusCustomEncoder *enc=NULL;
OpusCustomDecoder *dec=NULL;
int len;
opus_int32 frame_size, channels, rate;
int bytes_per_packet;
int bytes_per_packet=0;
unsigned char data[MAX_PACKET];
int complexity;
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
int complexity=-1;
float percent_loss = -1;
int i;
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
double rmsd = 0;
#endif
int count = 0;
opus_int32 skip;
opus_int16 *in, *out;
if (argc != 9 && argc != 8 && argc != 7)
opus_int16 *in=NULL, *out=NULL;
unsigned char *fbytes=NULL;
args = 1;
if (argc < 7)
{
fprintf (stderr, "Usage: test_opus_custom <rate> <channels> <frame size> "
" <bytes per packet> [<complexity> [packet loss rate]] "
"<input> <output>\n");
return 1;
print_usage(argv);
goto failure;
}
if (strcmp(argv[args], "-e")==0)
{
encode_only = 1;
args++;
} else if (strcmp(argv[args], "-d")==0)
{
decode_only = 1;
args++;
}
rate = (opus_int32)atol(argv[args]);
args++;
if (rate != 8000 && rate != 12000
&& rate != 16000 && rate != 24000
&& rate != 48000)
{
fprintf(stderr, "Supported sampling rates are 8000, 12000, "
"16000, 24000 and 48000.\n");
goto failure;
}
channels = atoi(argv[args]);
args++;
if (channels < 1 || channels > 2)
{
fprintf(stderr, "Opus_demo supports only 1 or 2 channels.\n");
goto failure;
}
frame_size = atoi(argv[args]);
args++;
if (!decode_only)
{
bytes_per_packet = (opus_int32)atol(argv[args]);
args++;
if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
{
fprintf (stderr, "bytes per packet must be between 0 and %d\n",
MAX_PACKET);
goto failure;
}
}
rate = (opus_int32)atol(argv[1]);
channels = atoi(argv[2]);
frame_size = atoi(argv[3]);
mode = opus_custom_mode_create(rate, frame_size, NULL);
if (mode == NULL)
{
fprintf(stderr, "failed to create a mode\n");
return 1;
goto failure;
}
bytes_per_packet = atoi(argv[4]);
if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
while( args < argc - 2 ) {
/* process command line options */
if( strcmp( argv[ args ], "-complexity" ) == 0 ) {
check_encoder_option(decode_only, "-complexity");
args++;
complexity=atoi(argv[args]);
args++;
} else if( strcmp( argv[ args ], "-loss" ) == 0 ) {
args++;
percent_loss = atof(argv[args]);
args++;
} else {
printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
print_usage( argv );
goto failure;
}
}
if (!decode_only) {
enc = opus_custom_encoder_create(mode, channels, &err);
if (err != 0)
{
fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err));
goto failure;
}
if (complexity >= 0)
{
opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity));
}
if (percent_loss >= 0) {
opus_custom_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC((int)percent_loss));
}
}
if (!encode_only) {
dec = opus_custom_decoder_create(mode, channels, &err);
if (err != 0)
{
fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err));
goto failure;
}
opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip));
}
if (argc-args != 2)
{
fprintf (stderr, "bytes per packet must be between 0 and %d\n",
MAX_PACKET);
return 1;
print_usage(argv);
goto failure;
}
inFile = argv[argc-2];
fin = fopen(inFile, "rb");
if (!fin)
{
fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
return 1;
goto failure;
}
outFile = argv[argc-1];
fout = fopen(outFile, "wb+");
if (!fout)
{
fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
fclose(fin);
return 1;
}
enc = opus_custom_encoder_create(mode, channels, &err);
if (err != 0)
{
fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err));
fclose(fin);
fclose(fout);
return 1;
}
dec = opus_custom_decoder_create(mode, channels, &err);
if (err != 0)
{
fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err));
fclose(fin);
fclose(fout);
return 1;
goto failure;
}
opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip));
if (argc>7)
{
complexity=atoi(argv[5]);
opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity));
}
in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
fbytes = (unsigned char*)malloc(frame_size*channels*2);
while (!feof(fin))
{
int ret;
err = fread(in, sizeof(short), frame_size*channels, fin);
if (feof(fin))
break;
len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
if (len <= 0)
fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));
/* This is for simulating bit errors */
#if 0
int errors = 0;
int eid = 0;
/* This simulates random bit error */
for (i=0;i<len*8;i++)
int lost = 0;
if (decode_only)
{
unsigned char ch[4];
size_t num_read = fread(ch, 1, 4, fin);
if (num_read!=4)
break;
len = char_to_int(ch);
if (len>MAX_PACKET || len<0)
{
fprintf(stderr, "Invalid payload length: %d\n",len);
break;
}
num_read = fread(ch, 1, 4, fin);
if (num_read!=4)
break;
enc_final_range = char_to_int(ch);
num_read = fread(data, 1, len, fin);
if (num_read!=(size_t)len)
{
fprintf(stderr, "Ran out of input, "
"expecting %d bytes got %d\n",
len,(int)num_read);
break;
}
} else {
err = fread(fbytes, sizeof(short), frame_size*channels, fin);
if (feof(fin))
break;
for(i=0;i<frame_size*channels;i++)
{
opus_int32 s;
s=fbytes[2*i+1]<<8|fbytes[2*i];
s=((s&0xFFFF)^0x8000)-0x8000;
in[i]=s;
}
len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
opus_custom_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range));
if (len <= 0)
fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));
}
if (encode_only)
{
if (rand()%atoi(argv[8])==0)
unsigned char int_field[4];
int_to_char(len, int_field);
if (fwrite(int_field, 1, 4, fout) != 4) {
fprintf(stderr, "Error writing.\n");
goto failure;
}
int_to_char(enc_final_range, int_field);
if (fwrite(int_field, 1, 4, fout) != 4) {
fprintf(stderr, "Error writing.\n");
goto failure;
}
if (fwrite(data, 1, len, fout) != (unsigned)len) {
fprintf(stderr, "Error writing.\n");
goto failure;
}
} else {
/* This is for simulating bit errors */
#if 0
int errors = 0;
int eid = 0;
/* This simulates random bit error */
for (i=0;i<len*8;i++)
{
if (i<64)
if (rand()%atoi(argv[8])==0)
{
errors++;
eid = i;
if (i<64)
{
errors++;
eid = i;
}
data[i/8] ^= 1<<(7-(i%8));
}
data[i/8] ^= 1<<(7-(i%8));
}
}
if (errors == 1)
data[eid/8] ^= 1<<(7-(eid%8));
else if (errors%2 == 1)
data[rand()%8] ^= 1<<rand()%8;
if (errors == 1)
data[eid/8] ^= 1<<(7-(eid%8));
else if (errors%2 == 1)
data[rand()%8] ^= 1<<rand()%8;
#endif
#if 1 /* Set to zero to use the encoder's output instead */
/* This is to simulate packet loss */
if (argc==9 && rand()%1000<atoi(argv[argc-3]))
/*if (errors && (errors%2==0))*/
ret = opus_custom_decode(dec, NULL, len, out, frame_size);
else
ret = opus_custom_decode(dec, data, len, out, frame_size);
if (ret < 0)
fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));
/* This is to simulate packet loss */
lost = percent_loss != 0 && (float)rand()/RAND_MAX<.01*percent_loss;
if (lost)
/*if (errors && (errors%2==0))*/
ret = opus_custom_decode(dec, NULL, len, out, frame_size);
else
ret = opus_custom_decode(dec, data, len, out, frame_size);
opus_custom_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
if (ret < 0)
fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));
#else
for (i=0;i<ret*channels;i++)
out[i] = in[i];
for (i=0;i<ret*channels;i++)
out[i] = in[i];
#endif
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
for (i=0;i<ret*channels;i++)
{
rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
/*out[i] -= in[i];*/
}
if (!encode_only && !decode_only)
{
for (i=0;i<ret*channels;i++)
{
rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
/*out[i] -= in[i];*/
}
}
#endif
for(i=0;i<(ret-skip)*channels;i++)
{
short s;
s=out[i+(skip*channels)];
fbytes[2*i]=s&0xFF;
fbytes[2*i+1]=(s>>8)&0xFF;
}
fwrite(fbytes, 2, (ret-skip)*channels, fout);
}
/* compare final range encoder rng values of encoder and decoder */
if( enc_final_range!=0 && !encode_only
&& !lost
&& dec_final_range != enc_final_range ) {
fprintf (stderr, "Error: Range coder state mismatch "
"between encoder and decoder "
"in frame %ld: 0x%8lx vs 0x%8lx\n",
(long)count,
(unsigned long)enc_final_range,
(unsigned long)dec_final_range);
goto failure;
}
count++;
fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
skip = 0;
}
PRINT_MIPS(stderr);
opus_custom_encoder_destroy(enc);
opus_custom_decoder_destroy(dec);
fclose(fin);
fclose(fout);
opus_custom_mode_destroy(mode);
free(in);
free(out);
ret = EXIT_SUCCESS;
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
if (rmsd > 0)
if (!encode_only && !decode_only)
{
rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
fprintf (stderr, "Error: encoder doesn't match decoder\n");
fprintf (stderr, "RMS mismatch is %f\n", rmsd);
return 1;
} else {
fprintf (stderr, "Encoder matches decoder!!\n");
if (rmsd > 0)
{
rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
fprintf (stderr, "Error: encoder doesn't match decoder\n");
fprintf (stderr, "RMS mismatch is %f\n", rmsd);
ret = 1;
} else {
fprintf (stderr, "Encoder matches decoder!!\n");
}
}
#endif
return 0;
failure:
/* Cleanup after ourselves. */
if (enc) opus_custom_encoder_destroy(enc);
if (dec) opus_custom_decoder_destroy(dec);
if (fin) fclose(fin);
if (fout) fclose(fout);
if (mode) opus_custom_mode_destroy(mode);
if (in) free(in);
if (out) free(out);
if (fbytes) free(fbytes);
return ret;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment