early-access version 1255

This commit is contained in:
pineappleEA
2020-12-28 15:15:37 +00:00
parent 84b39492d1
commit 78b48028e1
6254 changed files with 1868140 additions and 0 deletions

126
externals/opus/opus/tests/opus_decode_fuzzer.c vendored Executable file
View File

@@ -0,0 +1,126 @@
/* Copyright (c) 2017 Google Inc. */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "opus.h"
#include "opus_types.h"
#define MAX_FRAME_SAMP 5760
#define MAX_PACKET 1500
/* 4 bytes: packet length, 4 bytes: encoder final range */
#define SETUP_BYTE_COUNT 8
typedef struct {
int fs;
int channels;
} TocInfo;
static void ParseToc(const uint8_t *toc, TocInfo *const info) {
const int samp_freqs[5] = {8000, 12000, 16000, 24000, 48000};
const int bandwidth = opus_packet_get_bandwidth(toc);
info->fs = samp_freqs[bandwidth - OPUS_BANDWIDTH_NARROWBAND];
info->channels = opus_packet_get_nb_channels(toc);
}
/* Treats the input data as concatenated packets encoded by opus_demo,
* structured as
* bytes 0..3: packet length
* bytes 4..7: encoder final range
* bytes 8+ : Opus packet, including ToC
*/
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
OpusDecoder *dec;
opus_int16 *pcm;
uint8_t *packet;
TocInfo toc;
int i, err;
/* Not enough data to setup the decoder (+1 for the ToC) */
if (size < SETUP_BYTE_COUNT + 1) {
return 0;
}
/* Create decoder based on info from the first ToC available */
ParseToc(&data[SETUP_BYTE_COUNT], &toc);
dec = opus_decoder_create(toc.fs, toc.channels, &err);
if (err != OPUS_OK | dec == NULL) {
return 0;
}
pcm = (opus_int16*) malloc(sizeof(*pcm) * MAX_FRAME_SAMP * toc.channels);
packet = (uint8_t*) calloc(MAX_PACKET, sizeof(*packet));
i = 0;
while (1) {
int len, fec;
if (i + SETUP_BYTE_COUNT >= size) {
break;
}
len = (opus_uint32) data[i ] << 24 |
(opus_uint32) data[i + 1] << 16 |
(opus_uint32) data[i + 2] << 8 |
(opus_uint32) data[i + 3];
if (len > MAX_PACKET || len < 0) {
break;
}
/* Bytes 4..7 represent encoder final range, but are unused here.
* Instead, byte 4 is repurposed to determine if FEC is used. */
fec = data[i + 4] & 1;
/* Lost packet */
if (len == 0) {
int frame_size;
opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&frame_size));
(void) opus_decode(dec, NULL, size, pcm, frame_size, fec);
} else {
if (i + SETUP_BYTE_COUNT + len > size) {
break;
}
memcpy(pcm, &data[i + SETUP_BYTE_COUNT], len);
(void) opus_decode(dec, data, size, pcm, MAX_FRAME_SAMP, fec);
}
i += SETUP_BYTE_COUNT + len;
}
opus_decoder_destroy(dec);
free(pcm);
free(packet);
return 0;
}

View File

@@ -0,0 +1,2 @@
[libfuzzer]
max_len = 1000000

File diff suppressed because it is too large Load Diff

143
externals/opus/opus/tests/run_vectors.sh vendored Executable file
View File

@@ -0,0 +1,143 @@
#!/bin/sh
# Copyright (c) 2011-2012 Jean-Marc Valin
#
# This file is extracted from RFC6716. Please see that RFC for additional
# information.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Internet Society, IETF or IETF Trust, nor the
# names of specific contributors, may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
rm -f logs_mono.txt logs_mono2.txt
rm -f logs_stereo.txt logs_stereo2.txt
if [ "$#" -ne "3" ]; then
echo "usage: run_vectors.sh <exec path> <vector path> <rate>"
exit 1
fi
CMD_PATH=$1
VECTOR_PATH=$2
RATE=$3
: ${OPUS_DEMO:=$CMD_PATH/opus_demo}
: ${OPUS_COMPARE:=$CMD_PATH/opus_compare}
if [ -d "$VECTOR_PATH" ]; then
echo "Test vectors found in $VECTOR_PATH"
else
echo "No test vectors found"
#Don't make the test fail here because the test vectors
#will be distributed separately
exit 0
fi
if [ ! -x "$OPUS_COMPARE" ]; then
echo "ERROR: Compare program not found: $OPUS_COMPARE"
exit 1
fi
if [ -x "$OPUS_DEMO" ]; then
echo "Decoding with $OPUS_DEMO"
else
echo "ERROR: Decoder not found: $OPUS_DEMO"
exit 1
fi
echo "=============="
echo "Testing mono"
echo "=============="
echo
for file in 01 02 03 04 05 06 07 08 09 10 11 12
do
if [ -e "$VECTOR_PATH/testvector$file.bit" ]; then
echo "Testing testvector$file"
else
echo "Bitstream file not found: testvector$file.bit"
fi
if "$OPUS_DEMO" -d "$RATE" 1 "$VECTOR_PATH/testvector$file.bit" tmp.out >> logs_mono.txt 2>&1; then
echo "successfully decoded"
else
echo "ERROR: decoding failed"
exit 1
fi
"$OPUS_COMPARE" -r "$RATE" "$VECTOR_PATH/testvector${file}.dec" tmp.out >> logs_mono.txt 2>&1
float_ret=$?
"$OPUS_COMPARE" -r "$RATE" "$VECTOR_PATH/testvector${file}m.dec" tmp.out >> logs_mono2.txt 2>&1
float_ret2=$?
if [ "$float_ret" -eq "0" ] || [ "$float_ret2" -eq "0" ]; then
echo "output matches reference"
else
echo "ERROR: output does not match reference"
exit 1
fi
echo
done
echo "=============="
echo Testing stereo
echo "=============="
echo
for file in 01 02 03 04 05 06 07 08 09 10 11 12
do
if [ -e "$VECTOR_PATH/testvector$file.bit" ]; then
echo "Testing testvector$file"
else
echo "Bitstream file not found: testvector$file"
fi
if "$OPUS_DEMO" -d "$RATE" 2 "$VECTOR_PATH/testvector$file.bit" tmp.out >> logs_stereo.txt 2>&1; then
echo "successfully decoded"
else
echo "ERROR: decoding failed"
exit 1
fi
"$OPUS_COMPARE" -s -r "$RATE" "$VECTOR_PATH/testvector${file}.dec" tmp.out >> logs_stereo.txt 2>&1
float_ret=$?
"$OPUS_COMPARE" -s -r "$RATE" "$VECTOR_PATH/testvector${file}m.dec" tmp.out >> logs_stereo2.txt 2>&1
float_ret2=$?
if [ "$float_ret" -eq "0" ] || [ "$float_ret2" -eq "0" ]; then
echo "output matches reference"
else
echo "ERROR: output does not match reference"
exit 1
fi
echo
done
echo "All tests have passed successfully"
mono1=`grep quality logs_mono.txt | awk '{sum+=$4}END{if (NR == 12) sum /= 12; else sum = 0; print sum}'`
mono2=`grep quality logs_mono2.txt | awk '{sum+=$4}END{if (NR == 12) sum /= 12; else sum = 0; print sum}'`
echo $mono1 $mono2 | awk '{if ($2 > $1) $1 = $2; print "Average mono quality is", $1, "%"}'
stereo1=`grep quality logs_stereo.txt | awk '{sum+=$4}END{if (NR == 12) sum /= 12; else sum = 0; print sum}'`
stereo2=`grep quality logs_stereo2.txt | awk '{sum+=$4}END{if (NR == 12) sum /= 12; else sum = 0; print sum}'`
echo $stereo1 $stereo2 | awk '{if ($2 > $1) $1 = $2; print "Average stereo quality is", $1, "%"}'

1904
externals/opus/opus/tests/test_opus_api.c vendored Executable file

File diff suppressed because it is too large Load Diff

82
externals/opus/opus/tests/test_opus_common.h vendored Executable file
View File

@@ -0,0 +1,82 @@
/* Copyright (c) 2011 Xiph.Org Foundation
Written by Gregory Maxwell */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
static OPUS_INLINE void deb2_impl(unsigned char *_t,unsigned char **_p,int _k,int _x,int _y)
{
int i;
if(_x>2){
if(_y<3)for(i=0;i<_y;i++)*(--*_p)=_t[i+1];
}else{
_t[_x]=_t[_x-_y];
deb2_impl(_t,_p,_k,_x+1,_y);
for(i=_t[_x-_y]+1;i<_k;i++){
_t[_x]=i;
deb2_impl(_t,_p,_k,_x+1,_x);
}
}
}
/*Generates a De Bruijn sequence (k,2) with length k^2*/
static OPUS_INLINE void debruijn2(int _k, unsigned char *_res)
{
unsigned char *p;
unsigned char *t;
t=malloc(sizeof(unsigned char)*_k*2);
memset(t,0,sizeof(unsigned char)*_k*2);
p=&_res[_k*_k];
deb2_impl(t,&p,_k,1,1);
free(t);
}
/*MWC RNG of George Marsaglia*/
static opus_uint32 Rz, Rw;
static OPUS_INLINE opus_uint32 fast_rand(void)
{
Rz=36969*(Rz&65535)+(Rz>>16);
Rw=18000*(Rw&65535)+(Rw>>16);
return (Rz<<16)+Rw;
}
static opus_uint32 iseed;
#ifdef __GNUC__
__attribute__((noreturn))
#elif defined(_MSC_VER)
__declspec(noreturn)
#endif
static OPUS_INLINE void _test_failed(const char *file, int line)
{
fprintf(stderr,"\n ***************************************************\n");
fprintf(stderr," *** A fatal error was detected. ***\n");
fprintf(stderr," ***************************************************\n");
fprintf(stderr,"Please report this failure and include\n");
fprintf(stderr,"'make check SEED=%u fails %s at line %d for %s'\n",iseed,file,line,opus_get_version_string());
fprintf(stderr,"and any relevant details about your system.\n\n");
abort();
}
#define test_failed() _test_failed(__FILE__, __LINE__);
void regression_test(void);

463
externals/opus/opus/tests/test_opus_decode.c vendored Executable file
View File

@@ -0,0 +1,463 @@
/* Copyright (c) 2011-2013 Xiph.Org Foundation
Written by Gregory Maxwell */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdint.h>
#include <math.h>
#include <string.h>
#include <time.h>
#if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__)
#include <unistd.h>
#else
#include <process.h>
#define getpid _getpid
#endif
#include "opus.h"
#include "test_opus_common.h"
#define MAX_PACKET (1500)
#define MAX_FRAME_SAMP (5760)
int test_decoder_code0(int no_fuzz)
{
static const opus_int32 fsv[5]={48000,24000,16000,12000,8000};
int err,skip,plen;
int out_samples,fec;
int t;
opus_int32 i;
OpusDecoder *dec[5*2];
opus_int32 decsize;
OpusDecoder *decbak;
opus_uint32 dec_final_range1,dec_final_range2,dec_final_acc;
unsigned char *packet;
unsigned char modes[4096];
short *outbuf_int;
short *outbuf;
dec_final_range1=dec_final_range2=2;
packet=malloc(sizeof(unsigned char)*MAX_PACKET);
if(packet==NULL)test_failed();
outbuf_int=malloc(sizeof(short)*(MAX_FRAME_SAMP+16)*2);
for(i=0;i<(MAX_FRAME_SAMP+16)*2;i++)outbuf_int[i]=32749;
outbuf=&outbuf_int[8*2];
fprintf(stdout," Starting %d decoders...\n",5*2);
for(t=0;t<5*2;t++)
{
int fs=fsv[t>>1];
int c=(t&1)+1;
err=OPUS_INTERNAL_ERROR;
dec[t] = opus_decoder_create(fs, c, &err);
if(err!=OPUS_OK || dec[t]==NULL)test_failed();
fprintf(stdout," opus_decoder_create(%5d,%d) OK. Copy ",fs,c);
{
OpusDecoder *dec2;
/*The opus state structures contain no pointers and can be freely copied*/
dec2=(OpusDecoder *)malloc(opus_decoder_get_size(c));
if(dec2==NULL)test_failed();
memcpy(dec2,dec[t],opus_decoder_get_size(c));
memset(dec[t],255,opus_decoder_get_size(c));
opus_decoder_destroy(dec[t]);
printf("OK.\n");
dec[t]=dec2;
}
}
decsize=opus_decoder_get_size(1);
decbak=(OpusDecoder *)malloc(decsize);
if(decbak==NULL)test_failed();
for(t=0;t<5*2;t++)
{
int factor=48000/fsv[t>>1];
for(fec=0;fec<2;fec++)
{
opus_int32 dur;
/*Test PLC on a fresh decoder*/
out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor, fec);
if(out_samples!=120/factor)test_failed();
if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
if(dur!=120/factor)test_failed();
/*Test on a size which isn't a multiple of 2.5ms*/
out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor+2, fec);
if(out_samples!=OPUS_BAD_ARG)test_failed();
/*Test null pointer input*/
out_samples = opus_decode(dec[t], 0, -1, outbuf, 120/factor, fec);
if(out_samples!=120/factor)test_failed();
out_samples = opus_decode(dec[t], 0, 1, outbuf, 120/factor, fec);
if(out_samples!=120/factor)test_failed();
out_samples = opus_decode(dec[t], 0, 10, outbuf, 120/factor, fec);
if(out_samples!=120/factor)test_failed();
out_samples = opus_decode(dec[t], 0, fast_rand(), outbuf, 120/factor, fec);
if(out_samples!=120/factor)test_failed();
if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
if(dur!=120/factor)test_failed();
/*Zero lengths*/
out_samples = opus_decode(dec[t], packet, 0, outbuf, 120/factor, fec);
if(out_samples!=120/factor)test_failed();
/*Zero buffer*/
outbuf[0]=32749;
out_samples = opus_decode(dec[t], packet, 0, outbuf, 0, fec);
if(out_samples>0)test_failed();
#if !defined(OPUS_BUILD) && (OPUS_GNUC_PREREQ(4, 6) || (defined(__clang_major__) && __clang_major__ >= 3))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull"
#endif
out_samples = opus_decode(dec[t], packet, 0, 0, 0, fec);
#if !defined(OPUS_BUILD) && (OPUS_GNUC_PREREQ(4, 6) || (defined(__clang_major__) && __clang_major__ >= 3))
#pragma GCC diagnostic pop
#endif
if(out_samples>0)test_failed();
if(outbuf[0]!=32749)test_failed();
/*Invalid lengths*/
out_samples = opus_decode(dec[t], packet, -1, outbuf, MAX_FRAME_SAMP, fec);
if(out_samples>=0)test_failed();
out_samples = opus_decode(dec[t], packet, INT_MIN, outbuf, MAX_FRAME_SAMP, fec);
if(out_samples>=0)test_failed();
out_samples = opus_decode(dec[t], packet, -1, outbuf, -1, fec);
if(out_samples>=0)test_failed();
/*Crazy FEC values*/
out_samples = opus_decode(dec[t], packet, 1, outbuf, MAX_FRAME_SAMP, fec?-1:2);
if(out_samples>=0)test_failed();
/*Reset the decoder*/
if(opus_decoder_ctl(dec[t], OPUS_RESET_STATE)!=OPUS_OK)test_failed();
}
}
fprintf(stdout," dec[all] initial frame PLC OK.\n");
/*Count code 0 tests*/
for(i=0;i<64;i++)
{
opus_int32 dur;
int j,expected[5*2];
packet[0]=i<<2;
packet[1]=255;
packet[2]=255;
err=opus_packet_get_nb_channels(packet);
if(err!=(i&1)+1)test_failed();
for(t=0;t<5*2;t++){
expected[t]=opus_decoder_get_nb_samples(dec[t],packet,1);
if(expected[t]>2880)test_failed();
}
for(j=0;j<256;j++)
{
packet[1]=j;
for(t=0;t<5*2;t++)
{
out_samples = opus_decode(dec[t], packet, 3, outbuf, MAX_FRAME_SAMP, 0);
if(out_samples!=expected[t])test_failed();
if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
if(dur!=out_samples)test_failed();
opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1));
if(t==0)dec_final_range2=dec_final_range1;
else if(dec_final_range1!=dec_final_range2)test_failed();
}
}
for(t=0;t<5*2;t++){
int factor=48000/fsv[t>>1];
/* The PLC is run for 6 frames in order to get better PLC coverage. */
for(j=0;j<6;j++)
{
out_samples = opus_decode(dec[t], 0, 0, outbuf, expected[t], 0);
if(out_samples!=expected[t])test_failed();
if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
if(dur!=out_samples)test_failed();
}
/* Run the PLC once at 2.5ms, as a simulation of someone trying to
do small drift corrections. */
if(expected[t]!=120/factor)
{
out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor, 0);
if(out_samples!=120/factor)test_failed();
if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
if(dur!=out_samples)test_failed();
}
out_samples = opus_decode(dec[t], packet, 2, outbuf, expected[t]-1, 0);
if(out_samples>0)test_failed();
}
}
fprintf(stdout," dec[all] all 2-byte prefix for length 3 and PLC, all modes (64) OK.\n");
if(no_fuzz)
{
fprintf(stdout," Skipping many tests which fuzz the decoder as requested.\n");
free(decbak);
for(t=0;t<5*2;t++)opus_decoder_destroy(dec[t]);
printf(" Decoders stopped.\n");
err=0;
for(i=0;i<8*2;i++)err|=outbuf_int[i]!=32749;
for(i=MAX_FRAME_SAMP*2;i<(MAX_FRAME_SAMP+8)*2;i++)err|=outbuf[i]!=32749;
if(err)test_failed();
free(outbuf_int);
free(packet);
return 0;
}
{
/*We only test a subset of the modes here simply because the longer
durations end up taking a long time.*/
static const int cmodes[4]={16,20,24,28};
static const opus_uint32 cres[4]={116290185,2172123586u,2172123586u,2172123586u};
static const opus_uint32 lres[3]={3285687739u,1481572662,694350475};
static const int lmodes[3]={0,4,8};
int mode=fast_rand()%4;
packet[0]=cmodes[mode]<<3;
dec_final_acc=0;
t=fast_rand()%10;
for(i=0;i<65536;i++)
{
int factor=48000/fsv[t>>1];
packet[1]=i>>8;
packet[2]=i&255;
packet[3]=255;
out_samples = opus_decode(dec[t], packet, 4, outbuf, MAX_FRAME_SAMP, 0);
if(out_samples!=120/factor)test_failed();
opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1));
dec_final_acc+=dec_final_range1;
}
if(dec_final_acc!=cres[mode])test_failed();
fprintf(stdout," dec[%3d] all 3-byte prefix for length 4, mode %2d OK.\n",t,cmodes[mode]);
mode=fast_rand()%3;
packet[0]=lmodes[mode]<<3;
dec_final_acc=0;
t=fast_rand()%10;
for(i=0;i<65536;i++)
{
int factor=48000/fsv[t>>1];
packet[1]=i>>8;
packet[2]=i&255;
packet[3]=255;
out_samples = opus_decode(dec[t], packet, 4, outbuf, MAX_FRAME_SAMP, 0);
if(out_samples!=480/factor)test_failed();
opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1));
dec_final_acc+=dec_final_range1;
}
if(dec_final_acc!=lres[mode])test_failed();
fprintf(stdout," dec[%3d] all 3-byte prefix for length 4, mode %2d OK.\n",t,lmodes[mode]);
}
skip=fast_rand()%7;
for(i=0;i<64;i++)
{
int j,expected[5*2];
packet[0]=i<<2;
for(t=0;t<5*2;t++)expected[t]=opus_decoder_get_nb_samples(dec[t],packet,1);
for(j=2+skip;j<1275;j+=4)
{
int jj;
for(jj=0;jj<j;jj++)packet[jj+1]=fast_rand()&255;
for(t=0;t<5*2;t++)
{
out_samples = opus_decode(dec[t], packet, j+1, outbuf, MAX_FRAME_SAMP, 0);
if(out_samples!=expected[t])test_failed();
opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1));
if(t==0)dec_final_range2=dec_final_range1;
else if(dec_final_range1!=dec_final_range2)test_failed();
}
}
}
fprintf(stdout," dec[all] random packets, all modes (64), every 8th size from from %d bytes to maximum OK.\n",2+skip);
debruijn2(64,modes);
plen=(fast_rand()%18+3)*8+skip+3;
for(i=0;i<4096;i++)
{
int j,expected[5*2];
packet[0]=modes[i]<<2;
for(t=0;t<5*2;t++)expected[t]=opus_decoder_get_nb_samples(dec[t],packet,plen);
for(j=0;j<plen;j++)packet[j+1]=(fast_rand()|fast_rand())&255;
memcpy(decbak,dec[0],decsize);
if(opus_decode(decbak, packet, plen+1, outbuf, expected[0], 1)!=expected[0])test_failed();
memcpy(decbak,dec[0],decsize);
if(opus_decode(decbak, 0, 0, outbuf, MAX_FRAME_SAMP, 1)<20)test_failed();
memcpy(decbak,dec[0],decsize);
if(opus_decode(decbak, 0, 0, outbuf, MAX_FRAME_SAMP, 0)<20)test_failed();
for(t=0;t<5*2;t++)
{
opus_int32 dur;
out_samples = opus_decode(dec[t], packet, plen+1, outbuf, MAX_FRAME_SAMP, 0);
if(out_samples!=expected[t])test_failed();
if(t==0)dec_final_range2=dec_final_range1;
else if(dec_final_range1!=dec_final_range2)test_failed();
if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
if(dur!=out_samples)test_failed();
}
}
fprintf(stdout," dec[all] random packets, all mode pairs (4096), %d bytes/frame OK.\n",plen+1);
plen=(fast_rand()%18+3)*8+skip+3;
t=rand()&3;
for(i=0;i<4096;i++)
{
int count,j,expected;
packet[0]=modes[i]<<2;
expected=opus_decoder_get_nb_samples(dec[t],packet,plen);
for(count=0;count<10;count++)
{
for(j=0;j<plen;j++)packet[j+1]=(fast_rand()|fast_rand())&255;
out_samples = opus_decode(dec[t], packet, plen+1, outbuf, MAX_FRAME_SAMP, 0);
if(out_samples!=expected)test_failed();
}
}
fprintf(stdout," dec[%3d] random packets, all mode pairs (4096)*10, %d bytes/frame OK.\n",t,plen+1);
{
int tmodes[1]={25<<2};
opus_uint32 tseeds[1]={140441};
int tlen[1]={157};
opus_int32 tret[1]={480};
t=fast_rand()&1;
for(i=0;i<1;i++)
{
int j;
packet[0]=tmodes[i];
Rw=Rz=tseeds[i];
for(j=1;j<tlen[i];j++)packet[j]=fast_rand()&255;
out_samples=opus_decode(dec[t], packet, tlen[i], outbuf, MAX_FRAME_SAMP, 0);
if(out_samples!=tret[i])test_failed();
}
fprintf(stdout," dec[%3d] pre-selected random packets OK.\n",t);
}
free(decbak);
for(t=0;t<5*2;t++)opus_decoder_destroy(dec[t]);
printf(" Decoders stopped.\n");
err=0;
for(i=0;i<8*2;i++)err|=outbuf_int[i]!=32749;
for(i=MAX_FRAME_SAMP*2;i<(MAX_FRAME_SAMP+8)*2;i++)err|=outbuf[i]!=32749;
if(err)test_failed();
free(outbuf_int);
free(packet);
return 0;
}
#ifndef DISABLE_FLOAT_API
void test_soft_clip(void)
{
int i,j;
float x[1024];
float s[8] = {0, 0, 0, 0, 0, 0, 0, 0};
fprintf(stdout," Testing opus_pcm_soft_clip... ");
for(i=0;i<1024;i++)
{
for (j=0;j<1024;j++)
{
x[j]=(j&255)*(1/32.f)-4.f;
}
opus_pcm_soft_clip(&x[i],1024-i,1,s);
for (j=i;j<1024;j++)
{
if(x[j]>1.f)test_failed();
if(x[j]<-1.f)test_failed();
}
}
for(i=1;i<9;i++)
{
for (j=0;j<1024;j++)
{
x[j]=(j&255)*(1/32.f)-4.f;
}
opus_pcm_soft_clip(x,1024/i,i,s);
for (j=0;j<(1024/i)*i;j++)
{
if(x[j]>1.f)test_failed();
if(x[j]<-1.f)test_failed();
}
}
opus_pcm_soft_clip(x,0,1,s);
opus_pcm_soft_clip(x,1,0,s);
opus_pcm_soft_clip(x,1,1,0);
opus_pcm_soft_clip(x,1,-1,s);
opus_pcm_soft_clip(x,-1,1,s);
opus_pcm_soft_clip(0,1,1,s);
printf("OK.\n");
}
#endif
int main(int _argc, char **_argv)
{
const char * oversion;
const char * env_seed;
int env_used;
if(_argc>2)
{
fprintf(stderr,"Usage: %s [<seed>]\n",_argv[0]);
return 1;
}
env_used=0;
env_seed=getenv("SEED");
if(_argc>1)iseed=atoi(_argv[1]);
else if(env_seed)
{
iseed=atoi(env_seed);
env_used=1;
}
else iseed=(opus_uint32)time(NULL)^(((opus_uint32)getpid()&65535)<<16);
Rw=Rz=iseed;
oversion=opus_get_version_string();
if(!oversion)test_failed();
fprintf(stderr,"Testing %s decoder. Random seed: %u (%.4X)\n", oversion, iseed, fast_rand() % 65535);
if(env_used)fprintf(stderr," Random seed set from the environment (SEED=%s).\n", env_seed);
/*Setting TEST_OPUS_NOFUZZ tells the tool not to send garbage data
into the decoders. This is helpful because garbage data
may cause the decoders to clip, which angers CLANG IOC.*/
test_decoder_code0(getenv("TEST_OPUS_NOFUZZ")!=NULL);
#ifndef DISABLE_FLOAT_API
test_soft_clip();
#endif
return 0;
}

703
externals/opus/opus/tests/test_opus_encode.c vendored Executable file
View File

@@ -0,0 +1,703 @@
/* Copyright (c) 2011-2013 Xiph.Org Foundation
Written by Gregory Maxwell */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdint.h>
#include <math.h>
#include <string.h>
#include <time.h>
#if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__)
#include <unistd.h>
#else
#include <process.h>
#define getpid _getpid
#endif
#include "opus_multistream.h"
#include "opus.h"
#include "../src/opus_private.h"
#include "test_opus_common.h"
#define MAX_PACKET (1500)
#define SAMPLES (48000*30)
#define SSAMPLES (SAMPLES/3)
#define MAX_FRAME_SAMP (5760)
#define PI (3.141592653589793238462643f)
#define RAND_SAMPLE(a) (a[fast_rand() % sizeof(a)/sizeof(a[0])])
void generate_music(short *buf, opus_int32 len)
{
opus_int32 a1,b1,a2,b2;
opus_int32 c1,c2,d1,d2;
opus_int32 i,j;
a1=b1=a2=b2=0;
c1=c2=d1=d2=0;
j=0;
/*60ms silence*/
for(i=0;i<2880;i++)buf[i*2]=buf[i*2+1]=0;
for(i=2880;i<len;i++)
{
opus_uint32 r;
opus_int32 v1,v2;
v1=v2=(((j*((j>>12)^((j>>10|j>>12)&26&j>>7)))&128)+128)<<15;
r=fast_rand();v1+=r&65535;v1-=r>>16;
r=fast_rand();v2+=r&65535;v2-=r>>16;
b1=v1-a1+((b1*61+32)>>6);a1=v1;
b2=v2-a2+((b2*61+32)>>6);a2=v2;
c1=(30*(c1+b1+d1)+32)>>6;d1=b1;
c2=(30*(c2+b2+d2)+32)>>6;d2=b2;
v1=(c1+128)>>8;
v2=(c2+128)>>8;
buf[i*2]=v1>32767?32767:(v1<-32768?-32768:v1);
buf[i*2+1]=v2>32767?32767:(v2<-32768?-32768:v2);
if(i%6==0)j++;
}
}
#if 0
static int save_ctr = 0;
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_INLINE void save_packet(unsigned char* p, int len, opus_uint32 rng)
{
FILE *fout;
unsigned char int_field[4];
char name[256];
snprintf(name,255,"test_opus_encode.%llu.%d.bit",(unsigned long long)iseed,save_ctr);
fprintf(stdout,"writing %d byte packet to %s\n",len,name);
fout=fopen(name, "wb+");
if(fout==NULL)test_failed();
int_to_char(len, int_field);
fwrite(int_field, 1, 4, fout);
int_to_char(rng, int_field);
fwrite(int_field, 1, 4, fout);
fwrite(p, 1, len, fout);
fclose(fout);
save_ctr++;
}
#endif
int get_frame_size_enum(int frame_size, int sampling_rate)
{
int frame_size_enum;
if(frame_size==sampling_rate/400)
frame_size_enum = OPUS_FRAMESIZE_2_5_MS;
else if(frame_size==sampling_rate/200)
frame_size_enum = OPUS_FRAMESIZE_5_MS;
else if(frame_size==sampling_rate/100)
frame_size_enum = OPUS_FRAMESIZE_10_MS;
else if(frame_size==sampling_rate/50)
frame_size_enum = OPUS_FRAMESIZE_20_MS;
else if(frame_size==sampling_rate/25)
frame_size_enum = OPUS_FRAMESIZE_40_MS;
else if(frame_size==3*sampling_rate/50)
frame_size_enum = OPUS_FRAMESIZE_60_MS;
else if(frame_size==4*sampling_rate/50)
frame_size_enum = OPUS_FRAMESIZE_80_MS;
else if(frame_size==5*sampling_rate/50)
frame_size_enum = OPUS_FRAMESIZE_100_MS;
else if(frame_size==6*sampling_rate/50)
frame_size_enum = OPUS_FRAMESIZE_120_MS;
else
test_failed();
return frame_size_enum;
}
int test_encode(OpusEncoder *enc, int channels, int frame_size, OpusDecoder *dec)
{
int samp_count = 0;
opus_int16 *inbuf;
unsigned char packet[MAX_PACKET+257];
int len;
opus_int16 *outbuf;
int out_samples;
int ret = 0;
/* Generate input data */
inbuf = (opus_int16*)malloc(sizeof(*inbuf)*SSAMPLES);
generate_music(inbuf, SSAMPLES/2);
/* Allocate memory for output data */
outbuf = (opus_int16*)malloc(sizeof(*outbuf)*MAX_FRAME_SAMP*3);
/* Encode data, then decode for sanity check */
do {
len = opus_encode(enc, &inbuf[samp_count*channels], frame_size, packet, MAX_PACKET);
if(len<0 || len>MAX_PACKET) {
fprintf(stderr,"opus_encode() returned %d\n",len);
ret = -1;
break;
}
out_samples = opus_decode(dec, packet, len, outbuf, MAX_FRAME_SAMP, 0);
if(out_samples!=frame_size) {
fprintf(stderr,"opus_decode() returned %d\n",out_samples);
ret = -1;
break;
}
samp_count += frame_size;
} while (samp_count < ((SSAMPLES/2)-MAX_FRAME_SAMP));
/* Clean up */
free(inbuf);
free(outbuf);
return ret;
}
void fuzz_encoder_settings(const int num_encoders, const int num_setting_changes)
{
OpusEncoder *enc;
OpusDecoder *dec;
int i,j,err;
/* Parameters to fuzz. Some values are duplicated to increase their probability of being tested. */
int sampling_rates[5] = {8000, 12000, 16000, 24000, 48000};
int channels[2] = {1, 2};
int applications[3] = {OPUS_APPLICATION_AUDIO, OPUS_APPLICATION_VOIP, OPUS_APPLICATION_RESTRICTED_LOWDELAY};
int bitrates[11] = {6000, 12000, 16000, 24000, 32000, 48000, 64000, 96000, 510000, OPUS_AUTO, OPUS_BITRATE_MAX};
int force_channels[4] = {OPUS_AUTO, OPUS_AUTO, 1, 2};
int use_vbr[3] = {0, 1, 1};
int vbr_constraints[3] = {0, 1, 1};
int complexities[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int max_bandwidths[6] = {OPUS_BANDWIDTH_NARROWBAND, OPUS_BANDWIDTH_MEDIUMBAND,
OPUS_BANDWIDTH_WIDEBAND, OPUS_BANDWIDTH_SUPERWIDEBAND,
OPUS_BANDWIDTH_FULLBAND, OPUS_BANDWIDTH_FULLBAND};
int signals[4] = {OPUS_AUTO, OPUS_AUTO, OPUS_SIGNAL_VOICE, OPUS_SIGNAL_MUSIC};
int inband_fecs[3] = {0, 0, 1};
int packet_loss_perc[4] = {0, 1, 2, 5};
int lsb_depths[2] = {8, 24};
int prediction_disabled[3] = {0, 0, 1};
int use_dtx[2] = {0, 1};
int frame_sizes_ms_x2[9] = {5, 10, 20, 40, 80, 120, 160, 200, 240}; /* x2 to avoid 2.5 ms */
for (i=0; i<num_encoders; i++) {
int sampling_rate = RAND_SAMPLE(sampling_rates);
int num_channels = RAND_SAMPLE(channels);
int application = RAND_SAMPLE(applications);
dec = opus_decoder_create(sampling_rate, num_channels, &err);
if(err!=OPUS_OK || dec==NULL)test_failed();
enc = opus_encoder_create(sampling_rate, num_channels, application, &err);
if(err!=OPUS_OK || enc==NULL)test_failed();
for (j=0; j<num_setting_changes; j++) {
int bitrate = RAND_SAMPLE(bitrates);
int force_channel = RAND_SAMPLE(force_channels);
int vbr = RAND_SAMPLE(use_vbr);
int vbr_constraint = RAND_SAMPLE(vbr_constraints);
int complexity = RAND_SAMPLE(complexities);
int max_bw = RAND_SAMPLE(max_bandwidths);
int sig = RAND_SAMPLE(signals);
int inband_fec = RAND_SAMPLE(inband_fecs);
int pkt_loss = RAND_SAMPLE(packet_loss_perc);
int lsb_depth = RAND_SAMPLE(lsb_depths);
int pred_disabled = RAND_SAMPLE(prediction_disabled);
int dtx = RAND_SAMPLE(use_dtx);
int frame_size_ms_x2 = RAND_SAMPLE(frame_sizes_ms_x2);
int frame_size = frame_size_ms_x2*sampling_rate/2000;
int frame_size_enum = get_frame_size_enum(frame_size, sampling_rate);
force_channel = IMIN(force_channel, num_channels);
if(opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(force_channel)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_VBR(vbr)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(vbr_constraint)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_MAX_BANDWIDTH(max_bw)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_SIGNAL(sig)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(inband_fec)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(pkt_loss)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(lsb_depth)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_PREDICTION_DISABLED(pred_disabled)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_DTX(dtx)) != OPUS_OK) test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(frame_size_enum)) != OPUS_OK) test_failed();
if(test_encode(enc, num_channels, frame_size, dec)) {
fprintf(stderr,
"fuzz_encoder_settings: %d kHz, %d ch, application: %d, "
"%d bps, force ch: %d, vbr: %d, vbr constraint: %d, complexity: %d, "
"max bw: %d, signal: %d, inband fec: %d, pkt loss: %d%%, lsb depth: %d, "
"pred disabled: %d, dtx: %d, (%d/2) ms\n",
sampling_rate/1000, num_channels, application, bitrate,
force_channel, vbr, vbr_constraint, complexity, max_bw, sig, inband_fec,
pkt_loss, lsb_depth, pred_disabled, dtx, frame_size_ms_x2);
test_failed();
}
}
opus_encoder_destroy(enc);
opus_decoder_destroy(dec);
}
}
int run_test1(int no_fuzz)
{
static const int fsizes[6]={960*3,960*2,120,240,480,960};
static const char *mstrings[3] = {" LP","Hybrid"," MDCT"};
unsigned char mapping[256] = {0,1,255};
unsigned char db62[36];
opus_int32 i,j;
int rc,err;
OpusEncoder *enc;
OpusMSEncoder *MSenc;
OpusDecoder *dec;
OpusMSDecoder *MSdec;
OpusMSDecoder *MSdec_err;
OpusDecoder *dec_err[10];
short *inbuf;
short *outbuf;
short *out2buf;
opus_int32 bitrate_bps;
unsigned char packet[MAX_PACKET+257];
opus_uint32 enc_final_range;
opus_uint32 dec_final_range;
int fswitch;
int fsize;
int count;
/*FIXME: encoder api tests, fs!=48k, mono, VBR*/
fprintf(stdout," Encode+Decode tests.\n");
enc = opus_encoder_create(48000, 2, OPUS_APPLICATION_VOIP, &err);
if(err != OPUS_OK || enc==NULL)test_failed();
for(i=0;i<2;i++)
{
int *ret_err;
ret_err = i?0:&err;
MSenc = opus_multistream_encoder_create(8000, 2, 2, 0, mapping, OPUS_UNIMPLEMENTED, ret_err);
if((ret_err && *ret_err != OPUS_BAD_ARG) || MSenc!=NULL)test_failed();
MSenc = opus_multistream_encoder_create(8000, 0, 1, 0, mapping, OPUS_APPLICATION_VOIP, ret_err);
if((ret_err && *ret_err != OPUS_BAD_ARG) || MSenc!=NULL)test_failed();
MSenc = opus_multistream_encoder_create(44100, 2, 2, 0, mapping, OPUS_APPLICATION_VOIP, ret_err);
if((ret_err && *ret_err != OPUS_BAD_ARG) || MSenc!=NULL)test_failed();
MSenc = opus_multistream_encoder_create(8000, 2, 2, 3, mapping, OPUS_APPLICATION_VOIP, ret_err);
if((ret_err && *ret_err != OPUS_BAD_ARG) || MSenc!=NULL)test_failed();
MSenc = opus_multistream_encoder_create(8000, 2, -1, 0, mapping, OPUS_APPLICATION_VOIP, ret_err);
if((ret_err && *ret_err != OPUS_BAD_ARG) || MSenc!=NULL)test_failed();
MSenc = opus_multistream_encoder_create(8000, 256, 2, 0, mapping, OPUS_APPLICATION_VOIP, ret_err);
if((ret_err && *ret_err != OPUS_BAD_ARG) || MSenc!=NULL)test_failed();
}
MSenc = opus_multistream_encoder_create(8000, 2, 2, 0, mapping, OPUS_APPLICATION_AUDIO, &err);
if(err != OPUS_OK || MSenc==NULL)test_failed();
/*Some multistream encoder API tests*/
if(opus_multistream_encoder_ctl(MSenc, OPUS_GET_BITRATE(&i))!=OPUS_OK)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_GET_LSB_DEPTH(&i))!=OPUS_OK)test_failed();
if(i<16)test_failed();
{
OpusEncoder *tmp_enc;
if(opus_multistream_encoder_ctl(MSenc, OPUS_MULTISTREAM_GET_ENCODER_STATE(1,&tmp_enc))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(tmp_enc, OPUS_GET_LSB_DEPTH(&j))!=OPUS_OK)test_failed();
if(i!=j)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_MULTISTREAM_GET_ENCODER_STATE(2,&tmp_enc))!=OPUS_BAD_ARG)test_failed();
}
dec = opus_decoder_create(48000, 2, &err);
if(err != OPUS_OK || dec==NULL)test_failed();
MSdec = opus_multistream_decoder_create(48000, 2, 2, 0, mapping, &err);
if(err != OPUS_OK || MSdec==NULL)test_failed();
MSdec_err = opus_multistream_decoder_create(48000, 3, 2, 0, mapping, &err);
if(err != OPUS_OK || MSdec_err==NULL)test_failed();
dec_err[0]=(OpusDecoder *)malloc(opus_decoder_get_size(2));
memcpy(dec_err[0],dec,opus_decoder_get_size(2));
dec_err[1] = opus_decoder_create(48000, 1, &err);
dec_err[2] = opus_decoder_create(24000, 2, &err);
dec_err[3] = opus_decoder_create(24000, 1, &err);
dec_err[4] = opus_decoder_create(16000, 2, &err);
dec_err[5] = opus_decoder_create(16000, 1, &err);
dec_err[6] = opus_decoder_create(12000, 2, &err);
dec_err[7] = opus_decoder_create(12000, 1, &err);
dec_err[8] = opus_decoder_create(8000, 2, &err);
dec_err[9] = opus_decoder_create(8000, 1, &err);
for(i=0;i<10;i++)if(dec_err[i]==NULL)test_failed();
{
OpusEncoder *enccpy;
/*The opus state structures contain no pointers and can be freely copied*/
enccpy=(OpusEncoder *)malloc(opus_encoder_get_size(2));
memcpy(enccpy,enc,opus_encoder_get_size(2));
memset(enc,255,opus_encoder_get_size(2));
opus_encoder_destroy(enc);
enc=enccpy;
}
inbuf=(short *)malloc(sizeof(short)*SAMPLES*2);
outbuf=(short *)malloc(sizeof(short)*SAMPLES*2);
out2buf=(short *)malloc(sizeof(short)*MAX_FRAME_SAMP*3);
if(inbuf==NULL || outbuf==NULL || out2buf==NULL)test_failed();
generate_music(inbuf,SAMPLES);
/* FILE *foo;
foo = fopen("foo.sw", "wb+");
fwrite(inbuf, 1, SAMPLES*2*2, foo);
fclose(foo);*/
if(opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_AUTO))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(-2))!=OPUS_BAD_ARG)test_failed();
if(opus_encode(enc, inbuf, 500, packet, MAX_PACKET)!=OPUS_BAD_ARG)test_failed();
for(rc=0;rc<3;rc++)
{
if(opus_encoder_ctl(enc, OPUS_SET_VBR(rc<2))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(rc==1))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(rc==1))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(rc==0))!=OPUS_OK)test_failed();
for(j=0;j<13;j++)
{
int rate;
int modes[13]={0,0,0,1,1,1,1,2,2,2,2,2,2};
int rates[13]={6000,12000,48000,16000,32000,48000,64000,512000,13000,24000,48000,64000,96000};
int frame[13]={960*2,960,480,960,960,960,480,960*3,960*3,960,480,240,120};
rate=rates[j]+fast_rand()%rates[j];
count=i=0;
do {
int bw,len,out_samples,frame_size;
frame_size=frame[j];
if((fast_rand()&255)==0)
{
if(opus_encoder_ctl(enc, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
if(opus_decoder_ctl(dec, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
if((fast_rand()&1)!=0)
{
if(opus_decoder_ctl(dec_err[fast_rand()&1], OPUS_RESET_STATE)!=OPUS_OK)test_failed();
}
}
if((fast_rand()&127)==0)
{
if(opus_decoder_ctl(dec_err[fast_rand()&1], OPUS_RESET_STATE)!=OPUS_OK)test_failed();
}
if(fast_rand()%10==0){
int complex=fast_rand()%11;
if(opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complex))!=OPUS_OK)test_failed();
}
if(fast_rand()%50==0)opus_decoder_ctl(dec, OPUS_RESET_STATE);
if(opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(rc==0))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_SILK_ONLY+modes[j]))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_DTX(fast_rand()&1))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_BITRATE(rate))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS((rates[j]>=64000?2:1)))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY((count>>2)%11))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC((fast_rand()&15)&(fast_rand()%15)))!=OPUS_OK)test_failed();
bw=modes[j]==0?OPUS_BANDWIDTH_NARROWBAND+(fast_rand()%3):
modes[j]==1?OPUS_BANDWIDTH_SUPERWIDEBAND+(fast_rand()&1):
OPUS_BANDWIDTH_NARROWBAND+(fast_rand()%5);
if(modes[j]==2&&bw==OPUS_BANDWIDTH_MEDIUMBAND)bw+=3;
if(opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bw))!=OPUS_OK)test_failed();
len = opus_encode(enc, &inbuf[i<<1], frame_size, packet, MAX_PACKET);
if(len<0 || len>MAX_PACKET)test_failed();
if(opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range))!=OPUS_OK)test_failed();
if((fast_rand()&3)==0)
{
if(opus_packet_pad(packet,len,len+1)!=OPUS_OK)test_failed();
len++;
}
if((fast_rand()&7)==0)
{
if(opus_packet_pad(packet,len,len+256)!=OPUS_OK)test_failed();
len+=256;
}
if((fast_rand()&3)==0)
{
len=opus_packet_unpad(packet,len);
if(len<1)test_failed();
}
out_samples = opus_decode(dec, packet, len, &outbuf[i<<1], MAX_FRAME_SAMP, 0);
if(out_samples!=frame_size)test_failed();
if(opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range))!=OPUS_OK)test_failed();
if(enc_final_range!=dec_final_range)test_failed();
/*LBRR decode*/
out_samples = opus_decode(dec_err[0], packet, len, out2buf, frame_size, (fast_rand()&3)!=0);
if(out_samples!=frame_size)test_failed();
out_samples = opus_decode(dec_err[1], packet, (fast_rand()&3)==0?0:len, out2buf, MAX_FRAME_SAMP, (fast_rand()&7)!=0);
if(out_samples<120)test_failed();
i+=frame_size;
count++;
}while(i<(SSAMPLES-MAX_FRAME_SAMP));
fprintf(stdout," Mode %s FB encode %s, %6d bps OK.\n",mstrings[modes[j]],rc==0?" VBR":rc==1?"CVBR":" CBR",rate);
}
}
if(opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(OPUS_AUTO))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(OPUS_AUTO))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(0))!=OPUS_OK)test_failed();
if(opus_encoder_ctl(enc, OPUS_SET_DTX(0))!=OPUS_OK)test_failed();
for(rc=0;rc<3;rc++)
{
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_VBR(rc<2))!=OPUS_OK)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_VBR_CONSTRAINT(rc==1))!=OPUS_OK)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_VBR_CONSTRAINT(rc==1))!=OPUS_OK)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_INBAND_FEC(rc==0))!=OPUS_OK)test_failed();
for(j=0;j<16;j++)
{
int rate;
int modes[16]={0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2};
int rates[16]={4000,12000,32000,8000,16000,32000,48000,88000,4000,12000,32000,8000,16000,32000,48000,88000};
int frame[16]={160*1,160,80,160,160,80,40,20,160*1,160,80,160,160,80,40,20};
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_INBAND_FEC(rc==0&&j==1))!=OPUS_OK)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_FORCE_MODE(MODE_SILK_ONLY+modes[j]))!=OPUS_OK)test_failed();
rate=rates[j]+fast_rand()%rates[j];
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_DTX(fast_rand()&1))!=OPUS_OK)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_BITRATE(rate))!=OPUS_OK)test_failed();
count=i=0;
do {
int len,out_samples,frame_size,loss;
opus_int32 pred;
if(opus_multistream_encoder_ctl(MSenc, OPUS_GET_PREDICTION_DISABLED(&pred))!=OPUS_OK)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_PREDICTION_DISABLED((int)(fast_rand()&15)<(pred?11:4)))!=OPUS_OK)test_failed();
frame_size=frame[j];
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_COMPLEXITY((count>>2)%11))!=OPUS_OK)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_SET_PACKET_LOSS_PERC((fast_rand()&15)&(fast_rand()%15)))!=OPUS_OK)test_failed();
if((fast_rand()&255)==0)
{
if(opus_multistream_encoder_ctl(MSenc, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
if(opus_multistream_decoder_ctl(MSdec, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
if((fast_rand()&3)!=0)
{
if(opus_multistream_decoder_ctl(MSdec_err, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
}
}
if((fast_rand()&255)==0)
{
if(opus_multistream_decoder_ctl(MSdec_err, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
}
len = opus_multistream_encode(MSenc, &inbuf[i<<1], frame_size, packet, MAX_PACKET);
if(len<0 || len>MAX_PACKET)test_failed();
if(opus_multistream_encoder_ctl(MSenc, OPUS_GET_FINAL_RANGE(&enc_final_range))!=OPUS_OK)test_failed();
if((fast_rand()&3)==0)
{
if(opus_multistream_packet_pad(packet,len,len+1,2)!=OPUS_OK)test_failed();
len++;
}
if((fast_rand()&7)==0)
{
if(opus_multistream_packet_pad(packet,len,len+256,2)!=OPUS_OK)test_failed();
len+=256;
}
if((fast_rand()&3)==0)
{
len=opus_multistream_packet_unpad(packet,len,2);
if(len<1)test_failed();
}
out_samples = opus_multistream_decode(MSdec, packet, len, out2buf, MAX_FRAME_SAMP, 0);
if(out_samples!=frame_size*6)test_failed();
if(opus_multistream_decoder_ctl(MSdec, OPUS_GET_FINAL_RANGE(&dec_final_range))!=OPUS_OK)test_failed();
if(enc_final_range!=dec_final_range)test_failed();
/*LBRR decode*/
loss=(fast_rand()&63)==0;
out_samples = opus_multistream_decode(MSdec_err, packet, loss?0:len, out2buf, frame_size*6, (fast_rand()&3)!=0);
if(out_samples!=(frame_size*6))test_failed();
i+=frame_size;
count++;
}while(i<(SSAMPLES/12-MAX_FRAME_SAMP));
fprintf(stdout," Mode %s NB dual-mono MS encode %s, %6d bps OK.\n",mstrings[modes[j]],rc==0?" VBR":rc==1?"CVBR":" CBR",rate);
}
}
bitrate_bps=512000;
fsize=fast_rand()%31;
fswitch=100;
debruijn2(6,db62);
count=i=0;
do {
unsigned char toc;
const unsigned char *frames[48];
short size[48];
int payload_offset;
opus_uint32 dec_final_range2;
int jj,dec2;
int len,out_samples;
int frame_size=fsizes[db62[fsize]];
opus_int32 offset=i%(SAMPLES-MAX_FRAME_SAMP);
opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
len = opus_encode(enc, &inbuf[offset<<1], frame_size, packet, MAX_PACKET);
if(len<0 || len>MAX_PACKET)test_failed();
count++;
opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range));
out_samples = opus_decode(dec, packet, len, &outbuf[offset<<1], MAX_FRAME_SAMP, 0);
if(out_samples!=frame_size)test_failed();
opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
/* compare final range encoder rng values of encoder and decoder */
if(dec_final_range!=enc_final_range)test_failed();
/* We fuzz the packet, but take care not to only corrupt the payload
Corrupted headers are tested elsewhere and we need to actually run
the decoders in order to compare them. */
if(opus_packet_parse(packet,len,&toc,frames,size,&payload_offset)<=0)test_failed();
if((fast_rand()&1023)==0)len=0;
for(j=(opus_int32)(frames[0]-packet);j<len;j++)for(jj=0;jj<8;jj++)packet[j]^=((!no_fuzz)&&((fast_rand()&1023)==0))<<jj;
out_samples = opus_decode(dec_err[0], len>0?packet:NULL, len, out2buf, MAX_FRAME_SAMP, 0);
if(out_samples<0||out_samples>MAX_FRAME_SAMP)test_failed();
if((len>0&&out_samples!=frame_size))test_failed(); /*FIXME use lastframe*/
opus_decoder_ctl(dec_err[0], OPUS_GET_FINAL_RANGE(&dec_final_range));
/*randomly select one of the decoders to compare with*/
dec2=fast_rand()%9+1;
out_samples = opus_decode(dec_err[dec2], len>0?packet:NULL, len, out2buf, MAX_FRAME_SAMP, 0);
if(out_samples<0||out_samples>MAX_FRAME_SAMP)test_failed(); /*FIXME, use factor, lastframe for loss*/
opus_decoder_ctl(dec_err[dec2], OPUS_GET_FINAL_RANGE(&dec_final_range2));
if(len>0&&dec_final_range!=dec_final_range2)test_failed();
fswitch--;
if(fswitch<1)
{
int new_size;
fsize=(fsize+1)%36;
new_size=fsizes[db62[fsize]];
if(new_size==960||new_size==480)fswitch=2880/new_size*(fast_rand()%19+1);
else fswitch=(fast_rand()%(2880/new_size))+1;
}
bitrate_bps=((fast_rand()%508000+4000)+bitrate_bps)>>1;
i+=frame_size;
}while(i<SAMPLES*4);
fprintf(stdout," All framesize pairs switching encode, %d frames OK.\n",count);
if(opus_encoder_ctl(enc, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
opus_encoder_destroy(enc);
if(opus_multistream_encoder_ctl(MSenc, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
opus_multistream_encoder_destroy(MSenc);
if(opus_decoder_ctl(dec, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
opus_decoder_destroy(dec);
if(opus_multistream_decoder_ctl(MSdec, OPUS_RESET_STATE)!=OPUS_OK)test_failed();
opus_multistream_decoder_destroy(MSdec);
opus_multistream_decoder_destroy(MSdec_err);
for(i=0;i<10;i++)opus_decoder_destroy(dec_err[i]);
free(inbuf);
free(outbuf);
free(out2buf);
return 0;
}
void print_usage(char* _argv[])
{
fprintf(stderr,"Usage: %s [<seed>] [-fuzz <num_encoders> <num_settings_per_encoder>]\n",_argv[0]);
}
int main(int _argc, char **_argv)
{
int args=1;
char * strtol_str=NULL;
const char * oversion;
const char * env_seed;
int env_used;
int num_encoders_to_fuzz=5;
int num_setting_changes=40;
env_used=0;
env_seed=getenv("SEED");
if(_argc>1)
iseed=strtol(_argv[1], &strtol_str, 10); /* the first input argument might be the seed */
if(strtol_str!=NULL && strtol_str[0]=='\0') /* iseed is a valid number */
args++;
else if(env_seed) {
iseed=atoi(env_seed);
env_used=1;
}
else iseed=(opus_uint32)time(NULL)^(((opus_uint32)getpid()&65535)<<16);
Rw=Rz=iseed;
while(args<_argc)
{
if(strcmp(_argv[args], "-fuzz")==0 && _argc==(args+3)) {
num_encoders_to_fuzz=strtol(_argv[args+1], &strtol_str, 10);
if(strtol_str[0]!='\0' || num_encoders_to_fuzz<=0) {
print_usage(_argv);
return EXIT_FAILURE;
}
num_setting_changes=strtol(_argv[args+2], &strtol_str, 10);
if(strtol_str[0]!='\0' || num_setting_changes<=0) {
print_usage(_argv);
return EXIT_FAILURE;
}
args+=3;
}
else {
print_usage(_argv);
return EXIT_FAILURE;
}
}
oversion=opus_get_version_string();
if(!oversion)test_failed();
fprintf(stderr,"Testing %s encoder. Random seed: %u (%.4X)\n", oversion, iseed, fast_rand() % 65535);
if(env_used)fprintf(stderr," Random seed set from the environment (SEED=%s).\n", env_seed);
regression_test();
/*Setting TEST_OPUS_NOFUZZ tells the tool not to send garbage data
into the decoders. This is helpful because garbage data
may cause the decoders to clip, which angers CLANG IOC.*/
run_test1(getenv("TEST_OPUS_NOFUZZ")!=NULL);
/* Fuzz encoder settings online */
if(getenv("TEST_OPUS_NOFUZZ")==NULL) {
fprintf(stderr,"Running fuzz_encoder_settings with %d encoder(s) and %d setting change(s) each.\n",
num_encoders_to_fuzz, num_setting_changes);
fuzz_encoder_settings(num_encoders_to_fuzz, num_setting_changes);
}
fprintf(stderr,"Tests completed successfully.\n");
return 0;
}

93
externals/opus/opus/tests/test_opus_padding.c vendored Executable file
View File

@@ -0,0 +1,93 @@
/* Copyright (c) 2012 Xiph.Org Foundation
Written by Jüri Aedla and Ralph Giles */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Check for overflow in reading the padding length.
* http://lists.xiph.org/pipermail/opus/2012-November/001834.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "opus.h"
#include "test_opus_common.h"
#define PACKETSIZE 16909318
#define CHANNELS 2
#define FRAMESIZE 5760
int test_overflow(void)
{
OpusDecoder *decoder;
int result;
int error;
unsigned char *in = malloc(PACKETSIZE);
opus_int16 *out = malloc(FRAMESIZE*CHANNELS*sizeof(*out));
fprintf(stderr, " Checking for padding overflow... ");
if (!in || !out) {
fprintf(stderr, "FAIL (out of memory)\n");
return -1;
}
in[0] = 0xff;
in[1] = 0x41;
memset(in + 2, 0xff, PACKETSIZE - 3);
in[PACKETSIZE-1] = 0x0b;
decoder = opus_decoder_create(48000, CHANNELS, &error);
result = opus_decode(decoder, in, PACKETSIZE, out, FRAMESIZE, 0);
opus_decoder_destroy(decoder);
free(in);
free(out);
if (result != OPUS_INVALID_PACKET) {
fprintf(stderr, "FAIL!\n");
test_failed();
}
fprintf(stderr, "OK.\n");
return 1;
}
int main(void)
{
const char *oversion;
int tests = 0;;
iseed = 0;
oversion = opus_get_version_string();
if (!oversion) test_failed();
fprintf(stderr, "Testing %s padding.\n", oversion);
tests += test_overflow();
fprintf(stderr, "All padding tests passed.\n");
return 0;
}

View File

@@ -0,0 +1,394 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "float_cast.h"
#include "opus.h"
#include "test_opus_common.h"
#include "opus_projection.h"
#include "mathops.h"
#include "../src/mapping_matrix.h"
#include "mathops.h"
#define BUFFER_SIZE 960
#define MAX_DATA_BYTES 32768
#define MAX_FRAME_SAMPLES 5760
#define ERROR_TOLERANCE 1
#define SIMPLE_MATRIX_SIZE 12
#define SIMPLE_MATRIX_FRAME_SIZE 10
#define SIMPLE_MATRIX_INPUT_SIZE 30
#define SIMPLE_MATRIX_OUTPUT_SIZE 40
int assert_is_equal(
const opus_val16 *a, const opus_int16 *b, int size, opus_int16 tolerance)
{
int i;
for (i = 0; i < size; i++)
{
#ifdef FIXED_POINT
opus_int16 val = a[i];
#else
opus_int16 val = FLOAT2INT16(a[i]);
#endif
if (abs(val - b[i]) > tolerance)
return 1;
}
return 0;
}
int assert_is_equal_short(
const opus_int16 *a, const opus_int16 *b, int size, opus_int16 tolerance)
{
int i;
for (i = 0; i < size; i++)
if (abs(a[i] - b[i]) > tolerance)
return 1;
return 0;
}
void test_simple_matrix(void)
{
const MappingMatrix simple_matrix_params = {4, 3, 0};
const opus_int16 simple_matrix_data[SIMPLE_MATRIX_SIZE] = {0, 32767, 0, 0, 32767, 0, 0, 0, 0, 0, 0, 32767};
const opus_int16 input_int16[SIMPLE_MATRIX_INPUT_SIZE] = {
32767, 0, -32768, 29491, -3277, -29491, 26214, -6554, -26214, 22938, -9830,
-22938, 19661, -13107, -19661, 16384, -16384, -16384, 13107, -19661, -13107,
9830, -22938, -9830, 6554, -26214, -6554, 3277, -29491, -3277};
const opus_int16 expected_output_int16[SIMPLE_MATRIX_OUTPUT_SIZE] = {
0, 32767, 0, -32768, -3277, 29491, 0, -29491, -6554, 26214, 0, -26214,
-9830, 22938, 0, -22938, -13107, 19661, 0, -19661, -16384, 16384, 0, -16384,
-19661, 13107, 0, -13107, -22938, 9830, 0, -9830, -26214, 6554, 0, -6554,
-29491, 3277, 0, -3277};
int i, ret;
opus_int32 simple_matrix_size;
opus_val16 *input_val16;
opus_val16 *output_val16;
opus_int16 *output_int16;
MappingMatrix *simple_matrix;
/* Allocate input/output buffers. */
input_val16 = (opus_val16 *)opus_alloc(sizeof(opus_val16) * SIMPLE_MATRIX_INPUT_SIZE);
output_int16 = (opus_int16 *)opus_alloc(sizeof(opus_int16) * SIMPLE_MATRIX_OUTPUT_SIZE);
output_val16 = (opus_val16 *)opus_alloc(sizeof(opus_val16) * SIMPLE_MATRIX_OUTPUT_SIZE);
/* Initialize matrix */
simple_matrix_size = mapping_matrix_get_size(simple_matrix_params.rows,
simple_matrix_params.cols);
if (!simple_matrix_size)
test_failed();
simple_matrix = (MappingMatrix *)opus_alloc(simple_matrix_size);
mapping_matrix_init(simple_matrix, simple_matrix_params.rows,
simple_matrix_params.cols, simple_matrix_params.gain, simple_matrix_data,
sizeof(simple_matrix_data));
/* Copy inputs. */
for (i = 0; i < SIMPLE_MATRIX_INPUT_SIZE; i++)
{
#ifdef FIXED_POINT
input_val16[i] = input_int16[i];
#else
input_val16[i] = (1/32768.f)*input_int16[i];
#endif
}
/* _in_short */
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
output_val16[i] = 0;
for (i = 0; i < simple_matrix->rows; i++)
{
mapping_matrix_multiply_channel_in_short(simple_matrix,
input_int16, simple_matrix->cols, &output_val16[i], i,
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
}
ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
if (ret)
test_failed();
/* _out_short */
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
output_int16[i] = 0;
for (i = 0; i < simple_matrix->cols; i++)
{
mapping_matrix_multiply_channel_out_short(simple_matrix,
&input_val16[i], i, simple_matrix->cols, output_int16,
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
}
ret = assert_is_equal_short(output_int16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
if (ret)
test_failed();
#if !defined(DISABLE_FLOAT_API) && !defined(FIXED_POINT)
/* _in_float */
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
output_val16[i] = 0;
for (i = 0; i < simple_matrix->rows; i++)
{
mapping_matrix_multiply_channel_in_float(simple_matrix,
input_val16, simple_matrix->cols, &output_val16[i], i,
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
}
ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
if (ret)
test_failed();
/* _out_float */
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
output_val16[i] = 0;
for (i = 0; i < simple_matrix->cols; i++)
{
mapping_matrix_multiply_channel_out_float(simple_matrix,
&input_val16[i], i, simple_matrix->cols, output_val16,
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
}
ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
if (ret)
test_failed();
#endif
opus_free(input_val16);
opus_free(output_int16);
opus_free(output_val16);
opus_free(simple_matrix);
}
void test_creation_arguments(const int channels, const int mapping_family)
{
int streams;
int coupled_streams;
int enc_error;
int dec_error;
int ret;
OpusProjectionEncoder *st_enc = NULL;
OpusProjectionDecoder *st_dec = NULL;
const opus_int32 Fs = 48000;
const int application = OPUS_APPLICATION_AUDIO;
int order_plus_one = (int)floor(sqrt((float)channels));
int nondiegetic_channels = channels - order_plus_one * order_plus_one;
int is_channels_valid = 0;
int is_projection_valid = 0;
st_enc = opus_projection_ambisonics_encoder_create(Fs, channels,
mapping_family, &streams, &coupled_streams, application, &enc_error);
if (st_enc != NULL)
{
opus_int32 matrix_size;
unsigned char *matrix;
ret = opus_projection_encoder_ctl(st_enc,
OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, &matrix_size);
if (ret != OPUS_OK || !matrix_size)
test_failed();
matrix = (unsigned char *)opus_alloc(matrix_size);
ret = opus_projection_encoder_ctl(st_enc,
OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, matrix, matrix_size);
opus_projection_encoder_destroy(st_enc);
st_dec = opus_projection_decoder_create(Fs, channels, streams,
coupled_streams, matrix, matrix_size, &dec_error);
if (st_dec != NULL)
{
opus_projection_decoder_destroy(st_dec);
}
opus_free(matrix);
}
is_channels_valid = (order_plus_one >= 2 && order_plus_one <= 4) &&
(nondiegetic_channels == 0 || nondiegetic_channels == 2);
is_projection_valid = (enc_error == OPUS_OK && dec_error == OPUS_OK);
if (is_channels_valid ^ is_projection_valid)
{
fprintf(stderr, "Channels: %d, Family: %d\n", channels, mapping_family);
fprintf(stderr, "Order+1: %d, Non-diegetic Channels: %d\n",
order_plus_one, nondiegetic_channels);
fprintf(stderr, "Streams: %d, Coupled Streams: %d\n",
streams, coupled_streams);
test_failed();
}
}
void generate_music(short *buf, opus_int32 len, opus_int32 channels)
{
opus_int32 i,j,k;
opus_int32 *a,*b,*c,*d;
a = (opus_int32 *)malloc(sizeof(opus_int32) * channels);
b = (opus_int32 *)malloc(sizeof(opus_int32) * channels);
c = (opus_int32 *)malloc(sizeof(opus_int32) * channels);
d = (opus_int32 *)malloc(sizeof(opus_int32) * channels);
memset(a, 0, sizeof(opus_int32) * channels);
memset(b, 0, sizeof(opus_int32) * channels);
memset(c, 0, sizeof(opus_int32) * channels);
memset(d, 0, sizeof(opus_int32) * channels);
j=0;
for(i=0;i<len;i++)
{
for(k=0;k<channels;k++)
{
opus_uint32 r;
opus_int32 v;
v=(((j*((j>>12)^((j>>10|j>>12)&26&j>>7)))&128)+128)<<15;
r=fast_rand();v+=r&65535;v-=r>>16;
b[k]=v-a[k]+((b[k]*61+32)>>6);a[k]=v;
c[k]=(30*(c[k]+b[k]+d[k])+32)>>6;d[k]=b[k];
v=(c[k]+128)>>8;
buf[i*channels+k]=v>32767?32767:(v<-32768?-32768:v);
if(i%6==0)j++;
}
}
free(a);
free(b);
free(c);
free(d);
}
void test_encode_decode(opus_int32 bitrate, opus_int32 channels,
const int mapping_family)
{
const opus_int32 Fs = 48000;
const int application = OPUS_APPLICATION_AUDIO;
OpusProjectionEncoder *st_enc;
OpusProjectionDecoder *st_dec;
int streams;
int coupled;
int error;
short *buffer_in;
short *buffer_out;
unsigned char data[MAX_DATA_BYTES] = { 0 };
int len;
int out_samples;
opus_int32 matrix_size = 0;
unsigned char *matrix = NULL;
buffer_in = (short *)malloc(sizeof(short) * BUFFER_SIZE * channels);
buffer_out = (short *)malloc(sizeof(short) * BUFFER_SIZE * channels);
st_enc = opus_projection_ambisonics_encoder_create(Fs, channels,
mapping_family, &streams, &coupled, application, &error);
if (error != OPUS_OK) {
fprintf(stderr,
"Couldn\'t create encoder with %d channels and mapping family %d.\n",
channels, mapping_family);
free(buffer_in);
free(buffer_out);
test_failed();
}
error = opus_projection_encoder_ctl(st_enc,
OPUS_SET_BITRATE(bitrate * 1000 * (streams + coupled)));
if (error != OPUS_OK)
{
goto bad_cleanup;
}
error = opus_projection_encoder_ctl(st_enc,
OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, &matrix_size);
if (error != OPUS_OK || !matrix_size)
{
goto bad_cleanup;
}
matrix = (unsigned char *)opus_alloc(matrix_size);
error = opus_projection_encoder_ctl(st_enc,
OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, matrix, matrix_size);
st_dec = opus_projection_decoder_create(Fs, channels, streams, coupled,
matrix, matrix_size, &error);
opus_free(matrix);
if (error != OPUS_OK) {
fprintf(stderr,
"Couldn\'t create decoder with %d channels, %d streams "
"and %d coupled streams.\n", channels, streams, coupled);
goto bad_cleanup;
}
generate_music(buffer_in, BUFFER_SIZE, channels);
len = opus_projection_encode(
st_enc, buffer_in, BUFFER_SIZE, data, MAX_DATA_BYTES);
if(len<0 || len>MAX_DATA_BYTES) {
fprintf(stderr,"opus_encode() returned %d\n", len);
goto bad_cleanup;
}
out_samples = opus_projection_decode(
st_dec, data, len, buffer_out, MAX_FRAME_SAMPLES, 0);
if(out_samples!=BUFFER_SIZE) {
fprintf(stderr,"opus_decode() returned %d\n", out_samples);
goto bad_cleanup;
}
opus_projection_decoder_destroy(st_dec);
opus_projection_encoder_destroy(st_enc);
free(buffer_in);
free(buffer_out);
return;
bad_cleanup:
free(buffer_in);
free(buffer_out);
test_failed();
}
int main(int _argc, char **_argv)
{
unsigned int i;
(void)_argc;
(void)_argv;
/* Test simple matrix multiplication routines. */
test_simple_matrix();
/* Test full range of channels in creation arguments. */
for (i = 0; i < 255; i++)
test_creation_arguments(i, 3);
/* Test encode/decode pipeline. */
test_encode_decode(64 * 18, 18, 3);
fprintf(stderr, "All projection tests passed.\n");
return 0;
}