diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-28 21:17:26 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-28 21:17:26 +0000 |
commit | 6b6bee25314cfac02cc555cddedb9680c63a26d6 (patch) | |
tree | 237d6cc1ffccbe6e8d5de6dc95c699934878e774 | |
parent | 79181daa729bbfd77c8bf51dbcac8aac1593ccba (diff) | |
download | src-6b6bee25314cfac02cc555cddedb9680c63a26d6.tar.gz |
Update Opus to 1.0.2.
This update contains improvements for PLC, and various other fixes.
TBR=wez@chromium.org
Review URL: https://codereview.chromium.org/12388030
git-svn-id: svn://svn.chromium.org/chrome/trunk/deps/third_party/opus@185324 0039d316-1c4b-4281-b951-d872f2087c98
88 files changed, 2455 insertions, 949 deletions
@@ -37,8 +37,8 @@ specified at: Xiph.Org Foundation: https://datatracker.ietf.org/ipr/1524/ -Skype Limited: -https://datatracker.ietf.org/ipr/1602/ +Microsoft Corporation: +https://datatracker.ietf.org/ipr/1914/ Broadcom Corporation: https://datatracker.ietf.org/ipr/1526/ diff --git a/Makefile.am b/Makefile.am index db37d99..85909ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -126,24 +126,24 @@ install-opus: install # Or just the docs docs: - cd doc && $(MAKE) $(AM_MAKEFLAGS) + ( cd doc && $(MAKE) $(AM_MAKEFLAGS) ) install-docs: - cd doc && $(MAKE) $(AM_MAKEFLAGS) install + ( cd doc && $(MAKE) $(AM_MAKEFLAGS) install ) # Or everything (by default) all-local: - @[ -n "$(NO_DOXYGEN)" ] || cd doc && $(MAKE) $(AM_MAKEFLAGS) + @[ -n "$(NO_DOXYGEN)" ] || ( cd doc && $(MAKE) $(AM_MAKEFLAGS) ) install-data-local: - @[ -n "$(NO_DOXYGEN)" ] || cd doc && $(MAKE) $(AM_MAKEFLAGS) install + @[ -n "$(NO_DOXYGEN)" ] || ( cd doc && $(MAKE) $(AM_MAKEFLAGS) install ) clean-local: - -cd doc && $(MAKE) $(AM_MAKEFLAGS) clean + -( cd doc && $(MAKE) $(AM_MAKEFLAGS) clean ) uninstall-local: - cd doc && $(MAKE) $(AM_MAKEFLAGS) uninstall + ( cd doc && $(MAKE) $(AM_MAKEFLAGS) uninstall ) .PHONY: opus check-opus install-opus docs install-docs diff --git a/Makefile.in b/Makefile.in index 07cb8eb..38b5021 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11.3 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -19,6 +19,23 @@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -405,6 +422,11 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac DATA = $(m4data_DATA) $(pkgconfig_DATA) am__pkginclude_HEADERS_DIST = include/opus.h \ include/opus_multistream.h include/opus_types.h \ @@ -522,6 +544,8 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PC_BUILD = @PC_BUILD@ +PC_LIBM = @PC_LIBM@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -894,7 +918,6 @@ opus-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/opus-uninstalled.pc cd $(top_builddir) && $(SHELL) ./config.status $@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -902,6 +925,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } @@ -1861,8 +1886,11 @@ distclean-libtool: -rm -f libtool config.lt install-m4dataDATA: $(m4data_DATA) @$(NORMAL_INSTALL) - test -z "$(m4datadir)" || $(MKDIR_P) "$(DESTDIR)$(m4datadir)" @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(m4datadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(m4datadir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -1879,8 +1907,11 @@ uninstall-m4dataDATA: dir='$(DESTDIR)$(m4datadir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) - test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -1897,8 +1928,11 @@ uninstall-pkgconfigDATA: dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) - test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -2176,13 +2210,10 @@ distdir: $(DISTFILES) done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ @@ -2268,7 +2299,7 @@ distcheck: dist *.zip*) \ unzip $(distdir).zip ;;\ esac - chmod -R a-w $(distdir); chmod a+w $(distdir) + chmod -R a-w $(distdir); chmod u+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) @@ -2499,23 +2530,23 @@ install-opus: install # Or just the docs docs: - cd doc && $(MAKE) $(AM_MAKEFLAGS) + ( cd doc && $(MAKE) $(AM_MAKEFLAGS) ) install-docs: - cd doc && $(MAKE) $(AM_MAKEFLAGS) install + ( cd doc && $(MAKE) $(AM_MAKEFLAGS) install ) # Or everything (by default) all-local: - @[ -n "$(NO_DOXYGEN)" ] || cd doc && $(MAKE) $(AM_MAKEFLAGS) + @[ -n "$(NO_DOXYGEN)" ] || ( cd doc && $(MAKE) $(AM_MAKEFLAGS) ) install-data-local: - @[ -n "$(NO_DOXYGEN)" ] || cd doc && $(MAKE) $(AM_MAKEFLAGS) install + @[ -n "$(NO_DOXYGEN)" ] || ( cd doc && $(MAKE) $(AM_MAKEFLAGS) install ) clean-local: - -cd doc && $(MAKE) $(AM_MAKEFLAGS) clean + -( cd doc && $(MAKE) $(AM_MAKEFLAGS) clean ) uninstall-local: - cd doc && $(MAKE) $(AM_MAKEFLAGS) uninstall + ( cd doc && $(MAKE) $(AM_MAKEFLAGS) uninstall ) .PHONY: opus check-opus install-opus docs install-docs @@ -59,6 +59,10 @@ To build from the git repository, the following steps are necessary: % ./configure % make +3) Install the codec libraries (optional) + +% sudo make install + Once you have compiled the codec, there will be a opus_demo executable in the top directory. @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.11.3 -*- Autoconf -*- +# generated automatically by aclocal 1.11.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, @@ -8629,7 +8629,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11.3], [], +m4_if([$1], [1.11.6], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -8645,7 +8645,7 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11.3])dnl +[AM_AUTOMAKE_VERSION([1.11.6])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) diff --git a/celt/bands.c b/celt/bands.c index f38b662..3be543c 100644 --- a/celt/bands.c +++ b/celt/bands.c @@ -905,8 +905,8 @@ static unsigned quant_band(int encode, const CELTMode *m, int i, celt_norm *X, c fill &= ((1<<B)-1)<<B; delta = 16384; } else { - imid = bitexact_cos(itheta); - iside = bitexact_cos(16384-itheta); + imid = bitexact_cos((opus_int16)itheta); + iside = bitexact_cos((opus_int16)(16384-itheta)); /* This is the mid vs side allocation that minimizes squared error in that band. */ delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid)); diff --git a/celt/celt.c b/celt/celt.c index adb9737..9bbe852 100644 --- a/celt/celt.c +++ b/celt/celt.c @@ -193,9 +193,13 @@ struct OpusCustomEncoder { #endif celt_sig in_mem[1]; /* Size = channels*mode->overlap */ - /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_PERIOD */ - /* celt_sig overlap_mem[], Size = channels*mode->overlap */ - /* opus_val16 oldEBands[], Size = 2*channels*mode->nbEBands */ + /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_MAXPERIOD */ + /* opus_val16 oldBandE[], Size = channels*mode->nbEBands */ + /* opus_val16 oldLogE[], Size = channels*mode->nbEBands */ + /* opus_val16 oldLogE2[], Size = channels*mode->nbEBands */ +#ifdef RESYNTH + /* opus_val16 overlap_mem[], Size = channels*overlap */ +#endif }; int celt_encoder_get_size(int channels) @@ -207,9 +211,14 @@ int celt_encoder_get_size(int channels) OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int channels) { int size = sizeof(struct CELTEncoder) - + (2*channels*mode->overlap-1)*sizeof(celt_sig) - + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) - + 3*channels*mode->nbEBands*sizeof(opus_val16); + + (channels*mode->overlap-1)*sizeof(celt_sig) /* celt_sig in_mem[channels*mode->overlap]; */ + + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */ + + 3*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ + /* opus_val16 oldLogE[channels*mode->nbEBands]; */ + /* opus_val16 oldLogE2[channels*mode->nbEBands]; */ +#ifdef RESYNTH + size += channels*mode->overlap*sizeof(celt_sig); /* celt_sig overlap_mem[channels*mode->nbEBands]; */ +#endif return size; } @@ -563,7 +572,7 @@ static opus_val32 l1_metric(const celt_norm *tmp, int N, int LM, int width) static int tf_analysis(const CELTMode *m, int len, int C, int isTransient, int *tf_res, int nbCompressedBytes, celt_norm *X, int N0, int LM, - int *tf_sum) + int start, int *tf_sum) { int i; VARDECL(int, metric); @@ -576,7 +585,7 @@ static int tf_analysis(const CELTMode *m, int len, int C, int isTransient, int tf_select=0; SAVE_STACK; - if (nbCompressedBytes<15*C) + if (nbCompressedBytes<15*C || start!=0) { *tf_sum = 0; for (i=0;i<len;i++) @@ -944,7 +953,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, N = M*st->mode->shortMdctSize; prefilter_mem = st->in_mem+CC*(st->overlap); - oldBandE = (opus_val16*)(st->in_mem+CC*(2*st->overlap+COMBFILTER_MAXPERIOD)); + oldBandE = (opus_val16*)(st->in_mem+CC*(st->overlap+COMBFILTER_MAXPERIOD)); oldLogE = oldBandE + CC*st->mode->nbEBands; oldLogE2 = oldLogE + CC*st->mode->nbEBands; @@ -1266,7 +1275,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, normalise_bands(st->mode, freq, X, bandE, effEnd, C, M); ALLOC(tf_res, st->mode->nbEBands, int); - tf_select = tf_analysis(st->mode, effEnd, C, isTransient, tf_res, effectiveBytes, X, N, LM, &tf_sum); + tf_select = tf_analysis(st->mode, effEnd, C, isTransient, tf_res, effectiveBytes, X, N, LM, st->start, &tf_sum); for (i=effEnd;i<st->end;i++) tf_res[i] = tf_res[effEnd-1]; @@ -1278,13 +1287,15 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, tf_encode(st->start, st->end, isTransient, tf_res, LM, tf_select, enc); - st->spread_decision = SPREAD_NORMAL; if (ec_tell(enc)+4<=total_bits) { - if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C) + if (shortBlocks || st->complexity < 3 + || nbAvailableBytes < 10*C || st->start!=0) { if (st->complexity == 0) st->spread_decision = SPREAD_NONE; + else + st->spread_decision = SPREAD_NORMAL; } else { st->spread_decision = spreading_decision(st->mode, X, &st->tonal_average, st->spread_decision, &st->hf_average, @@ -1588,7 +1599,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, if (CC==2) out_mem[1] = st->syn_mem[1]+MAX_PERIOD; - overlap_mem[0] = prefilter_mem+CC*COMBFILTER_MAXPERIOD; + overlap_mem[0] = (celt_sig*)(oldLogE2 + CC*st->mode->nbEBands); if (CC==2) overlap_mem[1] = overlap_mem[0] + st->overlap; @@ -1843,7 +1854,7 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...) { int i; opus_val16 *oldBandE, *oldLogE, *oldLogE2; - oldBandE = (opus_val16*)(st->in_mem+st->channels*(2*st->overlap+COMBFILTER_MAXPERIOD)); + oldBandE = (opus_val16*)(st->in_mem+st->channels*(st->overlap+COMBFILTER_MAXPERIOD)); oldLogE = oldBandE + st->channels*st->mode->nbEBands; oldLogE2 = oldLogE + st->channels*st->mode->nbEBands; OPUS_CLEAR((char*)&st->ENCODER_RESET_START, @@ -2028,7 +2039,6 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R { int c; int pitch_index; - int overlap = st->mode->overlap; opus_val16 fade = Q15ONE; int i, len; const int C = st->channels; @@ -2039,8 +2049,17 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R opus_val16 *lpc; opus_val32 *out_syn[2]; opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; + const OpusCustomMode *mode; + int nbEBands; + int overlap; + const opus_int16 *eBands; SAVE_STACK; + mode = st->mode; + nbEBands = mode->nbEBands; + overlap = mode->overlap; + eBands = mode->eBands; + c=0; do { decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap); out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD; @@ -2048,15 +2067,15 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R } while (++c<C); lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*C); oldBandE = lpc+C*LPC_ORDER; - oldLogE = oldBandE + 2*st->mode->nbEBands; - oldLogE2 = oldLogE + 2*st->mode->nbEBands; - backgroundLogE = oldLogE2 + 2*st->mode->nbEBands; + oldLogE = oldBandE + 2*nbEBands; + oldLogE2 = oldLogE + 2*nbEBands; + backgroundLogE = oldLogE2 + 2*nbEBands; - out_syn[0] = out_mem[0]+MAX_PERIOD-N; - if (C==2) - out_syn[1] = out_mem[1]+MAX_PERIOD-N; + c=0; do { + out_syn[c] = out_mem[c]+MAX_PERIOD-N; + } while (++c<C); - len = N+st->mode->overlap; + len = N+overlap; if (st->loss_count >= 5 || st->start!=0) { @@ -2068,37 +2087,37 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R int effEnd; effEnd = st->end; - if (effEnd > st->mode->effEBands) - effEnd = st->mode->effEBands; + if (effEnd > mode->effEBands) + effEnd = mode->effEBands; ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */ ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ - ALLOC(bandE, st->mode->nbEBands*C, celt_ener); + ALLOC(bandE, nbEBands*C, celt_ener); if (st->loss_count >= 5) - log2Amp(st->mode, st->start, st->end, bandE, backgroundLogE, C); + log2Amp(mode, st->start, st->end, bandE, backgroundLogE, C); else { /* Energy decay */ opus_val16 decay = st->loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT); c=0; do { for (i=st->start;i<st->end;i++) - oldBandE[c*st->mode->nbEBands+i] -= decay; + oldBandE[c*nbEBands+i] -= decay; } while (++c<C); - log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C); + log2Amp(mode, st->start, st->end, bandE, oldBandE, C); } seed = st->rng; for (c=0;c<C;c++) { for (i=0;i<(st->mode->eBands[st->start]<<LM);i++) X[c*N+i] = 0; - for (i=st->start;i<st->mode->effEBands;i++) + for (i=st->start;i<mode->effEBands;i++) { int j; int boffs; int blen; - boffs = N*c+(st->mode->eBands[i]<<LM); - blen = (st->mode->eBands[i+1]-st->mode->eBands[i])<<LM; + boffs = N*c+(eBands[i]<<LM); + blen = (eBands[i+1]-eBands[i])<<LM; for (j=0;j<blen;j++) { seed = celt_lcg_rand(seed); @@ -2111,22 +2130,27 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R } st->rng = seed; - denormalise_bands(st->mode, X, freq, bandE, st->mode->effEBands, C, 1<<LM); + denormalise_bands(mode, X, freq, bandE, mode->effEBands, C, 1<<LM); c=0; do for (i=0;i<st->mode->eBands[st->start]<<LM;i++) freq[c*N+i] = 0; while (++c<C); c=0; do { - int bound = st->mode->eBands[effEnd]<<LM; + int bound = eBands[effEnd]<<LM; if (st->downsample!=1) bound = IMIN(bound, N/st->downsample); for (i=bound;i<N;i++) freq[c*N+i] = 0; } while (++c<C); - compute_inv_mdcts(st->mode, 0, freq, out_syn, overlap_mem, C, LM); + c=0; do { + OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap); + } while (++c<C); + compute_inv_mdcts(mode, 0, freq, out_syn, overlap_mem, C, LM); } else { /* Pitch-based PLC */ + VARDECL(opus_val32, etmp); + if (st->loss_count == 0) { opus_val16 pitch_buf[DECODE_BUFFER_SIZE>>1]; @@ -2144,23 +2168,26 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R fade = QCONST16(.8f,15); } + ALLOC(etmp, overlap, opus_val32); c=0; do { - VARDECL(opus_val32, e); opus_val16 exc[MAX_PERIOD]; opus_val32 ac[LPC_ORDER+1]; - opus_val16 decay = 1; + opus_val16 decay; + opus_val16 attenuation; opus_val32 S1=0; opus_val16 mem[LPC_ORDER]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + opus_val32 *e = out_syn[c]; - ALLOC(e, MAX_PERIOD+2*st->mode->overlap, opus_val32); offset = MAX_PERIOD-pitch_index; for (i=0;i<MAX_PERIOD;i++) exc[i] = ROUND16(out_mem[c][i], SIG_SHIFT); + /* Compute LPC coefficients for the last MAX_PERIOD samples before the loss so we can + work in the excitation-filter domain */ if (st->loss_count == 0) { - _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap, + _celt_autocorr(exc, ac, mode->window, overlap, LPC_ORDER, MAX_PERIOD); /* Noise floor -40 dB */ @@ -2182,11 +2209,15 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER); } + /* Samples just before the beginning of exc */ for (i=0;i<LPC_ORDER;i++) - mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT); + mem[i] = ROUND16(out_mem[c][-1-i], SIG_SHIFT); + /* Compute the excitation for MAX_PERIOD samples before the loss */ celt_fir(exc, lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem); - /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/ - /* Check if the waveform is decaying (and if so how fast) */ + + /* Check if the waveform is decaying (and if so how fast) + We do this to avoid adding energy when concealing in a segment + with decaying energy */ { opus_val32 E1=1, E2=1; int period; @@ -2202,30 +2233,43 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R if (E1 > E2) E1 = E2; decay = celt_sqrt(frac_div32(SHR32(E1,1),E2)); + attenuation = decay; } - /* Copy excitation, taking decay into account */ - for (i=0;i<len+st->mode->overlap;i++) + /* Move memory one frame to the left */ + OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap); + + /* Extrapolate excitation with the right period, taking decay into account */ + for (i=0;i<len;i++) { opus_val16 tmp; if (offset+i >= MAX_PERIOD) { offset -= pitch_index; - decay = MULT16_16_Q15(decay, decay); + attenuation = MULT16_16_Q15(attenuation, decay); } - e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT); - tmp = ROUND16(out_mem[c][offset+i],SIG_SHIFT); + e[i] = SHL32(EXTEND32(MULT16_16_Q15(attenuation, exc[offset+i])), SIG_SHIFT); + /* Compute the energy of the previously decoded signal whose + excitation we're copying */ + tmp = ROUND16(out_mem[c][-N+offset+i],SIG_SHIFT); S1 += SHR32(MULT16_16(tmp,tmp),8); } + + /* Copy the last decoded samples (prior to the overlap region) to + synthesis filter memory so we can have a continuous signal. */ for (i=0;i<LPC_ORDER;i++) - mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT); - for (i=0;i<len+st->mode->overlap;i++) + mem[i] = ROUND16(out_mem[c][MAX_PERIOD-N-1-i], SIG_SHIFT); + /* Apply the fading if not the first loss */ + for (i=0;i<len;i++) e[i] = MULT16_32_Q15(fade, e[i]); - celt_iir(e, lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem); + /* Synthesis filter -- back in the signal domain */ + celt_iir(e, lpc+c*LPC_ORDER, e, len, LPC_ORDER, mem); + /* Check if the synthesis energy is higher than expected, which can + happen with the signal changes during our window. If so, attenuate. */ { opus_val32 S2=0; - for (i=0;i<len+overlap;i++) + for (i=0;i<len;i++) { opus_val16 tmp = ROUND16(e[i],SIG_SHIFT); S2 += SHR32(MULT16_16(tmp,tmp),8); @@ -2234,51 +2278,45 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R #ifdef FIXED_POINT if (!(S1 > SHR32(S2,2))) #else - /* Float test is written this way to catch NaNs at the same time */ - if (!(S1 > 0.2f*S2)) + /* Float test is written this way to catch NaNs at the same time */ + if (!(S1 > 0.2f*S2)) #endif + { + for (i=0;i<len;i++) + e[i] = 0; + } else if (S1 < S2) + { + opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1)); + for (i=0;i<overlap;i++) { - for (i=0;i<len+overlap;i++) - e[i] = 0; - } else if (S1 < S2) - { - opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1)); - for (i=0;i<len+overlap;i++) - e[i] = MULT16_32_Q15(ratio, e[i]); + opus_val16 tmp_g = Q15ONE - MULT16_16_Q15(mode->window[i], Q15ONE-ratio); + e[i] = MULT16_32_Q15(tmp_g, e[i]); } + for (i=overlap;i<len;i++) + e[i] = MULT16_32_Q15(ratio, e[i]); + } } - /* Apply post-filter to the MDCT overlap of the previous frame */ - comb_filter(out_mem[c]+MAX_PERIOD, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, - st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset, + /* Apply pre-filter to the MDCT overlap for the next frame because the + post-filter will be re-applied in the decoder after the MDCT overlap */ + comb_filter(etmp, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, + -st->postfilter_gain, -st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset, NULL, 0); - for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++) - out_mem[c][i] = out_mem[c][N+i]; - - /* Apply TDAC to the concealed audio so that it blends with the - previous and next frames */ + /* Simulate TDAC on the concealed audio so that it blends with the + MDCT of next frames. */ for (i=0;i<overlap/2;i++) { opus_val32 tmp; - tmp = MULT16_32_Q15(st->mode->window[i], e[N+overlap-1-i]) + - MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]); - out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp); - out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(st->mode->window[i], tmp); + tmp = MULT16_32_Q15(mode->window[i], etmp[overlap-1-i]) + + MULT16_32_Q15(mode->window[overlap-i-1], etmp[i ]); + out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(mode->window[overlap-i-1], tmp); + out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(mode->window[i], tmp); } - for (i=0;i<N;i++) - out_mem[c][MAX_PERIOD-N+i] = e[i]; - - /* Apply pre-filter to the MDCT overlap for the next frame (post-filter will be applied then) */ - comb_filter(e, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, - -st->postfilter_gain, -st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset, - NULL, 0); - for (i=0;i<overlap;i++) - out_mem[c][MAX_PERIOD+i] = e[i]; } while (++c<C); } - deemphasis(out_syn, pcm, N, C, st->downsample, st->mode->preemph, st->preemph_memD); + deemphasis(out_syn, pcm, N, C, st->downsample, mode->preemph, st->preemph_memD); st->loss_count++; @@ -2387,6 +2425,13 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat if (effEnd > st->mode->effEBands) effEnd = st->mode->effEBands; + if (data == NULL || len<=1) + { + celt_decode_lost(st, pcm, N, LM); + RESTORE_STACK; + return frame_size/st->downsample; + } + ALLOC(freq, IMAX(CC,C)*N, celt_sig); /**< Interleaved signal MDCTs */ ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ ALLOC(bandE, st->mode->nbEBands*C, celt_ener); @@ -2399,13 +2444,6 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat X[c*N+i] = 0; while (++c<C); - if (data == NULL || len<=1) - { - celt_decode_lost(st, pcm, N, LM); - RESTORE_STACK; - return frame_size/st->downsample; - } - if (dec == NULL) { ec_dec_init(&_dec,(unsigned char*)data,len); @@ -2800,7 +2838,6 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...) *value = st->postfilter_period; } break; -#ifdef OPUS_BUILD case CELT_GET_MODE_REQUEST: { const CELTMode ** value = va_arg(ap, const CELTMode**); @@ -2823,7 +2860,6 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...) *value=st->rng; } break; -#endif default: goto bad_request; } diff --git a/celt/cwrs.c b/celt/cwrs.c index ac81a7e..8edc919 100644 --- a/celt/cwrs.c +++ b/celt/cwrs.c @@ -337,7 +337,7 @@ static opus_uint32 ncwrs_urow(unsigned _n,unsigned _k,opus_uint32 *_u){ but _k isn't tested here because k<=52 for n=7*/ if(_n<=6) #endif - { + { /*If _n==0, _u[0] should be 1 and the rest should be 0.*/ /*If _n==1, _u[i] should be 1 for i>1.*/ celt_assert(_n>=2); diff --git a/celt/ecintrin.h b/celt/ecintrin.h index 3dffa5f..be57dd4 100644 --- a/celt/ecintrin.h +++ b/celt/ecintrin.h @@ -48,7 +48,7 @@ /*Count leading zeros. This macro should only be used for implementing ec_ilog(), if it is defined. All other code should use EC_ILOG() instead.*/ -#if defined(_MSC_VER) +#if defined(_MSC_VER) && (_MSC_VER >= 1400) # include <intrin.h> /*In _DEBUG mode this is not an intrinsic by default.*/ # pragma intrinsic(_BitScanReverse) diff --git a/celt/entcode.c b/celt/entcode.c index 02ac690..fa5d7c7 100644 --- a/celt/entcode.c +++ b/celt/entcode.c @@ -33,6 +33,11 @@ #include "arch.h" #if !defined(EC_CLZ) +/*This is a fallback for systems where we don't know how to access + a BSR or CLZ instruction (see ecintrin.h). + If you are optimizing Opus on a new platform and it has a native CLZ or + BZR (e.g. cell, MIPS, x86, etc) then making it available to Opus will be + an easy performance win.*/ int ec_ilog(opus_uint32 _v){ /*On a Pentium M, this branchless version tested as the fastest on 1,000,000,000 random 32-bit integers, edging out a similar version with diff --git a/celt/pitch.c b/celt/pitch.c index c2f08ec..ca0f523 100644 --- a/celt/pitch.c +++ b/celt/pitch.c @@ -77,7 +77,7 @@ static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len, #ifndef FIXED_POINT /* Considering the range of xcorr16, this should avoid both underflows and overflows (inf) when squaring xcorr16 */ - xcorr16 *= 1e-12; + xcorr16 *= 1e-12f; #endif num = MULT16_16_Q15(xcorr16,xcorr16); if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy)) diff --git a/celt/quant_bands.c b/celt/quant_bands.c index b1d4eb1..66f1f5f 100644 --- a/celt/quant_bands.c +++ b/celt/quant_bands.c @@ -283,12 +283,15 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, /* Encode the global flags using a simple probability model (first symbols in the stream) */ + max_decay = QCONST16(16.f,DB_SHIFT); + if (end-start>10) + { #ifdef FIXED_POINT - max_decay = MIN32(QCONST16(16.f,DB_SHIFT), SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3)); + max_decay = MIN32(max_decay, SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3)); #else - max_decay = MIN32(16.f, .125f*nbAvailableBytes); + max_decay = MIN32(max_decay, .125f*nbAvailableBytes); #endif - + } enc_start_state = *enc; ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16); diff --git a/celt/rate.c b/celt/rate.c index 32fe9ac..4e96787 100644 --- a/celt/rate.c +++ b/celt/rate.c @@ -84,7 +84,7 @@ void compute_pulse_cache(CELTMode *m, int LM) unsigned char *bits; unsigned char *cap; - cindex = opus_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2)); + cindex = (opus_int16 *)opus_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2)); cache->index = cindex; /* Scan for all unique band sizes */ @@ -124,7 +124,7 @@ void compute_pulse_cache(CELTMode *m, int LM) } } } - bits = opus_alloc(sizeof(unsigned char)*curr); + bits = (unsigned char *)opus_alloc(sizeof(unsigned char)*curr); cache->bits = bits; cache->size = curr; /* Compute the cache for all unique sizes */ @@ -140,7 +140,7 @@ void compute_pulse_cache(CELTMode *m, int LM) /* Compute the maximum rate for each band at which we'll reliably use as many bits as we ask for. */ - cache->caps = cap = opus_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands); + cache->caps = cap = (unsigned char *)opus_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands); for (i=0;i<=LM;i++) { for (C=1;C<=2;C++) @@ -259,7 +259,7 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int int alloc_floor; opus_int32 left, percoeff; int done; - int balance; + opus_int32 balance; SAVE_STACK; alloc_floor = C<<BITRES; @@ -353,7 +353,7 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int #ifdef FUZZING if ((rand()&0x1) == 0) #else - if (band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4) + if (codedBands<=start+2 || band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4) #endif { ec_enc_bit_logp(ec, 1, 1); @@ -432,17 +432,17 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int int N0, N, den; int offset; int NClogN; - int excess; + opus_int32 excess, bit; celt_assert(bits[j] >= 0); N0 = m->eBands[j+1]-m->eBands[j]; N=N0<<LM; - bits[j] += balance; + bit = (opus_int32)bits[j]+balance; if (N>1) { - excess = IMAX(bits[j]-cap[j],0); - bits[j] -= excess; + excess = MAX32(bit-cap[j],0); + bits[j] = bit-excess; /* Compensate for the extra DoF in stereo */ den=(C*N+ ((C==2 && N>2 && !*dual_stereo && j<*intensity) ? 1 : 0)); @@ -483,8 +483,8 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int } else { /* For N=1, all bits go to fine energy except for a single sign bit */ - excess = IMAX(0,bits[j]-(C<<BITRES)); - bits[j] -= excess; + excess = MAX32(0,bit-(C<<BITRES)); + bits[j] = bit-excess; ebits[j] = 0; fine_priority[j] = 1; } diff --git a/celt/tests/test_unit_cwrs32.c b/celt/tests/test_unit_cwrs32.c index 905714e..4695f2d 100644 --- a/celt/tests/test_unit_cwrs32.c +++ b/celt/tests/test_unit_cwrs32.c @@ -1,3 +1,31 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation, + Gregory Maxwell + Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */ +/* + 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 diff --git a/celt/tests/test_unit_dft.c b/celt/tests/test_unit_dft.c index 5ca38ed..7ff0be0 100644 --- a/celt/tests/test_unit_dft.c +++ b/celt/tests/test_unit_dft.c @@ -1,3 +1,30 @@ +/* Copyright (c) 2008 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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 diff --git a/celt/tests/test_unit_entropy.c b/celt/tests/test_unit_entropy.c index 5cba4fe..bd83986 100644 --- a/celt/tests/test_unit_entropy.c +++ b/celt/tests/test_unit_entropy.c @@ -1,3 +1,31 @@ +/* Copyright (c) 2007-2011 Xiph.Org Foundation, Mozilla Corporation, + Gregory Maxwell + Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */ +/* + 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 diff --git a/celt/tests/test_unit_laplace.c b/celt/tests/test_unit_laplace.c index 5c80c19..b0f5935 100644 --- a/celt/tests/test_unit_laplace.c +++ b/celt/tests/test_unit_laplace.c @@ -1,3 +1,30 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation + Written by Jean-Marc Valin and Timothy B. Terriberry */ +/* + 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 diff --git a/celt/tests/test_unit_mathops.c b/celt/tests/test_unit_mathops.c index ea0af49..c11f0ad 100644 --- a/celt/tests/test_unit_mathops.c +++ b/celt/tests/test_unit_mathops.c @@ -1,3 +1,31 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation, + Gregory Maxwell + Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */ +/* + 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 diff --git a/celt/tests/test_unit_mdct.c b/celt/tests/test_unit_mdct.c index 0de3d54..f8fb9ac 100644 --- a/celt/tests/test_unit_mdct.c +++ b/celt/tests/test_unit_mdct.c @@ -1,3 +1,30 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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 diff --git a/celt/tests/test_unit_rotation.c b/celt/tests/test_unit_rotation.c index 29082b6..ce5f096 100644 --- a/celt/tests/test_unit_rotation.c +++ b/celt/tests/test_unit_rotation.c @@ -1,3 +1,30 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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 diff --git a/celt/tests/test_unit_types.c b/celt/tests/test_unit_types.c index 1c3357e..67a0fb8 100644 --- a/celt/tests/test_unit_types.c +++ b/celt/tests/test_unit_types.c @@ -1,3 +1,30 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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 diff --git a/celt_headers.mk b/celt_headers.mk new file mode 100644 index 0000000..f89d66a --- /dev/null +++ b/celt_headers.mk @@ -0,0 +1,31 @@ +CELT_HEAD = \ +celt/arch.h \ +celt/bands.h \ +celt/celt.h \ +include/opus_types.h \ +include/opus_defines.h \ +include/opus_custom.h \ +celt/cwrs.h \ +celt/ecintrin.h \ +celt/entcode.h \ +celt/entdec.h \ +celt/entenc.h \ +celt/fixed_debug.h \ +celt/fixed_generic.h \ +celt/float_cast.h \ +celt/_kiss_fft_guts.h \ +celt/kiss_fft.h \ +celt/laplace.h \ +celt/mathops.h \ +celt/mdct.h \ +celt/mfrngcod.h \ +celt/modes.h \ +celt/os_support.h \ +celt/pitch.h \ +celt/celt_lpc.h \ +celt/quant_bands.h \ +celt/rate.h \ +celt/stack_alloc.h \ +celt/vq.h \ +celt/static_modes_float.h \ +celt/static_modes_fixed.h diff --git a/celt_sources.mk b/celt_sources.mk new file mode 100644 index 0000000..6f0a90e --- /dev/null +++ b/celt_sources.mk @@ -0,0 +1,16 @@ +CELT_SOURCES = celt/bands.c \ +celt/celt.c \ +celt/cwrs.c \ +celt/entcode.c \ +celt/entdec.c \ +celt/entenc.c \ +celt/kiss_fft.c \ +celt/laplace.c \ +celt/mathops.c \ +celt/mdct.c \ +celt/modes.c \ +celt/pitch.c \ +celt/celt_lpc.c \ +celt/quant_bands.c \ +celt/rate.c \ +celt/vq.c @@ -1,7 +1,7 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-01-04.17; # UTC +scriptversion=2012-03-05.13; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free # Software Foundation, Inc. @@ -79,6 +79,48 @@ func_file_conv () esac } +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () @@ -109,43 +151,34 @@ func_cl_wrapper () ;; esac ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; -l*) - lib=${1#-l} - found=no - save_IFS=$IFS - IFS=';' - for dir in $lib_path $LIB - do - IFS=$save_IFS - if $shared && test -f "$dir/$lib.dll.lib"; then - found=yes - set x "$@" "$dir/$lib.dll.lib" - break - fi - if test -f "$dir/$lib.lib"; then - found=yes - set x "$@" "$dir/$lib.lib" - break - fi - done - IFS=$save_IFS - - test "$found" != yes && set x "$@" "$lib.lib" + func_cl_dashl "${1#-l}" + set x "$@" "$lib" shift ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; -L*) - func_file_conv "${1#-L}" - if test -z "$lib_path"; then - lib_path=$file - else - lib_path="$lib_path;$file" - fi - linker_opts="$linker_opts -LIBPATH:$file" + func_cl_dashL "${1#-L}" ;; -static) shared=false diff --git a/config.guess b/config.guess index 49ba16f..d622a44 100755 --- a/config.guess +++ b/config.guess @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. -timestamp='2012-01-01' +timestamp='2012-02-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -17,9 +17,7 @@ timestamp='2012-01-01' # 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., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see <http://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -863,6 +861,13 @@ EOF i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -1320,6 +1325,9 @@ EOF i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 diff --git a/config.h.in b/config.h.in index bf3b61a..a5e9503 100644 --- a/config.h.in +++ b/config.h.in @@ -1,8 +1,5 @@ /* config.h.in. Generated from configure.ac by autoheader. */ -/* Define if building universal (internal helper macro) */ -#undef AC_APPLE_UNIVERSAL_BUILD - /* Custom modes */ #undef CUSTOM_MODES @@ -15,9 +12,6 @@ /* Compile as fixed-point (for machines without a fast enough FPU) */ #undef FIXED_POINT -/* Compile as floating-point (for machines with a fast enough FPU) */ -#undef FLOATING_POINT - /* Float approximations */ #undef FLOAT_APPROX @@ -121,18 +115,6 @@ /* Use C99 variable-size arrays */ #undef VAR_ARRAYS -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - /* Define to empty if `const' does not conform to ANSI C. */ #undef const @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. -timestamp='2012-01-01' +timestamp='2012-02-10' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -21,9 +21,7 @@ timestamp='2012-01-01' # 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., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see <http://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -132,6 +130,10 @@ case $maybe_os in os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] @@ -247,6 +249,7 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ + | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ @@ -319,7 +322,7 @@ case $basic_machine in c6x) basic_machine=tic6x-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12 | picochip) + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; @@ -332,7 +335,10 @@ case $basic_machine in strongarm | thumb | xscale) basic_machine=arm-unknown ;; - + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; xscaleeb) basic_machine=armeb-unknown ;; @@ -355,6 +361,7 @@ case $basic_machine in # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ + | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ @@ -613,6 +613,8 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS +PC_LIBM +PC_BUILD CUSTOM_MODES_FALSE CUSTOM_MODES_TRUE FIXED_POINT_FALSE @@ -1393,7 +1395,7 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: `make V=1') --disable-silent-rules verbose build output (undo: `make V=0') - --enable-maintainer-mode enable make rules and dependencies not useful + --disable-maintainer-mode disable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] @@ -2484,9 +2486,9 @@ _ACEOF # For libtool. -OPUS_LT_CURRENT=2 +OPUS_LT_CURRENT=3 OPUS_LT_REVISION=0 -OPUS_LT_AGE=2 +OPUS_LT_AGE=3 @@ -2997,7 +2999,7 @@ $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else - USE_MAINTAINER_MODE=no + USE_MAINTAINER_MODE=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 @@ -11887,230 +11889,6 @@ if test "x$ac_cv_prog_cc_c99" != xno; then : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 -$as_echo_n "checking whether byte ordering is bigendian... " >&6; } -if ${ac_cv_c_bigendian+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_c_bigendian=unknown - # See if we're dealing with a universal compiler. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifndef __APPLE_CC__ - not a universal capable compiler - #endif - typedef int dummy; - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - - # Check for potential -arch flags. It is not universal unless - # there are at least two -arch flags with different values. - ac_arch= - ac_prev= - for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do - if test -n "$ac_prev"; then - case $ac_word in - i?86 | x86_64 | ppc | ppc64) - if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then - ac_arch=$ac_word - else - ac_cv_c_bigendian=universal - break - fi - ;; - esac - ac_prev= - elif test "x$ac_word" = "x-arch"; then - ac_prev=arch - fi - done -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - if test $ac_cv_c_bigendian = unknown; then - # See if sys/param.h defines the BYTE_ORDER macro. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <sys/types.h> - #include <sys/param.h> - -int -main () -{ -#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ - && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ - && LITTLE_ENDIAN) - bogus endian macros - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - # It does; now see whether it defined to BIG_ENDIAN or not. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <sys/types.h> - #include <sys/param.h> - -int -main () -{ -#if BYTE_ORDER != BIG_ENDIAN - not big endian - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_bigendian=yes -else - ac_cv_c_bigendian=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - if test $ac_cv_c_bigendian = unknown; then - # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <limits.h> - -int -main () -{ -#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) - bogus endian macros - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - # It does; now see whether it defined to _BIG_ENDIAN or not. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <limits.h> - -int -main () -{ -#ifndef _BIG_ENDIAN - not big endian - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_bigendian=yes -else - ac_cv_c_bigendian=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - if test $ac_cv_c_bigendian = unknown; then - # Compile a test program. - if test "$cross_compiling" = yes; then : - # Try to guess by grepping values from an object file. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -short int ascii_mm[] = - { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; - short int ascii_ii[] = - { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; - int use_ascii (int i) { - return ascii_mm[i] + ascii_ii[i]; - } - short int ebcdic_ii[] = - { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; - short int ebcdic_mm[] = - { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; - int use_ebcdic (int i) { - return ebcdic_mm[i] + ebcdic_ii[i]; - } - extern int foo; - -int -main () -{ -return use_ascii (foo) == use_ebcdic (foo); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then - ac_cv_c_bigendian=yes - fi - if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then - if test "$ac_cv_c_bigendian" = unknown; then - ac_cv_c_bigendian=no - else - # finding both strings is unlikely to happen, but who knows? - ac_cv_c_bigendian=unknown - fi - fi -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ - - /* Are we little or big endian? From Harbison&Steele. */ - union - { - long int l; - char c[sizeof (long int)]; - } u; - u.l = 1; - return u.c[sizeof (long int) - 1] == 1; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_c_bigendian=no -else - ac_cv_c_bigendian=yes -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 -$as_echo "$ac_cv_c_bigendian" >&6; } - case $ac_cv_c_bigendian in #( - yes) - $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h -;; #( - no) - ;; #( - universal) - -$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h - - ;; #( - *) - as_fn_error $? "unknown endianness - presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : @@ -12428,15 +12206,7 @@ if test "${enable_fixed_point+set}" = set; then : $as_echo "#define FIXED_POINT 1" >>confdefs.h -else - -$as_echo "#define FLOATING_POINT /**/" >>confdefs.h - fi -else - -$as_echo "#define FLOATING_POINT /**/" >>confdefs.h - fi @@ -12820,8 +12590,24 @@ else fi +if test x$ac_enable_float = xyes; then + PC_BUILD="floating-point" + PC_LIBM=$LIBM +else + PC_BUILD="fixed-point" + PC_LIBM= +fi +if test x$ac_enable_custom_modes = xyes; then + PC_BUILD="${PC_BUILD}, custom modes" + PC_LIBM=$LIBM +fi + + + + ac_config_files="$ac_config_files Makefile opus.pc opus-uninstalled.pc doc/Makefile doc/Doxyfile" + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -12951,7 +12737,6 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi - if test -z "${HAVE_DOXYGEN_TRUE}" && test -z "${HAVE_DOXYGEN_FALSE}"; then as_fn_error $? "conditional \"HAVE_DOXYGEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 0773c37..6394e2e 100644 --- a/configure.ac +++ b/configure.ac @@ -53,16 +53,16 @@ AC_DEFINE_UNQUOTED([OPUS_VERSION], ["$OPUS_VERSION"], # For libtool. dnl Please update these for releases. -OPUS_LT_CURRENT=2 +OPUS_LT_CURRENT=3 OPUS_LT_REVISION=0 -OPUS_LT_AGE=2 +OPUS_LT_AGE=3 AC_SUBST(OPUS_LT_CURRENT) AC_SUBST(OPUS_LT_REVISION) AC_SUBST(OPUS_LT_AGE) AM_INIT_AUTOMAKE($PACKAGE, $VERSION, no-define) -AM_MAINTAINER_MODE +AM_MAINTAINER_MODE([enable]) AC_CANONICAL_HOST AC_MINGW32 @@ -70,7 +70,6 @@ AM_PROG_LIBTOOL AM_PROG_CC_C_O AC_PROG_CC_C99 -AC_C_BIGENDIAN AC_C_CONST AC_C_INLINE @@ -159,10 +158,7 @@ AC_ARG_ENABLE(fixed-point, [ --enable-fixed-point compile without floatin ac_enable_fixed="yes"; ac_enable_float="no"; AC_DEFINE([FIXED_POINT], [1], [Compile as fixed-point (for machines without a fast enough FPU)]) -else - AC_DEFINE([FLOATING_POINT], , [Compile as floating-point (for machines with a fast enough FPU)]) -fi], -AC_DEFINE([FLOATING_POINT], , [Compile as floating-point (for machines with a fast enough FPU)])) +fi]) ac_enable_fixed_debug="no" AC_ARG_ENABLE(fixed-point-debug, [ --enable-fixed-point-debug debug fixed-point implementation], @@ -278,8 +274,27 @@ AC_SUBST(SIZE32) AM_CONDITIONAL([FIXED_POINT], [test x$ac_enable_fixed = xyes]) AM_CONDITIONAL([CUSTOM_MODES], [test x$ac_enable_custom_modes = xyes]) -AC_OUTPUT([Makefile opus.pc opus-uninstalled.pc - doc/Makefile doc/Doxyfile]) +dnl subsitutions for the pkg-config files +if test x$ac_enable_float = xyes; then + PC_BUILD="floating-point" + PC_LIBM=$LIBM +else + PC_BUILD="fixed-point" + PC_LIBM= +fi +dnl opus_custom requires libm as well +if test x$ac_enable_custom_modes = xyes; then + PC_BUILD="${PC_BUILD}, custom modes" + PC_LIBM=$LIBM +fi +AC_SUBST([PC_BUILD]) +AC_SUBST([PC_LIBM]) + + +AC_CONFIG_FILES([Makefile opus.pc opus-uninstalled.pc + doc/Makefile doc/Doxyfile]) + +AC_OUTPUT AC_MSG_RESULT([ ------------------------------------------------------------------------ @@ -1,10 +1,10 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2011-12-04.11; # UTC +scriptversion=2012-03-27.16; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, -# 2011 Free Software Foundation, Inc. +# 2011, 2012 Free Software Foundation, Inc. # 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 @@ -28,7 +28,7 @@ scriptversion=2011-12-04.11; # UTC case $1 in '') - echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) @@ -40,8 +40,8 @@ as side-effects. Environment variables: depmode Dependency tracking mode. - source Source file read by `PROGRAMS ARGS'. - object Object file output by `PROGRAMS ARGS'. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. @@ -57,6 +57,12 @@ EOF ;; esac +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' + if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 @@ -102,6 +108,12 @@ if test "$depmode" = msvc7msys; then depmode=msvc7 fi +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what @@ -156,15 +168,14 @@ gcc) ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. +## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory + tr ' ' "$nl" < "$tmpdepfile" | +## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. @@ -203,18 +214,15 @@ sgi) # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the + # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ + tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> "$depfile" + tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ + tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else @@ -226,10 +234,17 @@ sgi) rm -f "$tmpdepfile" ;; +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts `$object:' at the + # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` @@ -259,12 +274,11 @@ aix) test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then - # Each line is of the form `foo.o: dependent.h'. + # Each line is of the form 'foo.o: dependent.h'. # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. + # '$object: dependent.h' and one to simply 'dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile @@ -275,23 +289,26 @@ aix) ;; icc) - # Intel's C compiler understands `-MD -MF file'. However on - # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. + # However on + # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h - # which is wrong. We want: + # which is wrong. We want # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using \ : + # and will wrap long lines using '\': # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... - + # tcc 0.9.26 (FIXME still under development at the moment of writing) + # will emit a similar output, but also prepend the continuation lines + # with horizontal tabulation characters. "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : @@ -300,15 +317,21 @@ icc) exit $stat fi rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Each line is of the form 'foo.o: dependent.h', + # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | - sed -e 's/$/ :/' >> "$depfile" + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ + < "$tmpdepfile" > "$depfile" + sed ' + s/[ '"$tab"'][ '"$tab"']*/ /g + s/^ *// + s/ *\\*$// + s/^[^:]*: *// + /^$/d + /:$/d + s/$/ :/ + ' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; @@ -344,7 +367,7 @@ hp2) done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" - # Add `dependent.h:' lines. + # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// @@ -359,9 +382,9 @@ hp2) tru64) # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. + # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= @@ -407,8 +430,7 @@ tru64) done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi @@ -443,11 +465,11 @@ msvc7) p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g -s/\(.*\)/ \1 \\/p +s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { - s/.*/ / + s/.*/'"$tab"'/ G p }' >> "$depfile" @@ -478,7 +500,7 @@ dashmstdout) shift fi - # Remove `-o $object'. + # Remove '-o $object'. IFS=" " for arg do @@ -498,15 +520,14 @@ dashmstdout) done test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for `:' + # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: - # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | - sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ + tr ' ' "$nl" < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" @@ -562,8 +583,7 @@ makedepend) # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ + sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" @@ -583,7 +603,7 @@ cpp) shift fi - # Remove `-o $object'. + # Remove '-o $object'. IFS=" " for arg do @@ -652,8 +672,8 @@ msvisualcpp) sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 328a06e..7f5f7dc 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -835,7 +835,7 @@ HTML_FILE_EXTENSION = .html # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. -# It is adviced to generate a default header using "doxygen -w html +# It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW! diff --git a/doc/Makefile.am b/doc/Makefile.am index ba6f64c..cf5908a 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -22,7 +22,8 @@ doxygen-build.stamp: Doxyfile $(DOCINPUTS) install-data-local: for f in `find html -type f \! -name "installdox"`; do \ - $(INSTALL_DATA) -D $$f $(DESTDIR)$(docdir)/$$f; \ + $(INSTALL) -d $(DESTDIR)$(docdir)/html/search; \ + $(INSTALL_DATA) $$f $(DESTDIR)$(docdir)/$$f; \ done $(INSTALL) -d $(DESTDIR)$(mandir)/man3 diff --git a/doc/Makefile.in b/doc/Makefile.in index a40d72c..1eb4436 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11.3 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -15,6 +15,23 @@ @SET_MAKE@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -52,6 +69,11 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ SOURCES = DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -116,6 +138,8 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PC_BUILD = @PC_BUILD@ +PC_LIBM = @PC_LIBM@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -393,7 +417,8 @@ uninstall-am: uninstall-local @HAVE_DOXYGEN_TRUE@install-data-local: @HAVE_DOXYGEN_TRUE@ for f in `find html -type f \! -name "installdox"`; do \ -@HAVE_DOXYGEN_TRUE@ $(INSTALL_DATA) -D $$f $(DESTDIR)$(docdir)/$$f; \ +@HAVE_DOXYGEN_TRUE@ $(INSTALL) -d $(DESTDIR)$(docdir)/html/search; \ +@HAVE_DOXYGEN_TRUE@ $(INSTALL_DATA) $$f $(DESTDIR)$(docdir)/$$f; \ @HAVE_DOXYGEN_TRUE@ done @HAVE_DOXYGEN_TRUE@ $(INSTALL) -d $(DESTDIR)$(mandir)/man3 diff --git a/include/opus.h b/include/opus.h index a1f0156..847a07c 100644 --- a/include/opus.h +++ b/include/opus.h @@ -67,6 +67,7 @@ extern "C" { * @li @ref opus_encoder * @li @ref opus_decoder * @li @ref opus_repacketizer + * @li @ref opus_multistream * @li @ref opus_libinfo * @li @ref opus_custom */ @@ -135,10 +136,11 @@ extern "C" { * <li>audio_frame is the audio data in opus_int16 (or float for opus_encode_float())</li> * <li>frame_size is the duration of the frame in samples (per channel)</li> * <li>packet is the byte array to which the compressed data is written</li> - * <li>max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended)</li> + * <li>max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended). + * Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.</li> * </ul> * - * opus_encode() and opus_encode_frame() return the number of bytes actually written to the packet. + * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet. * The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value * is 1 byte, then the packet does not need to be transmitted (DTX). * @@ -161,6 +163,11 @@ extern "C" { */ typedef struct OpusEncoder OpusEncoder; +/** Gets the size of an <code>OpusEncoder</code> structure. + * @param[in] channels <tt>int</tt>: Number of channels. + * This must be 1 or 2. + * @returns The size in bytes. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels); /** @@ -188,11 +195,13 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels); * * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution). * @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz) - * @param [in] channels <tt>int</tt>: Number of channels (1/2) in input signal + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal * @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY) * @param [out] error <tt>int*</tt>: @ref opus_errorcodes * @note Regardless of the sampling rate and number channels selected, the Opus encoder - * can switch to a lower audio audio bandwidth or number of channels if the bitrate + * can switch to a lower audio bandwidth or number of channels if the bitrate * selected is too low. This also means that it is safe to always use 48 kHz stereo input * and let the encoder optimize the encoding. */ @@ -204,15 +213,17 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create( ); /** Initializes a previously allocated encoder state - * The memory pointed to by st must be the size returned by opus_encoder_get_size. + * The memory pointed to by st must be at least the size returned by opus_encoder_get_size(). * This is intended for applications which use their own allocator instead of malloc. * @see opus_encoder_create(),opus_encoder_get_size() - * To reset a previously initialized state use the OPUS_RESET_STATE CTL. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. * @param [in] st <tt>OpusEncoder*</tt>: Encoder state * @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz) - * @param [in] channels <tt>int</tt>: Number of channels (1/2) in input signal + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal * @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY) - * @retval OPUS_OK Success or @ref opus_errorcodes + * @retval #OPUS_OK Success or @ref opus_errorcodes */ OPUS_EXPORT int opus_encoder_init( OpusEncoder *st, @@ -222,16 +233,32 @@ OPUS_EXPORT int opus_encoder_init( ) OPUS_ARG_NONNULL(1); /** Encodes an Opus frame. - * The passed frame_size must an opus frame size for the encoder's sampling rate. - * For example, at 48kHz the permitted values are 120, 240, 480, 960, 1920, and 2880. - * Passing in a duration of less than 10ms (480 samples at 48kHz) will - * prevent the encoder from using the LPC or hybrid modes. * @param [in] st <tt>OpusEncoder*</tt>: Encoder state * @param [in] pcm <tt>opus_int16*</tt>: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16) - * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal - * @param [out] data <tt>char*</tt>: Output payload (at least max_data_bytes long) - * @param [in] max_data_bytes <tt>opus_int32</tt>: Allocated memory for payload; don't use for controlling bitrate - * @returns length of the data payload (in bytes) or @ref opus_errorcodes + * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the + * input signal. + * This must be an Opus frame size for + * the encoder's sampling rate. + * For example, at 48 kHz the permitted + * values are 120, 240, 480, 960, 1920, + * and 2880. + * Passing in a duration of less than + * 10 ms (480 samples at 48 kHz) will + * prevent the encoder from using the LPC + * or hybrid modes. + * @param [out] data <tt>unsigned char*</tt>: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode( OpusEncoder *st, @@ -242,10 +269,6 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode( ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); /** Encodes an Opus frame from floating point input. - * The passed frame_size must an opus frame size for the encoder's sampling rate. - * For example, at 48kHz the permitted values are 120, 240, 480, 960, 1920, and 2880. - * Passing in a duration of less than 10ms (480 samples at 48kHz) will - * prevent the encoder from using the LPC or hybrid modes. * @param [in] st <tt>OpusEncoder*</tt>: Encoder state * @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0. * Samples with a range beyond +/-1.0 are supported but will @@ -253,10 +276,30 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode( * only be used if it is known that the far end supports * extended dynamic range. * length is frame_size*channels*sizeof(float) - * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal - * @param [out] data <tt>char*</tt>: Output payload (at least max_data_bytes long) - * @param [in] max_data_bytes <tt>opus_int32</tt>: Allocated memory for payload; don't use for controlling bitrate - * @returns length of the data payload (in bytes) or @ref opus_errorcodes + * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the + * input signal. + * This must be an Opus frame size for + * the encoder's sampling rate. + * For example, at 48 kHz the permitted + * values are 120, 240, 480, 960, 1920, + * and 2880. + * Passing in a duration of less than + * 10 ms (480 samples at 48 kHz) will + * prevent the encoder from using the LPC + * or hybrid modes. + * @param [out] data <tt>unsigned char*</tt>: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float( OpusEncoder *st, @@ -266,7 +309,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float( opus_int32 max_data_bytes ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); -/** Frees an OpusEncoder allocated by opus_encoder_create. +/** Frees an <code>OpusEncoder</code> allocated by opus_encoder_create(). * @param[in] st <tt>OpusEncoder*</tt>: State to be freed. */ OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st); @@ -275,6 +318,11 @@ OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st); * * Generally the request and subsequent arguments are generated * by a convenience macro. + * @param st <tt>OpusEncoder*</tt>: Encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls or + * @ref opus_encoderctls. + * @see opus_genericctls * @see opus_encoderctls */ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); @@ -295,7 +343,7 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON * where * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000 * @li channels is the number of channels (1 or 2) - * @li error will hold the error code in case or failure (or OPUS_OK on success) + * @li error will hold the error code in case of failure (or #OPUS_OK on success) * @li the return value is a newly created decoder state to be used for decoding * * While opus_decoder_create() allocates memory for the state, it's also possible @@ -326,7 +374,7 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array * * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet. - * If that value is negative, then an error has occured. This can occur if the packet is corrupted or if the audio + * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio * buffer is too small to hold the decoded audio. * * Opus is a stateful codec with overlapping blocks and as a result Opus @@ -350,16 +398,19 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON */ typedef struct OpusDecoder OpusDecoder; -/** Gets the size of an OpusDecoder structure. - * @param [in] channels <tt>int</tt>: Number of channels - * @returns size +/** Gets the size of an <code>OpusDecoder</code> structure. + * @param [in] channels <tt>int</tt>: Number of channels. + * This must be 1 or 2. + * @returns The size in bytes. */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels); /** Allocates and initializes a decoder state. - * @param [in] Fs <tt>opus_int32</tt>: Sample rate to decode at (Hz) - * @param [in] channels <tt>int</tt>: Number of channels (1/2) to decode - * @param [out] error <tt>int*</tt>: OPUS_OK Success or @ref opus_errorcodes + * @param [in] Fs <tt>opus_int32</tt>: Sample rate to decode at (Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode + * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes * * Internally Opus stores data at 48000 Hz, so that should be the default * value for Fs. However, the decoder can efficiently decode to buffers @@ -376,13 +427,15 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create( ); /** Initializes a previously allocated decoder state. - * The state must be the size returned by opus_decoder_get_size. + * The state must be at least the size returned by opus_decoder_get_size(). * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size - * To reset a previously initialized state use the OPUS_RESET_STATE CTL. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. * @param [in] st <tt>OpusDecoder*</tt>: Decoder state. - * @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz) - * @param [in] channels <tt>int</tt>: Number of channels (1/2) to decode - * @retval OPUS_OK Success or @ref opus_errorcodes + * @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode + * @retval #OPUS_OK Success or @ref opus_errorcodes */ OPUS_EXPORT int opus_decoder_init( OpusDecoder *st, @@ -390,16 +443,20 @@ OPUS_EXPORT int opus_decoder_init( int channels ) OPUS_ARG_NONNULL(1); -/** Decode an Opus frame +/** Decode an Opus packet. * @param [in] st <tt>OpusDecoder*</tt>: Decoder state * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload* * @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length * is frame_size*channels*sizeof(opus_int16) - * @param [in] frame_size Number of samples per channel of available space in *pcm, - * if less than the maximum frame size (120ms) some frames can not be decoded - * @param [in] decode_fec <tt>int</tt>: Flag (0/1) to request that any in-band forward error correction data be - * decoded. If no such data is available the frame is decoded as if it were lost. + * @param [in] frame_size Number of samples per channel of available space in \a pcm. + * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will + * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), + * then frame_size needs to be exactly the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and + * FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms. + * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be + * decoded. If no such data is available, the frame is decoded as if it were lost. * @returns Number of decoded samples or @ref opus_errorcodes */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode( @@ -411,15 +468,19 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode( int decode_fec ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); -/** Decode an opus frame with floating point output +/** Decode an Opus packet with floating point output. * @param [in] st <tt>OpusDecoder*</tt>: Decoder state * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload * @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length * is frame_size*channels*sizeof(float) - * @param [in] frame_size Number of samples per channel of available space in *pcm, - * if less than the maximum frame size (120ms) some frames can not be decoded - * @param [in] decode_fec <tt>int</tt>: Flag (0/1) to request that any in-band forward error correction data be + * @param [in] frame_size Number of samples per channel of available space in \a pcm. + * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will + * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), + * then frame_size needs to be exactly the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and + * FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms. + * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be * decoded. If no such data is available the frame is decoded as if it were lost. * @returns Number of decoded samples or @ref opus_errorcodes */ @@ -436,11 +497,16 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float( * * Generally the request and subsequent arguments are generated * by a convenience macro. + * @param st <tt>OpusDecoder*</tt>: Decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls or + * @ref opus_decoderctls. * @see opus_genericctls + * @see opus_decoderctls */ OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); -/** Frees an OpusDecoder allocated by opus_decoder_create. +/** Frees an <code>OpusDecoder</code> allocated by opus_decoder_create(). * @param[in] st <tt>OpusDecoder*</tt>: State to be freed. */ OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st); @@ -479,10 +545,13 @@ OPUS_EXPORT int opus_packet_parse( OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1); /** Gets the number of samples per frame from an Opus packet. - * @param [in] data <tt>char*</tt>: Opus packet - * @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz - * @returns Number of samples per frame - * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + * @param [in] data <tt>char*</tt>: Opus packet. + * This must contain at least one byte of + * data. + * @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz. + * This must be a multiple of 400, or + * inaccurate results will be returned. + * @returns Number of samples per frame. */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1); @@ -502,6 +571,17 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsign OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1); /** Gets the number of samples of an Opus packet. + * @param [in] packet <tt>char*</tt>: Opus packet + * @param [in] len <tt>opus_int32</tt>: Length of packet + * @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz. + * This must be a multiple of 400, or + * inaccurate results will be returned. + * @returns Number of samples + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples of an Opus packet. * @param [in] dec <tt>OpusDecoder*</tt>: Decoder state * @param [in] packet <tt>char*</tt>: Opus packet * @param [in] len <tt>opus_int32</tt>: Length of packet @@ -514,27 +594,304 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDe /** @defgroup opus_repacketizer Repacketizer * @{ * - * The repacketizer can be used to merge multiple Opus packets into a single packet - * or alternatively to split Opus packets that have previously been merged. + * The repacketizer can be used to merge multiple Opus packets into a single + * packet or alternatively to split Opus packets that have previously been + * merged. Splitting valid Opus packets is always guaranteed to succeed, + * whereas merging valid packets only succeeds if all frames have the same + * mode, bandwidth, and frame size, and when the total duration of the merged + * packet is no more than 120 ms. + * The repacketizer currently only operates on elementary Opus + * streams. It will not manipualte multistream packets successfully, except in + * the degenerate case where they consist of data from a single stream. + * + * The repacketizing process starts with creating a repacketizer state, either + * by calling opus_repacketizer_create() or by allocating the memory yourself, + * e.g., + * @code + * OpusRepacketizer *rp; + * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size()); + * if (rp != NULL) + * opus_repacketizer_init(rp); + * @endcode + * + * Then the application should submit packets with opus_repacketizer_cat(), + * extract new packets with opus_repacketizer_out() or + * opus_repacketizer_out_range(), and then reset the state for the next set of + * input packets via opus_repacketizer_init(). + * + * For example, to split a sequence of packets into individual frames: + * @code + * unsigned char *data; + * int len; + * while (get_next_packet(&data, &len)) + * { + * unsigned char out[1276]; + * opus_int32 out_len; + * int nb_frames; + * int err; + * int i; + * err = opus_repacketizer_cat(rp, data, len); + * if (err != OPUS_OK) + * { + * release_packet(data); + * return err; + * } + * nb_frames = opus_repacketizer_get_nb_frames(rp); + * for (i = 0; i < nb_frames; i++) + * { + * out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out)); + * if (out_len < 0) + * { + * release_packet(data); + * return (int)out_len; + * } + * output_next_packet(out, out_len); + * } + * opus_repacketizer_init(rp); + * release_packet(data); + * } + * @endcode + * + * Alternatively, to combine a sequence of frames into packets that each + * contain up to <code>TARGET_DURATION_MS</code> milliseconds of data: + * @code + * // The maximum number of packets with duration TARGET_DURATION_MS occurs + * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5) + * // packets. + * unsigned char *data[(TARGET_DURATION_MS*2/5)+1]; + * opus_int32 len[(TARGET_DURATION_MS*2/5)+1]; + * int nb_packets; + * unsigned char out[1277*(TARGET_DURATION_MS*2/2)]; + * opus_int32 out_len; + * int prev_toc; + * nb_packets = 0; + * while (get_next_packet(data+nb_packets, len+nb_packets)) + * { + * int nb_frames; + * int err; + * nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]); + * if (nb_frames < 1) + * { + * release_packets(data, nb_packets+1); + * return nb_frames; + * } + * nb_frames += opus_repacketizer_get_nb_frames(rp); + * // If adding the next packet would exceed our target, or it has an + * // incompatible TOC sequence, output the packets we already have before + * // submitting it. + * // N.B., The nb_packets > 0 check ensures we've submitted at least one + * // packet since the last call to opus_repacketizer_init(). Otherwise a + * // single packet longer than TARGET_DURATION_MS would cause us to try to + * // output an (invalid) empty packet. It also ensures that prev_toc has + * // been set to a valid value. Additionally, len[nb_packets] > 0 is + * // guaranteed by the call to opus_packet_get_nb_frames() above, so the + * // reference to data[nb_packets][0] should be valid. + * if (nb_packets > 0 && ( + * ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) || + * opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames > + * TARGET_DURATION_MS*48)) + * { + * out_len = opus_repacketizer_out(rp, out, sizeof(out)); + * if (out_len < 0) + * { + * release_packets(data, nb_packets+1); + * return (int)out_len; + * } + * output_next_packet(out, out_len); + * opus_repacketizer_init(rp); + * release_packets(data, nb_packets); + * data[0] = data[nb_packets]; + * len[0] = len[nb_packets]; + * nb_packets = 0; + * } + * err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]); + * if (err != OPUS_OK) + * { + * release_packets(data, nb_packets+1); + * return err; + * } + * prev_toc = data[nb_packets][0]; + * nb_packets++; + * } + * // Output the final, partial packet. + * if (nb_packets > 0) + * { + * out_len = opus_repacketizer_out(rp, out, sizeof(out)); + * release_packets(data, nb_packets); + * if (out_len < 0) + * return (int)out_len; + * output_next_packet(out, out_len); + * } + * @endcode * + * An alternate way of merging packets is to simply call opus_repacketizer_cat() + * unconditionally until it fails. At that point, the merged packet can be + * obtained with opus_repacketizer_out() and the input packet for which + * opus_repacketizer_cat() needs to be re-added to a newly reinitialized + * repacketizer state. */ typedef struct OpusRepacketizer OpusRepacketizer; +/** Gets the size of an <code>OpusRepacketizer</code> structure. + * @returns The size in bytes. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void); +/** (Re)initializes a previously allocated repacketizer state. + * The state must be at least the size returned by opus_repacketizer_get_size(). + * This can be used for applications which use their own allocator instead of + * malloc(). + * It must also be called to reset the queue of packets waiting to be + * repacketized, which is necessary if the maximum packet duration of 120 ms + * is reached or if you wish to submit packets with a different Opus + * configuration (coding mode, audio bandwidth, frame size, or channel count). + * Failure to do so will prevent a new packet from being added with + * opus_repacketizer_cat(). + * @see opus_repacketizer_create + * @see opus_repacketizer_get_size + * @see opus_repacketizer_cat + * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to + * (re)initialize. + * @returns A pointer to the same repacketizer state that was passed in. + */ OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); +/** Allocates memory and initializes the new repacketizer with + * opus_repacketizer_init(). + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void); +/** Frees an <code>OpusRepacketizer</code> allocated by + * opus_repacketizer_create(). + * @param[in] rp <tt>OpusRepacketizer*</tt>: State to be freed. + */ OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp); +/** Add a packet to the current repacketizer state. + * This packet must match the configuration of any packets already submitted + * for repacketization since the last call to opus_repacketizer_init(). + * This means that it must have the same coding mode, audio bandwidth, frame + * size, and channel count. + * This can be checked in advance by examining the top 6 bits of the first + * byte of the packet, and ensuring they match the top 6 bits of the first + * byte of any previously submitted packet. + * The total duration of audio in the repacketizer state also must not exceed + * 120 ms, the maximum duration of a single packet, after adding this packet. + * + * The contents of the current repacketizer state can be extracted into new + * packets using opus_repacketizer_out() or opus_repacketizer_out_range(). + * + * In order to add a packet with a different configuration or to add more + * audio beyond 120 ms, you must clear the repacketizer state by calling + * opus_repacketizer_init(). + * If a packet is too large to add to the current repacketizer state, no part + * of it is added, even if it contains multiple frames, some of which might + * fit. + * If you wish to be able to add parts of such packets, you should first use + * another repacketizer to split the packet into pieces and add them + * individually. + * @see opus_repacketizer_out_range + * @see opus_repacketizer_out + * @see opus_repacketizer_init + * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to which to + * add the packet. + * @param[in] data <tt>const unsigned char*</tt>: The packet data. + * The application must ensure + * this pointer remains valid + * until the next call to + * opus_repacketizer_init() or + * opus_repacketizer_destroy(). + * @param len <tt>opus_int32</tt>: The number of bytes in the packet data. + * @returns An error code indicating whether or not the operation succeeded. + * @retval #OPUS_OK The packet's contents have been added to the repacketizer + * state. + * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence, + * the packet's TOC sequence was not compatible + * with previously submitted packets (because + * the coding mode, audio bandwidth, frame size, + * or channel count did not match), or adding + * this packet would increase the total amount of + * audio stored in the repacketizer state to more + * than 120 ms. + */ OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); + +/** Construct a new packet from data previously submitted to the repacketizer + * state via opus_repacketizer_cat(). + * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to + * construct the new packet. + * @param begin <tt>int</tt>: The index of the first frame in the current + * repacketizer state to include in the output. + * @param end <tt>int</tt>: One past the index of the last frame in the + * current repacketizer state to include in the + * output. + * @param[out] data <tt>const unsigned char*</tt>: The buffer in which to + * store the output packet. + * @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in + * the output buffer. In order to guarantee + * success, this should be at least + * <code>1276</code> for a single frame, + * or for multiple frames, + * <code>1277*(end-begin)</code>. + * However, <code>1*(end-begin)</code> plus + * the size of all packet data submitted to + * the repacketizer since the last call to + * opus_repacketizer_init() or + * opus_repacketizer_create() is also + * sufficient, and possibly much smaller. + * @returns The total size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BAD_ARG <code>[begin,end)</code> was an invalid range of + * frames (begin < 0, begin >= end, or end > + * opus_repacketizer_get_nb_frames()). + * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the + * complete output packet. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); +/** Return the total number of frames contained in packet data submitted to + * the repacketizer state so far via opus_repacketizer_cat() since the last + * call to opus_repacketizer_init() or opus_repacketizer_create(). + * This defines the valid range of packets that can be extracted with + * opus_repacketizer_out_range() or opus_repacketizer_out(). + * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state containing the + * frames. + * @returns The total number of frames contained in the packet data submitted + * to the repacketizer state. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); +/** Construct a new packet from data previously submitted to the repacketizer + * state via opus_repacketizer_cat(). + * This is a convenience routine that returns all the data submitted so far + * in a single packet. + * It is equivalent to calling + * @code + * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp), + * data, maxlen) + * @endcode + * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to + * construct the new packet. + * @param[out] data <tt>const unsigned char*</tt>: The buffer in which to + * store the output packet. + * @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in + * the output buffer. In order to guarantee + * success, this should be at least + * <code>1277*opus_repacketizer_get_nb_frames(rp)</code>. + * However, + * <code>1*opus_repacketizer_get_nb_frames(rp)</code> + * plus the size of all packet data + * submitted to the repacketizer since the + * last call to opus_repacketizer_init() or + * opus_repacketizer_create() is also + * sufficient, and possibly much smaller. + * @returns The total size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the + * complete output packet. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1); /**@}*/ diff --git a/include/opus_defines.h b/include/opus_defines.h index 82a5f06..cdde061 100644 --- a/include/opus_defines.h +++ b/include/opus_defines.h @@ -63,20 +63,18 @@ extern "C" { /** @cond OPUS_INTERNAL_DOC */ /**Export control for opus functions */ -#if !defined(OPUS_EXPORT) - -#if defined(__GNUC__) && defined(OPUS_BUILD) -# define OPUS_EXPORT __attribute__ ((visibility ("default"))) -#elif defined(WIN32) && !defined(__MINGW32__) -# ifdef OPUS_BUILD +#ifndef OPUS_EXPORT +# if defined(__GNUC__) && defined(OPUS_BUILD) +# define OPUS_EXPORT __attribute__ ((visibility ("default"))) +# elif defined(WIN32) && !defined(__MINGW32__) +# ifdef OPUS_BUILD # define OPUS_EXPORT __declspec(dllexport) -# else +# else # define OPUS_EXPORT +# endif +# else +# define OPUS_EXPORT # endif -#else -# define OPUS_EXPORT -#endif - #endif # if !defined(OPUS_GNUC_PREREQ) @@ -147,10 +145,14 @@ extern "C" { #define OPUS_GET_FINAL_RANGE_REQUEST 4031 #define OPUS_GET_PITCH_REQUEST 4033 #define OPUS_SET_GAIN_REQUEST 4034 -#define OPUS_GET_GAIN_REQUEST 4045 +#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */ #define OPUS_SET_LSB_DEPTH_REQUEST 4036 #define OPUS_GET_LSB_DEPTH_REQUEST 4037 +#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039 + +/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */ + /* Macros to trigger compilation errors when the wrong types are provided to a CTL */ #define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x)) #define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr))) @@ -505,6 +507,24 @@ extern "C" { * </dl> * @hideinitializer */ #define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x) +/** Configures the depth of signal being encoded. + * This is a hint which helps the encoder identify silence and near-silence. + * @see OPUS_GET_LSB_DEPTH + * @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24 + * (default: 24). + * @hideinitializer */ +#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured signal depth. + * @see OPUS_SET_LSB_DEPTH + * @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and + * 24 (default: 24). + * @hideinitializer */ +#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x) + +/** Gets the duration (in samples) of the last packet successfully decoded or concealed. + * @param[out] x <tt>opus_int32 *</tt>: Number of samples (at current sampling rate). + * @hideinitializer */ +#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x) /**@}*/ /** @defgroup opus_genericctls Generic CTLs @@ -584,19 +604,6 @@ extern "C" { * @hideinitializer */ #define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) -/** Configures the depth of signal being encoded. - * This is a hint which helps the encoder identify silence and near-silence. - * @see OPUS_GET_LSB_DEPTH - * @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24 - * (default: 24). - * @hideinitializer */ -#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x) -/** Gets the encoder's configured signal depth. - * @see OPUS_SET_LSB_DEPTH - * @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and - * 24 (default: 24). - * @hideinitializer */ -#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x) /**@}*/ /** @defgroup opus_decoderctls Decoder related CTLs diff --git a/include/opus_multistream.h b/include/opus_multistream.h index 5e5364a..658067f 100644 --- a/include/opus_multistream.h +++ b/include/opus_multistream.h @@ -39,132 +39,592 @@ extern "C" { #endif -typedef struct OpusMSEncoder OpusMSEncoder; -typedef struct OpusMSDecoder OpusMSDecoder; +/** @cond OPUS_INTERNAL_DOC */ +/** Macros to trigger compilation errors when the wrong types are provided to a + * CTL. */ +/**@{*/ #define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr))) #define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr))) +/**@}*/ +/** These are the actual encoder and decoder CTL ID numbers. + * They should not be used directly by applications. + * In general, SETs should be even and GETs should be odd.*/ +/**@{*/ #define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120 #define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122 +/**@}*/ + +/** @endcond */ +/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs + * + * These are convenience macros that are specific to the + * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl() + * interface. + * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and + * @ref opus_decoderctls may be applied to a multistream encoder or decoder as + * well. + * In addition, you may retrieve the encoder or decoder state for an specific + * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or + * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually. + */ +/**@{*/ + +/** Gets the encoder state for an individual stream of a multistream encoder. + * @param[in] x <tt>opus_int32</tt>: The index of the stream whose encoder you + * wish to retrieve. + * This must be non-negative and less than + * the <code>streams</code> parameter used + * to initialize the encoder. + * @param[out] y <tt>OpusEncoder**</tt>: Returns a pointer to the given + * encoder state. + * @retval OPUS_BAD_ARG The index of the requested stream was out of range. + * @hideinitializer + */ #define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y) + +/** Gets the decoder state for an individual stream of a multistream decoder. + * @param[in] x <tt>opus_int32</tt>: The index of the stream whose decoder you + * wish to retrieve. + * This must be non-negative and less than + * the <code>streams</code> parameter used + * to initialize the decoder. + * @param[out] y <tt>OpusDecoder**</tt>: Returns a pointer to the given + * decoder state. + * @retval OPUS_BAD_ARG The index of the requested stream was out of range. + * @hideinitializer + */ #define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y) -/** Allocate and initialize a multistream encoder state object. - * Call opus_multistream_encoder_destroy() to release - * this object when finished. */ +/**@}*/ + +/** @defgroup opus_multistream Opus Multistream API + * @{ + * + * The multistream API allows individual Opus streams to be combined into a + * single packet, enabling support for up to 255 channels. Unlike an + * elementary Opus stream, the encoder and decoder must negotiate the channel + * configuration before the decoder can successfully interpret the data in the + * packets produced by the encoder. Some basic information, such as packet + * duration, can be computed without any special negotiation. + * + * The format for multistream Opus packets is defined in the + * <a href="http://tools.ietf.org/html/draft-terriberry-oggopus">Ogg + * encapsulation specification</a> and is based on the self-delimited Opus + * framing described in Appendix B of <a href="http://tools.ietf.org/html/rfc6716">RFC 6716</a>. + * Normal Opus packets are just a degenerate case of multistream Opus packets, + * and can be encoded or decoded with the multistream API by setting + * <code>streams</code> to <code>1</code> when initializing the encoder or + * decoder. + * + * Multistream Opus streams can contain up to 255 elementary Opus streams. + * These may be either "uncoupled" or "coupled", indicating that the decoder + * is configured to decode them to either 1 or 2 channels, respectively. + * The streams are ordered so that all coupled streams appear at the + * beginning. + * + * A <code>mapping</code> table defines which decoded channel <code>i</code> + * should be used for each input/output (I/O) channel <code>j</code>. This table is + * typically provided as an unsigned char array. + * Let <code>i = mapping[j]</code> be the index for I/O channel <code>j</code>. + * If <code>i < 2*coupled_streams</code>, then I/O channel <code>j</code> is + * encoded as the left channel of stream <code>(i/2)</code> if <code>i</code> + * is even, or as the right channel of stream <code>(i/2)</code> if + * <code>i</code> is odd. Otherwise, I/O channel <code>j</code> is encoded as + * mono in stream <code>(i - coupled_streams)</code>, unless it has the special + * value 255, in which case it is omitted from the encoding entirely (the + * decoder will reproduce it as silence). Each value <code>i</code> must either + * be the special value 255 or be less than <code>streams + coupled_streams</code>. + * + * The output channels specified by the encoder + * should use the + * <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis + * channel ordering</a>. A decoder may wish to apply an additional permutation + * to the mapping the encoder used to achieve a different output channel + * order (e.g. for outputing in WAV order). + * + * Each multistream packet contains an Opus packet for each stream, and all of + * the Opus packets in a single multistream packet must have the same + * duration. Therefore the duration of a multistream packet can be extracted + * from the TOC sequence of the first stream, which is located at the + * beginning of the packet, just like an elementary Opus stream: + * + * @code + * int nb_samples; + * int nb_frames; + * nb_frames = opus_packet_get_nb_frames(data, len); + * if (nb_frames < 1) + * return nb_frames; + * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames; + * @endcode + * + * The general encoding and decoding process proceeds exactly the same as in + * the normal @ref opus_encoder and @ref opus_decoder APIs. + * See their documentation for an overview of how to use the corresponding + * multistream functions. + */ + +/** Opus multistream encoder state. + * This contains the complete state of a multistream Opus encoder. + * It is position independent and can be freely copied. + * @see opus_multistream_encoder_create + * @see opus_multistream_encoder_init + */ +typedef struct OpusMSEncoder OpusMSEncoder; + +/** Opus multistream decoder state. + * This contains the complete state of a multistream Opus decoder. + * It is position independent and can be freely copied. + * @see opus_multistream_decoder_create + * @see opus_multistream_decoder_init + */ +typedef struct OpusMSDecoder OpusMSDecoder; + +/**\name Multistream encoder functions */ +/**@{*/ + +/** Gets the size of an OpusMSEncoder structure. + * @param streams <tt>int</tt>: The total number of streams to encode from the + * input. + * This must be no more than 255. + * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (<code>streams + + * coupled_streams</code>) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size( + int streams, + int coupled_streams +); + +/** Allocates and initializes a multistream encoder state. + * Call opus_multistream_encoder_destroy() to release + * this object when finished. + * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels <tt>int</tt>: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (<code>streams + + * coupled_streams</code>). + * @param streams <tt>int</tt>: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (<code>streams + + * coupled_streams</code>) must be no + * more than the number of input channels. + * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from + * encoded channels to input channels, as described in + * @ref opus_multistream. As an extra constraint, the + * multistream encoder does not allow encoding coupled + * streams for which one channel is unused since this + * is never a good idea. + * @param application <tt>int</tt>: The target encoder application. + * This must be one of the following: + * <dl> + * <dt>#OPUS_APPLICATION_VOIP</dt> + * <dd>Process signal for improved speech intelligibility.</dd> + * <dt>#OPUS_APPLICATION_AUDIO</dt> + * <dd>Favor faithfulness to the original input.</dd> + * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt> + * <dd>Configure the minimum possible coding delay by disabling certain modes + * of operation.</dd> + * </dl> + * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create( - opus_int32 Fs, /**< Sampling rate of input signal (Hz) */ - int channels, /**< Number of channels in the input signal */ - int streams, /**< Total number of streams to encode from the input */ - int coupled_streams, /**< Number of coupled (stereo) streams to encode */ - const unsigned char *mapping, /**< Encoded mapping between channels and streams */ - int application, /**< Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */ - int *error /**< Error code */ + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application, + int *error ) OPUS_ARG_NONNULL(5); -/** Initialize an already allocated multistream encoder state. */ +/** Initialize a previously allocated multistream encoder state. + * The memory pointed to by \a st must be at least the size returned by + * opus_multistream_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_multistream_encoder_create + * @see opus_multistream_encoder_get_size + * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize. + * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels <tt>int</tt>: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (<code>streams + + * coupled_streams</code>). + * @param streams <tt>int</tt>: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (<code>streams + + * coupled_streams</code>) must be no + * more than the number of input channels. + * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from + * encoded channels to input channels, as described in + * @ref opus_multistream. As an extra constraint, the + * multistream encoder does not allow encoding coupled + * streams for which one channel is unused since this + * is never a good idea. + * @param application <tt>int</tt>: The target encoder application. + * This must be one of the following: + * <dl> + * <dt>#OPUS_APPLICATION_VOIP</dt> + * <dd>Process signal for improved speech intelligibility.</dd> + * <dt>#OPUS_APPLICATION_AUDIO</dt> + * <dd>Favor faithfulness to the original input.</dd> + * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt> + * <dd>Configure the minimum possible coding delay by disabling certain modes + * of operation.</dd> + * </dl> + * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ OPUS_EXPORT int opus_multistream_encoder_init( - OpusMSEncoder *st, /**< Encoder state */ - opus_int32 Fs, /**< Sampling rate of input signal (Hz) */ - int channels, /**< Number of channels in the input signal */ - int streams, /**< Total number of streams to encode from the input */ - int coupled_streams, /**< Number of coupled (stereo) streams to encode */ - const unsigned char *mapping, /**< Encoded mapping between channels and streams */ - int application /**< Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */ + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); -/** Returns length of the data payload (in bytes) or a negative error code */ +/** Encodes a multistream Opus frame. + * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state. + * @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved + * samples. + * This must contain + * <code>frame_size*channels</code> + * samples. + * @param frame_size <tt>int</tt>: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data <tt>unsigned char*</tt>: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode( - OpusMSEncoder *st, /**< Encoder state */ - const opus_int16 *pcm, /**< Input signal as interleaved samples. Length is frame_size*channels */ - int frame_size, /**< Number of samples per frame of input signal */ - unsigned char *data, /**< Output buffer for the compressed payload (no more than max_data_bytes long) */ - opus_int32 max_data_bytes /**< Allocated memory for payload; don't use for controlling bitrate */ + OpusMSEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); -/** Returns length of the data payload (in bytes) or a negative error code. */ +/** Encodes a multistream Opus frame from floating point input. + * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state. + * @param[in] pcm <tt>const float*</tt>: The input signal as interleaved + * samples with a normal range of + * +/-1.0. + * Samples with a range beyond +/-1.0 + * are supported but will be clipped by + * decoders using the integer API and + * should only be used if it is known + * that the far end supports extended + * dynamic range. + * This must contain + * <code>frame_size*channels</code> + * samples. + * @param frame_size <tt>int</tt>: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data <tt>unsigned char*</tt>: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float( - OpusMSEncoder *st, /**< Encoder state */ - const float *pcm, /**< Input signal interleaved in channel order. length is frame_size*channels */ - int frame_size, /**< Number of samples per frame of input signal */ - unsigned char *data, /**< Output buffer for the compressed payload (no more than max_data_bytes long) */ - opus_int32 max_data_bytes /**< Allocated memory for payload; don't use for controlling bitrate */ + OpusMSEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); -/** Gets the size of an OpusMSEncoder structure. - * @returns size +/** Frees an <code>OpusMSEncoder</code> allocated by + * opus_multistream_encoder_create(). + * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to be freed. */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size( - int streams, /**< Total number of coded streams */ - int coupled_streams /**< Number of coupled (stereo) streams */ -); - -/** Deallocate a multstream encoder state */ OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st); -/** Get or set options on a multistream encoder state */ +/** Perform a CTL function on a multistream Opus encoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_encoderctls, or @ref opus_multistream_ctls. + * @see opus_genericctls + * @see opus_encoderctls + * @see opus_multistream_ctls + */ OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); -/** Allocate and initialize a multistream decoder state object. - * Call opus_multistream_decoder_destroy() to release - * this object when finished. */ +/**@}*/ + +/**\name Multistream decoder functions */ +/**@{*/ + +/** Gets the size of an <code>OpusMSDecoder</code> structure. + * @param streams <tt>int</tt>: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams <tt>int</tt>: Number streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (<code>streams + + * coupled_streams</code>) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size( + int streams, + int coupled_streams +); + +/** Allocates and initializes a multistream decoder state. + * Call opus_multistream_decoder_destroy() to release + * this object when finished. + * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels <tt>int</tt>: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (<code>streams + + * coupled_streams</code>). + * @param streams <tt>int</tt>: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (<code>streams + + * coupled_streams</code>) must be no + * more than 255. + * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from + * coded channels to output channels, as described in + * @ref opus_multistream. + * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create( - opus_int32 Fs, /**< Sampling rate to decode at (Hz) */ - int channels, /**< Number of channels to decode */ - int streams, /**< Total number of coded streams in the multistream */ - int coupled_streams, /**< Number of coupled (stereo) streams in the multistream */ - const unsigned char *mapping, /**< Stream to channel mapping table */ - int *error /**< Error code */ + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int *error ) OPUS_ARG_NONNULL(5); -/** Intialize a previously allocated decoder state object. */ +/** Intialize a previously allocated decoder state object. + * The memory pointed to by \a st must be at least the size returned by + * opus_multistream_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_multistream_decoder_create + * @see opus_multistream_deocder_get_size + * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize. + * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels <tt>int</tt>: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (<code>streams + + * coupled_streams</code>). + * @param streams <tt>int</tt>: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (<code>streams + + * coupled_streams</code>) must be no + * more than 255. + * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from + * coded channels to output channels, as described in + * @ref opus_multistream. + * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ OPUS_EXPORT int opus_multistream_decoder_init( - OpusMSDecoder *st, /**< Encoder state */ - opus_int32 Fs, /**< Sample rate of input signal (Hz) */ - int channels, /**< Number of channels in the input signal */ - int streams, /**< Total number of coded streams */ - int coupled_streams, /**< Number of coupled (stereo) streams */ - const unsigned char *mapping /**< Stream to channel mapping table */ + OpusMSDecoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); -/** Returns the number of samples decoded or a negative error code */ +/** Decode a multistream Opus packet. + * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state. + * @param[in] data <tt>const unsigned char*</tt>: Input payload. + * Use a <code>NULL</code> + * pointer to indicate packet + * loss. + * @param len <tt>opus_int32</tt>: Number of bytes in payload. + * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved + * samples. + * This must contain room for + * <code>frame_size*channels</code> + * samples. + * @param frame_size <tt>int</tt>: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * <b>must</b> be a multiple of 2.5 ms. + * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode( - OpusMSDecoder *st, /**< Decoder state */ - const unsigned char *data, /**< Input payload. Use a NULL pointer to indicate packet loss */ - opus_int32 len, /**< Number of bytes in payload */ - opus_int16 *pcm, /**< Output signal, samples interleaved in channel order . length is frame_size*channels */ - int frame_size, /**< Number of samples per frame of input signal */ - int decode_fec /**< Flag (0/1) to request that any in-band forward error correction data be */ - /**< decoded. If no such data is available the frame is decoded as if it were lost. */ + OpusMSDecoder *st, + const unsigned char *data, + opus_int32 len, + opus_int16 *pcm, + int frame_size, + int decode_fec ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); -/** Returns the number of samples decoded or a negative error code */ +/** Decode a multistream Opus packet with floating point output. + * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state. + * @param[in] data <tt>const unsigned char*</tt>: Input payload. + * Use a <code>NULL</code> + * pointer to indicate packet + * loss. + * @param len <tt>opus_int32</tt>: Number of bytes in payload. + * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved + * samples. + * This must contain room for + * <code>frame_size*channels</code> + * samples. + * @param frame_size <tt>int</tt>: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * <b>must</b> be a multiple of 2.5 ms. + * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float( - OpusMSDecoder *st, /**< Decoder state */ - const unsigned char *data, /**< Input payload buffer. Use a NULL pointer to indicate packet loss */ - opus_int32 len, /**< Number of payload bytes in data */ - float *pcm, /**< Buffer for the output signal (interleaved iin channel order). length is frame_size*channels */ - int frame_size, /**< Number of samples per frame of input signal */ - int decode_fec /**< Flag (0/1) to request that any in-band forward error correction data be */ - /**< decoded. If no such data is available the frame is decoded as if it were lost. */ + OpusMSDecoder *st, + const unsigned char *data, + opus_int32 len, + float *pcm, + int frame_size, + int decode_fec ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); -/** Gets the size of an OpusMSDecoder structure. - * @returns size +/** Perform a CTL function on a multistream Opus decoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_decoderctls, or @ref opus_multistream_ctls. + * @see opus_genericctls + * @see opus_decoderctls + * @see opus_multistream_ctls */ -OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size( - int streams, /**< Total number of coded streams */ - int coupled_streams /**< Number of coupled (stereo) streams */ -); - -/** Get or set options on a multistream decoder state */ OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); -/** Deallocate a multistream decoder state object */ +/** Frees an <code>OpusMSDecoder</code> allocated by + * opus_multistream_decoder_create(). + * @param st <tt>OpusMSDecoder</tt>: Multistream decoder state to be freed. + */ OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st); +/**@}*/ + +/**@}*/ + #ifdef __cplusplus } #endif diff --git a/opus-uninstalled.pc.in b/opus-uninstalled.pc.in index 7361028..36e8db6 100644 --- a/opus-uninstalled.pc.in +++ b/opus-uninstalled.pc.in @@ -1,12 +1,12 @@ -# opus codec reference implementation uninstalled pkg-config file +# Opus codec reference implementation uninstalled pkg-config file libdir=${pcfiledir}/.libs includedir=${pcfiledir} Name: opus uninstalled -Description: Opus IETF audio codec (not installed) +Description: Opus IETF audio codec (not installed, @PC_BUILD@) Version: @VERSION@ Requires: Conflicts: -Libs: ${libdir}/libopus.a -Cflags: -I${includedir}/include +Libs: ${libdir}/libopus.a @PC_LIBM@ +Cflags: -I${pcfiledir}/@top_srcdir@/include @@ -102,7 +102,7 @@ int main () echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means Opus was incorrectly installed" + echo "*** exact error that occurred. This usually means Opus was incorrectly installed" echo "*** or that you have moved Opus since it was installed." ]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" @@ -1,4 +1,4 @@ -# opus codec reference implementation pkg-config file +# Opus codec reference implementation pkg-config file prefix=@prefix@ exec_prefix=@exec_prefix@ @@ -6,10 +6,11 @@ libdir=@libdir@ includedir=@includedir@ Name: Opus -Description: Opus IETF low-latency audio codec +Description: Opus IETF audio codec (@PC_BUILD@ build) URL: http://opus-codec.org/ Version: @VERSION@ Requires: Conflicts: Libs: -L${libdir} -lopus +Libs.private: @PC_LIBM@ Cflags: -I${includedir}/opus diff --git a/opus_headers.mk b/opus_headers.mk new file mode 100644 index 0000000..f160710 --- /dev/null +++ b/opus_headers.mk @@ -0,0 +1,4 @@ +OPUS_HEAD = \ +include/opus.h \ +include/opus_multistream.h \ +src/opus_private.h diff --git a/opus_sources.mk b/opus_sources.mk new file mode 100644 index 0000000..384b036 --- /dev/null +++ b/opus_sources.mk @@ -0,0 +1,5 @@ +OPUS_SOURCES = src/opus.c \ +src/opus_decoder.c \ +src/opus_encoder.c \ +src/opus_multistream.c \ +src/repacketizer.c @@ -67,14 +67,6 @@ opus_int silk_InitEncoder( /* O Returns error co silk_EncControlStruct *encStatus /* O Encoder Status */ ); -/***************************************/ -/* Read control structure from encoder */ -/***************************************/ -opus_int silk_QueryEncoder( /* O Returns error code */ - const void *encState, /* I State */ - silk_EncControlStruct *encStatus /* O Encoder Status */ -); - /**************************/ /* Encode frame with Silk */ /**************************/ diff --git a/silk/NLSF_stabilize.c b/silk/NLSF_stabilize.c index fc642af..7498b54 100644 --- a/silk/NLSF_stabilize.c +++ b/silk/NLSF_stabilize.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. /* NLSF stabilizer: */ /* */ -/* - Moves NLSFs futher apart if they are too close */ +/* - Moves NLSFs further apart if they are too close */ /* - Moves NLSFs away from borders if they are too close */ /* - High effort to achieve a modification with minimum */ /* Euclidean distance to input vector */ @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include "main.h" +#include "stack_alloc.h" #include "PLC.h" #define NB_ATT 2 @@ -178,12 +179,17 @@ static inline void silk_PLC_conceal( opus_int16 rand_scale_Q14; opus_int16 *B_Q14, *exc_buf_ptr; opus_int32 *sLPC_Q14_ptr; - opus_int16 exc_buf[ 2 * MAX_SUB_FRAME_LENGTH ]; + VARDECL( opus_int16, exc_buf ); opus_int16 A_Q12[ MAX_LPC_ORDER ]; - opus_int16 sLTP[ MAX_FRAME_LENGTH ]; - opus_int32 sLTP_Q14[ 2 * MAX_FRAME_LENGTH ]; + VARDECL( opus_int16, sLTP ); + VARDECL( opus_int32, sLTP_Q14 ); silk_PLC_struct *psPLC = &psDec->sPLC; opus_int32 prevGain_Q10[2]; + SAVE_STACK; + + ALLOC( exc_buf, 2*psPLC->subfr_length, opus_int16 ); + ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); + ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 ); prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6); prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6); @@ -354,9 +360,10 @@ static inline void silk_PLC_conceal( for( i = 0; i < MAX_NB_SUBFR; i++ ) { psDecCtrl->pitchL[ i ] = lag; } + RESTORE_STACK; } -/* Glues concealed frames with new good recieved frames */ +/* Glues concealed frames with new good received frames */ void silk_PLC_glue_frames( silk_decoder_state *psDec, /* I/O decoder state */ opus_int16 frame[], /* I/O signal */ diff --git a/silk/SigProc_FIX.h b/silk/SigProc_FIX.h index 72ec26a..daa5fd0 100644 --- a/silk/SigProc_FIX.h +++ b/silk/SigProc_FIX.h @@ -313,7 +313,7 @@ void silk_burg_modified( opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ - const opus_int subfr_length, /* I Input signal subframe length (incl. D preceeding samples) */ + const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */ const opus_int nb_subfr, /* I Number of subframes stacked in x */ const opus_int D /* I Order */ ); @@ -379,7 +379,7 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot ) } } -/* Allocate opus_int16 alligned to 4-byte memory address */ +/* Allocate opus_int16 aligned to 4-byte memory address */ #if EMBEDDED_ARM #define silk_DWORD_ALIGN __attribute__((aligned(4))) #else diff --git a/silk/control_audio_bandwidth.c b/silk/control_audio_bandwidth.c index a9af913..b645dd5 100644 --- a/silk/control_audio_bandwidth.c +++ b/silk/control_audio_bandwidth.c @@ -80,6 +80,8 @@ opus_int silk_control_audio_bandwidth( } else { if( psEncC->sLP.transition_frame_no <= 0 ) { encControl->switchReady = 1; + /* Make room for redundancy */ + encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 ); } else { /* Direction: down (at double speed) */ psEncC->sLP.mode = -2; @@ -106,6 +108,8 @@ opus_int silk_control_audio_bandwidth( } else { if( psEncC->sLP.mode == 0 ) { encControl->switchReady = 1; + /* Make room for redundancy */ + encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 ); } else { /* Direction: up */ psEncC->sLP.mode = 1; diff --git a/silk/control_codec.c b/silk/control_codec.c index d0ed528..ecc338c 100644 --- a/silk/control_codec.c +++ b/silk/control_codec.c @@ -38,18 +38,18 @@ POSSIBILITY OF SUCH DAMAGE. #include "tuning_parameters.h" #include "pitch_est_defines.h" -opus_int silk_setup_resamplers( +static opus_int silk_setup_resamplers( silk_encoder_state_Fxx *psEnc, /* I/O */ opus_int fs_kHz /* I */ ); -opus_int silk_setup_fs( +static opus_int silk_setup_fs( silk_encoder_state_Fxx *psEnc, /* I/O */ opus_int fs_kHz, /* I */ opus_int PacketSize_ms /* I */ ); -opus_int silk_setup_complexity( +static opus_int silk_setup_complexity( silk_encoder_state *psEncC, /* I/O */ opus_int Complexity /* I */ ); @@ -131,7 +131,7 @@ opus_int silk_control_encoder( return ret; } -opus_int silk_setup_resamplers( +static opus_int silk_setup_resamplers( silk_encoder_state_Fxx *psEnc, /* I/O */ opus_int fs_kHz /* I */ ) @@ -186,7 +186,7 @@ opus_int silk_setup_resamplers( return ret; } -opus_int silk_setup_fs( +static opus_int silk_setup_fs( silk_encoder_state_Fxx *psEnc, /* I/O */ opus_int fs_kHz, /* I */ opus_int PacketSize_ms /* I */ @@ -299,7 +299,7 @@ opus_int silk_setup_fs( return ret; } -opus_int silk_setup_complexity( +static opus_int silk_setup_complexity( silk_encoder_state *psEncC, /* I/O */ opus_int Complexity /* I */ ) diff --git a/silk/dec_API.c b/silk/dec_API.c index 60beef6..68403b7 100644 --- a/silk/dec_API.c +++ b/silk/dec_API.c @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include "API.h" #include "main.h" +#include "stack_alloc.h" /************************/ /* Decoder Super Struct */ @@ -85,14 +86,16 @@ opus_int silk_Decode( /* O Returns error co { opus_int i, n, decode_only_middle = 0, ret = SILK_NO_ERROR; opus_int32 nSamplesOutDec, LBRR_symbol; - opus_int16 samplesOut1_tmp[ 2 ][ MAX_FS_KHZ * MAX_FRAME_LENGTH_MS + 2 ]; - opus_int16 samplesOut2_tmp[ MAX_API_FS_KHZ * MAX_FRAME_LENGTH_MS ]; + opus_int16 *samplesOut1_tmp[ 2 ]; + VARDECL( opus_int16, samplesOut1_tmp_storage ); + VARDECL( opus_int16, samplesOut2_tmp ); opus_int32 MS_pred_Q13[ 2 ] = { 0 }; opus_int16 *resample_out_ptr; silk_decoder *psDec = ( silk_decoder * )decState; silk_decoder_state *channel_state = psDec->channel_state; opus_int has_side; opus_int stereo_to_mono; + SAVE_STACK; /**********************************/ /* Test if first frame in payload */ @@ -132,11 +135,13 @@ opus_int silk_Decode( /* O Returns error co channel_state[ n ].nb_subfr = 4; } else { silk_assert( 0 ); + RESTORE_STACK; return SILK_DEC_INVALID_FRAME_SIZE; } fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1; if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) { silk_assert( 0 ); + RESTORE_STACK; return SILK_DEC_INVALID_SAMPLING_FREQUENCY; } ret += silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec, decControl->API_sampleRate ); @@ -153,6 +158,7 @@ opus_int silk_Decode( /* O Returns error co if( decControl->API_sampleRate > (opus_int32)MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) { ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY; + RESTORE_STACK; return( ret ); } @@ -240,6 +246,14 @@ opus_int silk_Decode( /* O Returns error co psDec->channel_state[ 1 ].first_frame_after_reset = 1; } + ALLOC( samplesOut1_tmp_storage, + decControl->nChannelsInternal*( + channel_state[ 0 ].frame_length + 2 ), + opus_int16 ); + samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage; + samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage + + channel_state[ 0 ].frame_length + 2; + if( lostFlag == FLAG_DECODE_NORMAL ) { has_side = !decode_only_middle; } else { @@ -285,6 +299,8 @@ opus_int silk_Decode( /* O Returns error co *nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) ); /* Set up pointers to temp buffers */ + ALLOC( samplesOut2_tmp, + decControl->nChannelsAPI == 2 ? *nSamplesOut : 0, opus_int16 ); if( decControl->nChannelsAPI == 2 ) { resample_out_ptr = samplesOut2_tmp; } else { @@ -337,6 +353,7 @@ opus_int silk_Decode( /* O Returns error co } else { psDec->prev_decode_only_middle = decode_only_middle; } + RESTORE_STACK; return ret; } diff --git a/silk/decode_core.c b/silk/decode_core.c index 2142dd4..0365ffd 100644 --- a/silk/decode_core.c +++ b/silk/decode_core.c @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include "main.h" +#include "stack_alloc.h" /**********************************************************/ /* Core decoder. Performs inverse NSQ operation LTP + LPC */ @@ -43,15 +44,21 @@ void silk_decode_core( { opus_int i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType; opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ]; - opus_int16 sLTP[ MAX_FRAME_LENGTH ]; - opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ]; + VARDECL( opus_int16, sLTP ); + VARDECL( opus_int32, sLTP_Q15 ); opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10; opus_int32 *pred_lag_ptr, *pexc_Q14, *pres_Q14; - opus_int32 res_Q14[ MAX_SUB_FRAME_LENGTH ]; - opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; + VARDECL( opus_int32, res_Q14 ); + VARDECL( opus_int32, sLPC_Q14 ); + SAVE_STACK; silk_assert( psDec->prev_gain_Q16 != 0 ); + ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); + ALLOC( sLTP_Q15, psDec->ltp_mem_length + psDec->frame_length, opus_int32 ); + ALLOC( res_Q14, psDec->subfr_length, opus_int32 ); + ALLOC( sLPC_Q14, psDec->subfr_length + MAX_LPC_ORDER, opus_int32 ); + offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ]; if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) { @@ -227,4 +234,5 @@ void silk_decode_core( /* Save LPC state */ silk_memcpy( psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof( opus_int32 ) ); + RESTORE_STACK; } diff --git a/silk/decode_frame.c b/silk/decode_frame.c index 9db93d8..3e4a6e2 100644 --- a/silk/decode_frame.c +++ b/silk/decode_frame.c @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include "main.h" +#include "stack_alloc.h" #include "PLC.h" /****************/ @@ -44,12 +45,16 @@ opus_int silk_decode_frame( opus_int condCoding /* I The type of conditional coding to use */ ) { - silk_decoder_control sDecCtrl; + VARDECL( silk_decoder_control, psDecCtrl ); opus_int L, mv_len, ret = 0; - opus_int pulses[ MAX_FRAME_LENGTH ]; + VARDECL( opus_int, pulses ); + SAVE_STACK; L = psDec->frame_length; - sDecCtrl.LTP_scale_Q14 = 0; + ALLOC( psDecCtrl, 1, silk_decoder_control ); + ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) & + ~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int ); + psDecCtrl->LTP_scale_Q14 = 0; /* Safety checks */ silk_assert( L > 0 && L <= MAX_FRAME_LENGTH ); @@ -71,20 +76,17 @@ opus_int silk_decode_frame( /********************************************/ /* Decode parameters and pulse signal */ /********************************************/ - silk_decode_parameters( psDec, &sDecCtrl, condCoding ); - - /* Update length. Sampling frequency may have changed */ - L = psDec->frame_length; + silk_decode_parameters( psDec, psDecCtrl, condCoding ); /********************************************************/ /* Run inverse NSQ */ /********************************************************/ - silk_decode_core( psDec, &sDecCtrl, pOut, pulses ); + silk_decode_core( psDec, psDecCtrl, pOut, pulses ); /********************************************************/ /* Update PLC state */ /********************************************************/ - silk_PLC( psDec, &sDecCtrl, pOut, 0 ); + silk_PLC( psDec, psDecCtrl, pOut, 0 ); psDec->lossCnt = 0; psDec->prevSignalType = psDec->indices.signalType; @@ -94,7 +96,7 @@ opus_int silk_decode_frame( psDec->first_frame_after_reset = 0; } else { /* Handle packet loss by extrapolation */ - silk_PLC( psDec, &sDecCtrl, pOut, 1 ); + silk_PLC( psDec, psDecCtrl, pOut, 1 ); } /*************************/ @@ -113,13 +115,14 @@ opus_int silk_decode_frame( /************************************************/ /* Comfort noise generation / estimation */ /************************************************/ - silk_CNG( psDec, &sDecCtrl, pOut, L ); + silk_CNG( psDec, psDecCtrl, pOut, L ); /* Update some decoder state variables */ - psDec->lagPrev = sDecCtrl.pitchL[ psDec->nb_subfr - 1 ]; + psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; /* Set output frame length */ *pN = L; + RESTORE_STACK; return ret; } diff --git a/silk/enc_API.c b/silk/enc_API.c index c0143fd..ec7915c 100644 --- a/silk/enc_API.c +++ b/silk/enc_API.c @@ -40,6 +40,14 @@ POSSIBILITY OF SUCH DAMAGE. #include "main_FLP.h" #endif +/***************************************/ +/* Read control structure from encoder */ +/***************************************/ +static opus_int silk_QueryEncoder( /* O Returns error code */ + const void *encState, /* I State */ + silk_EncControlStruct *encStatus /* O Encoder Status */ +); + /****************************************/ /* Encoder functions */ /****************************************/ @@ -90,7 +98,7 @@ opus_int silk_InitEncoder( /* O Returns error co /***************************************/ /* Read control structure from encoder */ /***************************************/ -opus_int silk_QueryEncoder( /* O Returns error code */ +static opus_int silk_QueryEncoder( /* O Returns error code */ const void *encState, /* I State */ silk_EncControlStruct *encStatus /* O Encoder Status */ ) diff --git a/silk/fixed/LTP_analysis_filter_FIX.c b/silk/fixed/LTP_analysis_filter_FIX.c index 155eea8..a8fee55 100644 --- a/silk/fixed/LTP_analysis_filter_FIX.c +++ b/silk/fixed/LTP_analysis_filter_FIX.c @@ -33,13 +33,13 @@ POSSIBILITY OF SUCH DAMAGE. void silk_LTP_analysis_filter_FIX( opus_int16 *LTP_res, /* O LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ - const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceeding samples */ + const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceding samples */ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag, one for each subframe */ const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I Inverse quantization gains, one for each subframe */ const opus_int subfr_length, /* I Length of each subframe */ const opus_int nb_subfr, /* I Number of subframes */ - const opus_int pre_length /* I Length of the preceeding samples starting at &x[0] for each subframe */ + const opus_int pre_length /* I Length of the preceding samples starting at &x[0] for each subframe */ ) { const opus_int16 *x_ptr, *x_lag_ptr; diff --git a/silk/fixed/burg_modified_FIX.c b/silk/fixed/burg_modified_FIX.c index ecbba03..26a66b1 100644 --- a/silk/fixed/burg_modified_FIX.c +++ b/silk/fixed/burg_modified_FIX.c @@ -47,7 +47,7 @@ void silk_burg_modified( opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ - const opus_int subfr_length, /* I Input signal subframe length (incl. D preceeding samples) */ + const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */ const opus_int nb_subfr, /* I Number of subframes stacked in x */ const opus_int D /* I Order */ ) @@ -238,7 +238,7 @@ void silk_burg_modified( /* Scale coefficients */ A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); } - /* Subtract energy of preceeding samples from C0 */ + /* Subtract energy of preceding samples from C0 */ if( rshifts > 0 ) { for( s = 0; s < nb_subfr; s++ ) { x_ptr = x + s * subfr_length; diff --git a/silk/fixed/find_pitch_lags_FIX.c b/silk/fixed/find_pitch_lags_FIX.c index a323411..39c3048 100644 --- a/silk/fixed/find_pitch_lags_FIX.c +++ b/silk/fixed/find_pitch_lags_FIX.c @@ -54,7 +54,7 @@ void silk_find_pitch_lags_FIX( /******************************************/ buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; - /* Safty check */ + /* Safety check */ silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); x_buf = x - psEnc->sCmn.ltp_mem_length; @@ -101,7 +101,7 @@ void silk_find_pitch_lags_FIX( } /* Do BWE */ - silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWITH_EXPANSION, 16 ) ); + silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWIDTH_EXPANSION, 16 ) ); /*****************************************/ /* LPC analysis filtering */ diff --git a/silk/fixed/main_FIX.h b/silk/fixed/main_FIX.h index 1e60f88..369b31e 100644 --- a/silk/fixed/main_FIX.h +++ b/silk/fixed/main_FIX.h @@ -168,17 +168,17 @@ void silk_find_LTP_FIX( void silk_LTP_analysis_filter_FIX( opus_int16 *LTP_res, /* O LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ - const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceeding samples */ + const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceding samples */ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag, one for each subframe */ const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I Inverse quantization gains, one for each subframe */ const opus_int subfr_length, /* I Length of each subframe */ const opus_int nb_subfr, /* I Number of subframes */ - const opus_int pre_length /* I Length of the preceeding samples starting at &x[0] for each subframe */ + const opus_int pre_length /* I Length of the preceding samples starting at &x[0] for each subframe */ ); /* Calculates residual energies of input subframes where all subframes have LPC_order */ -/* of preceeding samples */ +/* of preceding samples */ void silk_residual_energy_FIX( opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ diff --git a/silk/fixed/noise_shape_analysis_FIX.c b/silk/fixed/noise_shape_analysis_FIX.c index b0e35de..d230e48 100644 --- a/silk/fixed/noise_shape_analysis_FIX.c +++ b/silk/fixed/noise_shape_analysis_FIX.c @@ -199,7 +199,7 @@ void silk_noise_shape_analysis_FIX( /*************************/ /* Set quantizer offset */ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Initally set to 0; may be overruled in process_gains(..) */ + /* Initially set to 0; may be overruled in process_gains(..) */ psEnc->sCmn.indices.quantOffsetType = 0; psEncCtrl->sparseness_Q8 = 0; } else { diff --git a/silk/fixed/pitch_analysis_core_FIX.c b/silk/fixed/pitch_analysis_core_FIX.c index bb9166e..d43f444 100644 --- a/silk/fixed/pitch_analysis_core_FIX.c +++ b/silk/fixed/pitch_analysis_core_FIX.c @@ -500,7 +500,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 silk_assert( lag == silk_SAT16( lag ) ); contour_bias_Q20 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 20 ), lag ); - /* Set up codebook parameters acording to complexity setting and frame length */ + /* Set up codebook parameters according to complexity setting and frame length */ if( nb_subfr == PE_MAX_NB_SUBFR ) { nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; cbk_size = PE_NB_CBKS_STAGE3_MAX; diff --git a/silk/fixed/residual_energy_FIX.c b/silk/fixed/residual_energy_FIX.c index 912b16b..f284e51 100644 --- a/silk/fixed/residual_energy_FIX.c +++ b/silk/fixed/residual_energy_FIX.c @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "main_FIX.h" /* Calculates residual energies of input subframes where all subframes have LPC_order */ -/* of preceeding samples */ +/* of preceding samples */ void silk_residual_energy_FIX( opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ @@ -54,7 +54,7 @@ void silk_residual_energy_FIX( /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ for( i = 0; i < nb_subfr >> 1; i++ ) { - /* Calculate half frame LPC residual signal including preceeding samples */ + /* Calculate half frame LPC residual signal including preceding samples */ silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order ); /* Point to first subframe of the just calculated LPC residual signal */ diff --git a/silk/float/LTP_analysis_filter_FLP.c b/silk/float/LTP_analysis_filter_FLP.c index 297c813..d3a6a5a 100644 --- a/silk/float/LTP_analysis_filter_FLP.c +++ b/silk/float/LTP_analysis_filter_FLP.c @@ -33,13 +33,13 @@ POSSIBILITY OF SUCH DAMAGE. void silk_LTP_analysis_filter_FLP( silk_float *LTP_res, /* O LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */ - const silk_float *x, /* I Input signal, with preceeding samples */ + const silk_float *x, /* I Input signal, with preceding samples */ const silk_float B[ LTP_ORDER * MAX_NB_SUBFR ], /* I LTP coefficients for each subframe */ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ const silk_float invGains[ MAX_NB_SUBFR ], /* I Inverse quantization gains */ const opus_int subfr_length, /* I Length of each subframe */ const opus_int nb_subfr, /* I number of subframes */ - const opus_int pre_length /* I Preceeding samples for each subframe */ + const opus_int pre_length /* I Preceding samples for each subframe */ ) { const silk_float *x_ptr, *x_lag_ptr; diff --git a/silk/float/SigProc_FLP.h b/silk/float/SigProc_FLP.h index 18e2571..036b46d 100644 --- a/silk/float/SigProc_FLP.h +++ b/silk/float/SigProc_FLP.h @@ -109,7 +109,7 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy silk_float A[], /* O prediction coefficients (length order) */ const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ const silk_float minInvGain, /* I minimum inverse prediction gain */ - const opus_int subfr_length, /* I input signal subframe length (incl. D preceeding samples) */ + const opus_int subfr_length, /* I input signal subframe length (incl. D preceding samples) */ const opus_int nb_subfr, /* I number of subframes stacked in x */ const opus_int D /* I order */ ); diff --git a/silk/float/burg_modified_FLP.c b/silk/float/burg_modified_FLP.c index 0add3a6..31c9b22 100644 --- a/silk/float/burg_modified_FLP.c +++ b/silk/float/burg_modified_FLP.c @@ -40,7 +40,7 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy silk_float A[], /* O prediction coefficients (length order) */ const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */ const silk_float minInvGain, /* I minimum inverse prediction gain */ - const opus_int subfr_length, /* I input signal subframe length (incl. D preceeding samples) */ + const opus_int subfr_length, /* I input signal subframe length (incl. D preceding samples) */ const opus_int nb_subfr, /* I number of subframes stacked in x */ const opus_int D /* I order */ ) @@ -162,7 +162,7 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy for( k = 0; k < D; k++ ) { A[ k ] = (silk_float)( -Af[ k ] ); } - /* Subtract energy of preceeding samples from C0 */ + /* Subtract energy of preceding samples from C0 */ for( s = 0; s < nb_subfr; s++ ) { C0 -= silk_energy_FLP( x + s * subfr_length, D ); } diff --git a/silk/float/find_pitch_lags_FLP.c b/silk/float/find_pitch_lags_FLP.c index b3ade8f..00862a6 100644 --- a/silk/float/find_pitch_lags_FLP.c +++ b/silk/float/find_pitch_lags_FLP.c @@ -54,7 +54,7 @@ void silk_find_pitch_lags_FLP( /******************************************/ buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; - /* Safty check */ + /* Safety check */ silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); x_buf = x - psEnc->sCmn.ltp_mem_length; @@ -96,7 +96,7 @@ void silk_find_pitch_lags_FLP( silk_k2a_FLP( A, refl_coef, psEnc->sCmn.pitchEstimationLPCOrder ); /* Bandwidth expansion */ - silk_bwexpander_FLP( A, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWITH_EXPANSION ); + silk_bwexpander_FLP( A, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWIDTH_EXPANSION ); /*****************************************/ /* LPC analysis filtering */ diff --git a/silk/float/main_FLP.h b/silk/float/main_FLP.h index 202a7fe..93455d4 100644 --- a/silk/float/main_FLP.h +++ b/silk/float/main_FLP.h @@ -164,17 +164,17 @@ void silk_find_LTP_FLP( void silk_LTP_analysis_filter_FLP( silk_float *LTP_res, /* O LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */ - const silk_float *x, /* I Input signal, with preceeding samples */ + const silk_float *x, /* I Input signal, with preceding samples */ const silk_float B[ LTP_ORDER * MAX_NB_SUBFR ], /* I LTP coefficients for each subframe */ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ const silk_float invGains[ MAX_NB_SUBFR ], /* I Inverse quantization gains */ const opus_int subfr_length, /* I Length of each subframe */ const opus_int nb_subfr, /* I number of subframes */ - const opus_int pre_length /* I Preceeding samples for each subframe */ + const opus_int pre_length /* I Preceding samples for each subframe */ ); /* Calculates residual energies of input subframes where all subframes have LPC_order */ -/* of preceeding samples */ +/* of preceding samples */ void silk_residual_energy_FLP( silk_float nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ const silk_float x[], /* I Input signal */ diff --git a/silk/float/noise_shape_analysis_FLP.c b/silk/float/noise_shape_analysis_FLP.c index 1c203b3..33bfd20 100644 --- a/silk/float/noise_shape_analysis_FLP.c +++ b/silk/float/noise_shape_analysis_FLP.c @@ -174,7 +174,7 @@ void silk_noise_shape_analysis_FLP( /*************************/ /* Set quantizer offset */ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Initally set to 0; may be overruled in process_gains(..) */ + /* Initially set to 0; may be overruled in process_gains(..) */ psEnc->sCmn.indices.quantOffsetType = 0; psEncCtrl->sparseness = 0.0f; } else { diff --git a/silk/float/pitch_analysis_core_FLP.c b/silk/float/pitch_analysis_core_FLP.c index d23e4ee..fbff90c 100644 --- a/silk/float/pitch_analysis_core_FLP.c +++ b/silk/float/pitch_analysis_core_FLP.c @@ -419,7 +419,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, silk_assert( lag == silk_SAT16( lag ) ); contour_bias = PE_FLATCONTOUR_BIAS / lag; - /* Set up cbk parameters acording to complexity setting and frame length */ + /* Set up cbk parameters according to complexity setting and frame length */ if( nb_subfr == PE_MAX_NB_SUBFR ) { nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; cbk_size = PE_NB_CBKS_STAGE3_MAX; diff --git a/silk/float/prefilter_FLP.c b/silk/float/prefilter_FLP.c index 95b32da..d6c8439 100644 --- a/silk/float/prefilter_FLP.c +++ b/silk/float/prefilter_FLP.c @@ -47,7 +47,7 @@ static inline void silk_prefilt_FLP( opus_int length /* I */ ); -void silk_warped_LPC_analysis_filter_FLP( +static void silk_warped_LPC_analysis_filter_FLP( silk_float state[], /* I/O State [order + 1] */ silk_float res[], /* O Residual signal [length] */ const silk_float coef[], /* I Coefficients [order] */ diff --git a/silk/float/residual_energy_FLP.c b/silk/float/residual_energy_FLP.c index 4fa0e67..e65457a 100644 --- a/silk/float/residual_energy_FLP.c +++ b/silk/float/residual_energy_FLP.c @@ -87,7 +87,7 @@ silk_float silk_residual_energy_covar_FLP( /* O } /* Calculates residual energies of input subframes where all subframes have LPC_order */ -/* of preceeding samples */ +/* of preceding samples */ void silk_residual_energy_FLP( silk_float nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ const silk_float x[], /* I Input signal */ diff --git a/silk/float/wrappers_FLP.c b/silk/float/wrappers_FLP.c index 5500425..4259e90 100644 --- a/silk/float/wrappers_FLP.c +++ b/silk/float/wrappers_FLP.c @@ -155,7 +155,7 @@ void silk_NSQ_wrapper_FLP( /* Convert input to fix */ for( i = 0; i < psEnc->sCmn.frame_length; i++ ) { - x_Q3[ i ] = silk_float2int( 8.0 * x[ i ] ); + x_Q3[ i ] = silk_float2int( 8.0f * x[ i ] ); } /* Call NSQ */ diff --git a/silk/resampler_rom.c b/silk/resampler_rom.c index a09d188..b50af2e 100644 --- a/silk/resampler_rom.c +++ b/silk/resampler_rom.c @@ -34,18 +34,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "resampler_private.h" -/* Tables for 2x downsampler */ -const opus_int16 silk_resampler_down2_0 = 9872; -const opus_int16 silk_resampler_down2_1 = 39809 - 65536; - -/* Tables for 2x upsampler, high quality */ -const opus_int16 silk_resampler_up2_hq_0[ 3 ] = { 1746, 14986, 39083 - 65536 }; -const opus_int16 silk_resampler_up2_hq_1[ 3 ] = { 6854, 25769, 55542 - 65536 }; - /* Matlab code for the notch filter coefficients: */ /* B = [1, 0.147, 1]; A = [1, 0.107, 0.89]; G = 0.93; freqz(G * B, A, 2^14, 16e3); axis([0, 8000, -10, 1]) */ /* fprintf('\t%6d, %6d, %6d, %6d\n', round(B(2)*2^16), round(-A(2)*2^16), round((1-A(3))*2^16), round(G*2^15)) */ -const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 9634, -7012, 7209, 30474 }; +/* const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 9634, -7012, 7209, 30474 }; */ /* Tables with IIR and FIR coefficients for fractional downsamplers (123 Words) */ silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = { diff --git a/silk/resampler_rom.h b/silk/resampler_rom.h index 0ad0686..473b24a 100644 --- a/silk/resampler_rom.h +++ b/silk/resampler_rom.h @@ -42,12 +42,12 @@ extern "C" #define RESAMPLER_ORDER_FIR_12 8 /* Tables for 2x downsampler */ -extern const opus_int16 silk_resampler_down2_0; -extern const opus_int16 silk_resampler_down2_1; +static const opus_int16 silk_resampler_down2_0 = 9872; +static const opus_int16 silk_resampler_down2_1 = 39809 - 65536; /* Tables for 2x upsampler, high quality */ -extern const opus_int16 silk_resampler_up2_hq_0[ 3 ]; -extern const opus_int16 silk_resampler_up2_hq_1[ 3 ]; +static const opus_int16 silk_resampler_up2_hq_0[ 3 ] = { 1746, 14986, 39083 - 65536 }; +static const opus_int16 silk_resampler_up2_hq_1[ 3 ] = { 6854, 25769, 55542 - 65536 }; /* Tables with IIR and FIR coefficients for fractional downsamplers */ extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ]; diff --git a/silk/tables_LTP.c b/silk/tables_LTP.c index 5522e32..dd1fb55 100644 --- a/silk/tables_LTP.c +++ b/silk/tables_LTP.c @@ -35,16 +35,16 @@ const opus_uint8 silk_LTP_per_index_iCDF[3] = { 179, 99, 0 }; -const opus_uint8 silk_LTP_gain_iCDF_0[8] = { +static const opus_uint8 silk_LTP_gain_iCDF_0[8] = { 71, 56, 43, 30, 21, 12, 6, 0 }; -const opus_uint8 silk_LTP_gain_iCDF_1[16] = { +static const opus_uint8 silk_LTP_gain_iCDF_1[16] = { 199, 165, 144, 124, 109, 96, 84, 71, 61, 51, 42, 32, 23, 15, 8, 0 }; -const opus_uint8 silk_LTP_gain_iCDF_2[32] = { +static const opus_uint8 silk_LTP_gain_iCDF_2[32] = { 241, 225, 211, 199, 187, 175, 164, 153, 142, 132, 123, 114, 105, 96, 88, 80, 72, 64, 57, 50, 44, 38, 33, 29, @@ -53,16 +53,16 @@ const opus_uint8 silk_LTP_gain_iCDF_2[32] = { const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304; -const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = { +static const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = { 15, 131, 138, 138, 155, 155, 173, 173 }; -const opus_uint8 silk_LTP_gain_BITS_Q5_1[16] = { +static const opus_uint8 silk_LTP_gain_BITS_Q5_1[16] = { 69, 93, 115, 118, 131, 138, 141, 138, 150, 150, 155, 150, 155, 160, 166, 160 }; -const opus_uint8 silk_LTP_gain_BITS_Q5_2[32] = { +static const opus_uint8 silk_LTP_gain_BITS_Q5_2[32] = { 131, 128, 134, 141, 141, 141, 145, 145, 145, 150, 155, 155, 155, 155, 160, 160, 160, 160, 166, 166, 173, 173, 182, 192, @@ -81,7 +81,7 @@ const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[NB_LTP_CBKS] = { silk_LTP_gain_BITS_Q5_2 }; -const opus_int8 silk_LTP_gain_vq_0[8][5] = +static const opus_int8 silk_LTP_gain_vq_0[8][5] = { { 4, 6, 24, 7, 5 @@ -109,7 +109,7 @@ const opus_int8 silk_LTP_gain_vq_0[8][5] = } }; -const opus_int8 silk_LTP_gain_vq_1[16][5] = +static const opus_int8 silk_LTP_gain_vq_1[16][5] = { { 13, 22, 39, 23, 12 @@ -161,7 +161,7 @@ const opus_int8 silk_LTP_gain_vq_1[16][5] = } }; -const opus_int8 silk_LTP_gain_vq_2[32][5] = +static const opus_int8 silk_LTP_gain_vq_2[32][5] = { { -6, 27, 61, 39, 5 diff --git a/silk/tables_NLSF_CB_NB_MB.c b/silk/tables_NLSF_CB_NB_MB.c index 57bb817..7548052 100644 --- a/silk/tables_NLSF_CB_NB_MB.c +++ b/silk/tables_NLSF_CB_NB_MB.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "tables.h" -const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = { +static const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = { 12, 35, 60, 83, 108, 132, 157, 180, 206, 228, 15, 32, 55, 77, 101, 125, 151, 175, 201, 225, 19, 42, 66, 89, @@ -74,7 +74,7 @@ const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = { 64, 84, 104, 118, 156, 177, 201, 230 }; -const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = { +static const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = { 212, 178, 148, 129, 108, 96, 85, 82, 79, 77, 61, 59, 57, 56, 51, 49, 48, 45, 42, 41, 40, 38, 36, 34, @@ -85,7 +85,7 @@ const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = { 28, 20, 19, 18, 12, 11, 5, 0 }; -const opus_uint8 silk_NLSF_CB2_SELECT_NB_MB[ 160 ] = { +static const opus_uint8 silk_NLSF_CB2_SELECT_NB_MB[ 160 ] = { 16, 0, 0, 0, 0, 99, 66, 36, 36, 34, 36, 34, 34, 34, 34, 83, 69, 36, 52, 34, 116, 102, 70, 68, @@ -108,7 +108,7 @@ const opus_uint8 silk_NLSF_CB2_SELECT_NB_MB[ 160 ] = { 171, 137, 139, 137, 155, 218, 219, 139 }; -const opus_uint8 silk_NLSF_CB2_iCDF_NB_MB[ 72 ] = { +static const opus_uint8 silk_NLSF_CB2_iCDF_NB_MB[ 72 ] = { 255, 254, 253, 238, 14, 3, 2, 1, 0, 255, 254, 252, 218, 35, 3, 2, 1, 0, 255, 254, 250, 208, 59, 4, @@ -120,7 +120,7 @@ const opus_uint8 silk_NLSF_CB2_iCDF_NB_MB[ 72 ] = { 254, 236, 173, 95, 37, 7, 1, 0 }; -const opus_uint8 silk_NLSF_CB2_BITS_NB_MB_Q5[ 72 ] = { +static const opus_uint8 silk_NLSF_CB2_BITS_NB_MB_Q5[ 72 ] = { 255, 255, 255, 131, 6, 145, 255, 255, 255, 255, 255, 236, 93, 15, 96, 255, 255, 255, 255, 255, 194, 83, 25, 71, @@ -132,13 +132,13 @@ const opus_uint8 silk_NLSF_CB2_BITS_NB_MB_Q5[ 72 ] = { 251, 123, 65, 55, 68, 100, 171, 255 }; -const opus_uint8 silk_NLSF_PRED_NB_MB_Q8[ 18 ] = { +static const opus_uint8 silk_NLSF_PRED_NB_MB_Q8[ 18 ] = { 179, 138, 140, 148, 151, 149, 153, 151, 163, 116, 67, 82, 59, 92, 72, 100, 89, 92 }; -const opus_int16 silk_NLSF_DELTA_MIN_NB_MB_Q15[ 11 ] = { +static const opus_int16 silk_NLSF_DELTA_MIN_NB_MB_Q15[ 11 ] = { 250, 3, 6, 3, 3, 3, 4, 3, 3, 3, 461 }; diff --git a/silk/tables_NLSF_CB_WB.c b/silk/tables_NLSF_CB_WB.c index 00b68f7..3d6052e 100644 --- a/silk/tables_NLSF_CB_WB.c +++ b/silk/tables_NLSF_CB_WB.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "tables.h" -const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = { +static const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = { 7, 23, 38, 54, 69, 85, 100, 116, 131, 147, 162, 178, 193, 208, 223, 239, 13, 25, 41, 55, 69, 83, 98, 112, @@ -98,7 +98,7 @@ const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = { 110, 119, 129, 141, 175, 198, 218, 237 }; -const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = { +static const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = { 225, 204, 201, 184, 183, 175, 158, 154, 153, 135, 119, 115, 113, 110, 109, 99, 98, 95, 79, 68, 52, 50, 48, 45, @@ -109,7 +109,7 @@ const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = { 24, 21, 11, 6, 5, 4, 3, 0 }; -const opus_uint8 silk_NLSF_CB2_SELECT_WB[ 256 ] = { +static const opus_uint8 silk_NLSF_CB2_SELECT_WB[ 256 ] = { 0, 0, 0, 0, 0, 0, 0, 1, 100, 102, 102, 68, 68, 36, 34, 96, 164, 107, 158, 185, 180, 185, 139, 102, @@ -144,7 +144,7 @@ const opus_uint8 silk_NLSF_CB2_SELECT_WB[ 256 ] = { 100, 107, 120, 119, 36, 197, 24, 0 }; -const opus_uint8 silk_NLSF_CB2_iCDF_WB[ 72 ] = { +static const opus_uint8 silk_NLSF_CB2_iCDF_WB[ 72 ] = { 255, 254, 253, 244, 12, 3, 2, 1, 0, 255, 254, 252, 224, 38, 3, 2, 1, 0, 255, 254, 251, 209, 57, 4, @@ -156,7 +156,7 @@ const opus_uint8 silk_NLSF_CB2_iCDF_WB[ 72 ] = { 248, 227, 177, 100, 19, 2, 1, 0 }; -const opus_uint8 silk_NLSF_CB2_BITS_WB_Q5[ 72 ] = { +static const opus_uint8 silk_NLSF_CB2_BITS_WB_Q5[ 72 ] = { 255, 255, 255, 156, 4, 154, 255, 255, 255, 255, 255, 227, 102, 15, 92, 255, 255, 255, 255, 255, 213, 83, 24, 72, @@ -168,14 +168,14 @@ const opus_uint8 silk_NLSF_CB2_BITS_WB_Q5[ 72 ] = { 166, 116, 76, 55, 53, 125, 255, 255 }; -const opus_uint8 silk_NLSF_PRED_WB_Q8[ 30 ] = { +static const opus_uint8 silk_NLSF_PRED_WB_Q8[ 30 ] = { 175, 148, 160, 176, 178, 173, 174, 164, 177, 174, 196, 182, 198, 192, 182, 68, 62, 66, 60, 72, 117, 85, 90, 118, 136, 151, 142, 160, 142, 155 }; -const opus_int16 silk_NLSF_DELTA_MIN_WB_Q15[ 17 ] = { +static const opus_int16 silk_NLSF_DELTA_MIN_WB_Q15[ 17 ] = { 100, 3, 40, 3, 3, 3, 5, 14, 14, 10, 11, 3, 8, 9, 7, 3, 347 diff --git a/silk/tables_other.c b/silk/tables_other.c index dedff26..3dc68d4 100644 --- a/silk/tables_other.c +++ b/silk/tables_other.c @@ -67,8 +67,8 @@ const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ] = { const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ] = { 64, 0 }; /* Tables for LBRR flags */ -const opus_uint8 silk_LBRR_flags_2_iCDF[ 3 ] = { 203, 150, 0 }; -const opus_uint8 silk_LBRR_flags_3_iCDF[ 7 ] = { 215, 195, 166, 125, 110, 82, 0 }; +static const opus_uint8 silk_LBRR_flags_2_iCDF[ 3 ] = { 203, 150, 0 }; +static const opus_uint8 silk_LBRR_flags_3_iCDF[ 7 ] = { 215, 195, 166, 125, 110, 82, 0 }; const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ] = { silk_LBRR_flags_2_iCDF, silk_LBRR_flags_3_iCDF diff --git a/silk/tuning_parameters.h b/silk/tuning_parameters.h index 0b0b774..a26de4d 100644 --- a/silk/tuning_parameters.h +++ b/silk/tuning_parameters.h @@ -44,7 +44,7 @@ extern "C" #define FIND_PITCH_WHITE_NOISE_FRACTION 1e-3f /* Bandwidth expansion for whitening filter in pitch analysis */ -#define FIND_PITCH_BANDWITH_EXPANSION 0.99f +#define FIND_PITCH_BANDWIDTH_EXPANSION 0.99f /*********************/ /* Linear prediction */ diff --git a/silk_headers.mk b/silk_headers.mk new file mode 100644 index 0000000..45c6985 --- /dev/null +++ b/silk_headers.mk @@ -0,0 +1,26 @@ +SILK_HEAD = \ +silk/debug.h \ +silk/control.h \ +silk/errors.h \ +silk/API.h \ +silk/typedef.h \ +silk/define.h \ +silk/main.h \ +silk/PLC.h \ +silk/structs.h \ +silk/tables.h \ +silk/tuning_parameters.h \ +silk/Inlines.h \ +silk/MacroCount.h \ +silk/MacroDebug.h \ +silk/macros.h \ +silk/pitch_est_defines.h \ +silk/resampler_private.h \ +silk/resampler_rom.h \ +silk/resampler_structs.h \ +silk/SigProc_FIX.h \ +silk/fixed/main_FIX.h \ +silk/fixed/structs_FIX.h \ +silk/float/main_FLP.h \ +silk/float/structs_FLP.h \ +silk/float/SigProc_FLP.h diff --git a/silk_sources.mk b/silk_sources.mk new file mode 100644 index 0000000..0de367b --- /dev/null +++ b/silk_sources.mk @@ -0,0 +1,138 @@ +SILK_SOURCES = \ +silk/CNG.c \ +silk/code_signs.c \ +silk/init_decoder.c \ +silk/decode_core.c \ +silk/decode_frame.c \ +silk/decode_parameters.c \ +silk/decode_indices.c \ +silk/decode_pulses.c \ +silk/decoder_set_fs.c \ +silk/dec_API.c \ +silk/enc_API.c \ +silk/encode_indices.c \ +silk/encode_pulses.c \ +silk/gain_quant.c \ +silk/interpolate.c \ +silk/LP_variable_cutoff.c \ +silk/NLSF_decode.c \ +silk/NSQ.c \ +silk/NSQ_del_dec.c \ +silk/PLC.c \ +silk/shell_coder.c \ +silk/tables_gain.c \ +silk/tables_LTP.c \ +silk/tables_NLSF_CB_NB_MB.c \ +silk/tables_NLSF_CB_WB.c \ +silk/tables_other.c \ +silk/tables_pitch_lag.c \ +silk/tables_pulses_per_block.c \ +silk/VAD.c \ +silk/control_audio_bandwidth.c \ +silk/quant_LTP_gains.c \ +silk/VQ_WMat_EC.c \ +silk/HP_variable_cutoff.c \ +silk/NLSF_encode.c \ +silk/NLSF_VQ.c \ +silk/NLSF_unpack.c \ +silk/NLSF_del_dec_quant.c \ +silk/process_NLSFs.c \ +silk/stereo_LR_to_MS.c \ +silk/stereo_MS_to_LR.c \ +silk/check_control_input.c \ +silk/control_SNR.c \ +silk/init_encoder.c \ +silk/control_codec.c \ +silk/A2NLSF.c \ +silk/ana_filt_bank_1.c \ +silk/biquad_alt.c \ +silk/bwexpander_32.c \ +silk/bwexpander.c \ +silk/debug.c \ +silk/decode_pitch.c \ +silk/inner_prod_aligned.c \ +silk/lin2log.c \ +silk/log2lin.c \ +silk/LPC_analysis_filter.c \ +silk/LPC_inv_pred_gain.c \ +silk/table_LSF_cos.c \ +silk/NLSF2A.c \ +silk/NLSF_stabilize.c \ +silk/NLSF_VQ_weights_laroia.c \ +silk/pitch_est_tables.c \ +silk/resampler.c \ +silk/resampler_down2_3.c \ +silk/resampler_down2.c \ +silk/resampler_private_AR2.c \ +silk/resampler_private_down_FIR.c \ +silk/resampler_private_IIR_FIR.c \ +silk/resampler_private_up2_HQ.c \ +silk/resampler_rom.c \ +silk/sigm_Q15.c \ +silk/sort.c \ +silk/sum_sqr_shift.c \ +silk/stereo_decode_pred.c \ +silk/stereo_encode_pred.c \ +silk/stereo_find_predictor.c \ +silk/stereo_quant_pred.c + + +SILK_SOURCES_FIXED = \ +silk/fixed/LTP_analysis_filter_FIX.c \ +silk/fixed/LTP_scale_ctrl_FIX.c \ +silk/fixed/corrMatrix_FIX.c \ +silk/fixed/encode_frame_FIX.c \ +silk/fixed/find_LPC_FIX.c \ +silk/fixed/find_LTP_FIX.c \ +silk/fixed/find_pitch_lags_FIX.c \ +silk/fixed/find_pred_coefs_FIX.c \ +silk/fixed/noise_shape_analysis_FIX.c \ +silk/fixed/prefilter_FIX.c \ +silk/fixed/process_gains_FIX.c \ +silk/fixed/regularize_correlations_FIX.c \ +silk/fixed/residual_energy16_FIX.c \ +silk/fixed/residual_energy_FIX.c \ +silk/fixed/solve_LS_FIX.c \ +silk/fixed/warped_autocorrelation_FIX.c \ +silk/fixed/apply_sine_window_FIX.c \ +silk/fixed/autocorr_FIX.c \ +silk/fixed/burg_modified_FIX.c \ +silk/fixed/k2a_FIX.c \ +silk/fixed/k2a_Q16_FIX.c \ +silk/fixed/pitch_analysis_core_FIX.c \ +silk/fixed/vector_ops_FIX.c \ +silk/fixed/schur64_FIX.c \ +silk/fixed/schur_FIX.c + +SILK_SOURCES_FLOAT = \ +silk/float/apply_sine_window_FLP.c \ +silk/float/corrMatrix_FLP.c \ +silk/float/encode_frame_FLP.c \ +silk/float/find_LPC_FLP.c \ +silk/float/find_LTP_FLP.c \ +silk/float/find_pitch_lags_FLP.c \ +silk/float/find_pred_coefs_FLP.c \ +silk/float/LPC_analysis_filter_FLP.c \ +silk/float/LTP_analysis_filter_FLP.c \ +silk/float/LTP_scale_ctrl_FLP.c \ +silk/float/noise_shape_analysis_FLP.c \ +silk/float/prefilter_FLP.c \ +silk/float/process_gains_FLP.c \ +silk/float/regularize_correlations_FLP.c \ +silk/float/residual_energy_FLP.c \ +silk/float/solve_LS_FLP.c \ +silk/float/warped_autocorrelation_FLP.c \ +silk/float/wrappers_FLP.c \ +silk/float/autocorrelation_FLP.c \ +silk/float/burg_modified_FLP.c \ +silk/float/bwexpander_FLP.c \ +silk/float/energy_FLP.c \ +silk/float/inner_product_FLP.c \ +silk/float/k2a_FLP.c \ +silk/float/levinsondurbin_FLP.c \ +silk/float/LPC_inv_pred_gain_FLP.c \ +silk/float/pitch_analysis_core_FLP.c \ +silk/float/scale_copy_vector_FLP.c \ +silk/float/scale_vector_FLP.c \ +silk/float/schur_FLP.c \ +silk/float/sort_FLP.c diff --git a/src/opus_compare.c b/src/opus_compare.c index b8a1620..06c67d7 100644 --- a/src/opus_compare.c +++ b/src/opus_compare.c @@ -1,3 +1,30 @@ +/* Copyright (c) 2011-2012 Xiph.Org Foundation, Mozilla Corporation + Written by Jean-Marc Valin and Timothy B. Terriberry */ +/* + 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. +*/ + #include <stdio.h> #include <stdlib.h> #include <math.h> diff --git a/src/opus_decoder.c b/src/opus_decoder.c index f0188cd..ad5f747 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -30,7 +30,7 @@ #endif #ifndef OPUS_BUILD -#error "OPUS_BUILD _MUST_ be defined to build Opus and you probably want a decent config.h, see README for more details." +#error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details." #endif #include <stdarg.h> @@ -64,6 +64,7 @@ struct OpusDecoder { int prev_mode; int frame_size; int prev_redundancy; + int last_packet_duration; opus_uint32 rangeFinal; }; @@ -257,23 +258,10 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, } } - /* For CELT/hybrid PLC of more than 20 ms, do multiple calls */ - if (data==NULL && frame_size > F20 && mode != MODE_SILK_ONLY) - { - int nb_samples = 0; - do { - int ret = opus_decode_frame(st, NULL, 0, pcm, F20, 0); - if (ret != F20) - { - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - pcm += F20*st->channels; - nb_samples += F20; - } while (nb_samples < frame_size); - RESTORE_STACK; - return frame_size; - } + /* For CELT/hybrid PLC of more than 20 ms, opus_decode_native() will do + multiple calls */ + if (data==NULL && mode != MODE_SILK_ONLY) + frame_size = IMIN(frame_size, F20); ALLOC(pcm_transition, F5*st->channels, opus_val16); if (data!=NULL && st->prev_mode > 0 && ( @@ -560,7 +548,7 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, int cbr; unsigned char ch, toc; int framesize; - int last_size; + opus_int32 last_size; const unsigned char *data0 = data; if (size==NULL) @@ -586,7 +574,9 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, { if (len&0x1) return OPUS_INVALID_PACKET; - size[0] = last_size = len/2; + last_size = len/2; + /* If last_size doesn't fit in size[0], we'll catch it later */ + size[0] = (short)last_size; } break; /* Two VBR frames */ @@ -647,7 +637,7 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, if (last_size*count!=len) return OPUS_INVALID_PACKET; for (i=0;i<count-1;i++) - size[i] = last_size; + size[i] = (short)last_size; } break; } @@ -675,7 +665,7 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, 1275. Reject them here.*/ if (last_size > 1275) return OPUS_INVALID_PACKET; - size[count-1] = last_size; + size[count-1] = (short)last_size; } if (frames) @@ -712,30 +702,81 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data, int count, offset; unsigned char toc; int tot_offset; + int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; /* 48 x 2.5 ms = 120 ms */ short size[48]; if (decode_fec<0 || decode_fec>1) return OPUS_BAD_ARG; + /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ + if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) + return OPUS_BAD_ARG; if (len==0 || data==NULL) - return opus_decode_frame(st, NULL, 0, pcm, frame_size, 0); - else if (len<0) + { + int pcm_count=0; + do { + int ret; + ret = opus_decode_frame(st, NULL, 0, pcm, frame_size-pcm_count, 0); + if (ret<0) + return ret; + pcm += st->channels*ret; + pcm_count += ret; + } while (pcm_count < frame_size); + st->last_packet_duration = pcm_count; + return pcm_count; + } else if (len<0) return OPUS_BAD_ARG; - tot_offset = 0; - st->mode = opus_packet_get_mode(data); - st->bandwidth = opus_packet_get_bandwidth(data); - st->frame_size = opus_packet_get_samples_per_frame(data, st->Fs); - st->stream_channels = opus_packet_get_nb_channels(data); + packet_mode = opus_packet_get_mode(data); + packet_bandwidth = opus_packet_get_bandwidth(data); + packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); + packet_stream_channels = opus_packet_get_nb_channels(data); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset); + + data += offset; + + if (decode_fec) + { + int duration_copy; + int ret; + /* If no FEC can be present, run the PLC (recursive call) */ + if (frame_size <= packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) + return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL); + /* Otherwise, run the PLC on everything except the size for which we might have FEC */ + duration_copy = st->last_packet_duration; + ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL); + if (ret<0) + { + st->last_packet_duration = duration_copy; + return ret; + } + /* Complete with FEC */ + st->mode = packet_mode; + st->bandwidth = packet_bandwidth; + st->frame_size = packet_frame_size; + st->stream_channels = packet_stream_channels; + ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), + packet_frame_size, 1); + if (ret<0) + return ret; + st->last_packet_duration = frame_size; + return frame_size; + } + tot_offset = 0; if (count < 0) return count; - data += offset; tot_offset += offset; - if (count*st->frame_size > frame_size) + if (count*packet_frame_size > frame_size) return OPUS_BUFFER_TOO_SMALL; + + /* Update the state as the last step to avoid updating it on an invalid packet */ + st->mode = packet_mode; + st->bandwidth = packet_bandwidth; + st->frame_size = packet_frame_size; + st->stream_channels = packet_stream_channels; + nb_samples=0; for (i=0;i<count;i++) { @@ -750,6 +791,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data, } if (packet_offset != NULL) *packet_offset = tot_offset; + st->last_packet_duration = nb_samples; return nb_samples; } @@ -903,6 +945,12 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...) st->decode_gain = value; } break; + case OPUS_GET_LAST_PACKET_DURATION_REQUEST: + { + opus_uint32 *value = va_arg(ap, opus_uint32*); + *value = st->last_packet_duration; + } + break; default: /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/ ret = OPUS_UNIMPLEMENTED; @@ -979,8 +1027,8 @@ int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) return packet[1]&0x3F; } -int opus_decoder_get_nb_samples(const OpusDecoder *dec, - const unsigned char packet[], opus_int32 len) +int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, + opus_int32 Fs) { int samples; int count = opus_packet_get_nb_frames(packet, len); @@ -988,10 +1036,16 @@ int opus_decoder_get_nb_samples(const OpusDecoder *dec, if (count<0) return count; - samples = count*opus_packet_get_samples_per_frame(packet, dec->Fs); + samples = count*opus_packet_get_samples_per_frame(packet, Fs); /* Can't have more than 120 ms */ - if (samples*25 > dec->Fs*3) + if (samples*25 > Fs*3) return OPUS_INVALID_PACKET; else return samples; } + +int opus_decoder_get_nb_samples(const OpusDecoder *dec, + const unsigned char packet[], opus_int32 len) +{ + return opus_packet_get_nb_samples(packet, len, dec->Fs); +} diff --git a/src/opus_demo.c b/src/opus_demo.c index 20bebba..09b12a3 100644 --- a/src/opus_demo.c +++ b/src/opus_demo.c @@ -95,7 +95,7 @@ static void check_encoder_option(int decode_only, const char *opt) } } -int silk8_test[][4] = { +static const int silk8_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*2, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960, 1}, @@ -106,7 +106,7 @@ int silk8_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 480, 2} }; -int silk12_test[][4] = { +static const int silk12_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*3, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960*2, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 960, 1}, @@ -117,7 +117,7 @@ int silk12_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_MEDIUMBAND, 480, 2} }; -int silk16_test[][4] = { +static const int silk16_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*3, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960*2, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 1}, @@ -128,21 +128,21 @@ int silk16_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, 480, 2} }; -int hybrid24_test[][4] = { +static const int hybrid24_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 2}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 480, 2} }; -int hybrid48_test[][4] = { +static const int hybrid48_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 1}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2}, {MODE_SILK_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2} }; -int celt_test[][4] = { +static const int celt_test[][4] = { {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 1}, {MODE_CELT_ONLY, OPUS_BANDWIDTH_SUPERWIDEBAND, 960, 1}, {MODE_CELT_ONLY, OPUS_BANDWIDTH_WIDEBAND, 960, 1}, @@ -185,7 +185,7 @@ int celt_test[][4] = { }; -int celt_hq_test[][4] = { +static const int celt_hq_test[][4] = { {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 960, 2}, {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 480, 2}, {MODE_CELT_ONLY, OPUS_BANDWIDTH_FULLBAND, 240, 2}, @@ -234,7 +234,7 @@ int main(int argc, char *argv[]) int random_framesize=0, newsize=0, delayed_celt=0; int sweep_max=0, sweep_min=0; int random_fec=0; - int (*mode_list)[4]=NULL; + const int (*mode_list)[4]=NULL; int nb_modes_in_list=0; int curr_mode=0; int curr_mode_count=0; @@ -684,18 +684,22 @@ int main(int argc, char *argv[]) } else { int output_samples; lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc); + if (lost) + opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples)); + else + output_samples = max_frame_size; if( count >= use_inbandfec ) { /* delay by one packet when using in-band FEC */ if( use_inbandfec ) { if( lost_prev ) { /* attempt to decode with in-band FEC from next packet */ - output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1); + output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 1); } else { /* regular decode */ - output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0); + output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, output_samples, 0); } } else { - output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0); + output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 0); } if (output_samples>0) { diff --git a/src/opus_encoder.c b/src/opus_encoder.c index b77e48e..aae3125 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -291,7 +291,7 @@ static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channel } #ifndef FIXED_POINT -void silk_biquad_float( +static void silk_biquad_float( const opus_val16 *in, /* I: Input signal */ const opus_int32 *B_Q28, /* I: MA coefficients [3] */ const opus_int32 *A_Q28, /* I: AR coefficients [2] */ @@ -458,20 +458,20 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s int prefill=0; int start_band = 0; int redundancy = 0; - int redundancy_bytes = 0; + int redundancy_bytes = 0; /* Number of bytes to use for redundancy frame */ int celt_to_silk = 0; VARDECL(opus_val16, pcm_buf); int nb_compr_bytes; int to_celt = 0; opus_uint32 redundant_rng = 0; int cutoff_Hz, hp_freq_smth1; - int voice_est; + int voice_est; /* Probability of voice in Q7 */ opus_int32 equiv_rate; int delay_compensation; int frame_rate; - opus_int32 max_rate; + opus_int32 max_rate; /* Max bitrate we're allowed to use */ int curr_bandwidth; - opus_int32 max_data_bytes; + opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */ VARDECL(opus_val16, tmp_prefill); ALLOC_STACK; @@ -652,6 +652,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s } } } + /* For the first frame at a new SILK bandwidth */ if (st->silk_bw_switch) { redundancy = 1; @@ -659,6 +660,15 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s st->silk_bw_switch = 0; } + if (redundancy) + { + /* Fair share of the max size allowed */ + redundancy_bytes = IMIN(257, max_data_bytes*(opus_int32)(st->Fs/200)/(frame_size+st->Fs/200)); + /* For VBR, target the actual bitrate (subject to the limit above) */ + if (st->use_vbr) + redundancy_bytes = IMIN(redundancy_bytes, st->bitrate_bps/1600); + } + if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) { silk_EncControlStruct dummy; @@ -823,7 +833,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s st->mode = MODE_SILK_ONLY; /* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */ - bytes_target = IMIN(max_data_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1; + bytes_target = IMIN(max_data_bytes-redundancy_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1; data += 1; @@ -929,7 +939,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s st->silk_mode.useCBR = !st->use_vbr; /* Call SILK encoder for the low band */ - nBytes = IMIN(1275, max_data_bytes-1); + nBytes = IMIN(1275, max_data_bytes-1-redundancy_bytes); st->silk_mode.maxBits = nBytes*8; /* Only allow up to 90% of the bits for hybrid mode*/ @@ -941,8 +951,6 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s /* Reduce the initial target to make it easier to reach the CBR rate */ st->silk_mode.bitRate = IMAX(1, st->silk_mode.bitRate-2000); } - if (redundancy) - st->silk_mode.maxBits -= st->silk_mode.maxBits/(1 + frame_size/(st->Fs/200)); if (prefill) { @@ -990,6 +998,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s } st->silk_mode.opusCanSwitch = st->silk_mode.switchReady; + /* FIXME: How do we allocate the redundancy for CBR? */ if (st->silk_mode.opusCanSwitch) { redundancy = 1; @@ -1047,7 +1056,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1)); celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint)); celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps)); - nb_compr_bytes = max_data_bytes-1; + nb_compr_bytes = max_data_bytes-1-redundancy_bytes; } else { nb_compr_bytes = bytes_target; } @@ -1119,8 +1128,10 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s } if (!redundancy) + { st->silk_bw_switch = 0; - + redundancy_bytes = 0; + } if (st->mode != MODE_CELT_ONLY)start_band=17; if (st->mode == MODE_SILK_ONLY) diff --git a/src/opus_multistream.c b/src/opus_multistream.c index 955dc81..a7f25a5 100644 --- a/src/opus_multistream.c +++ b/src/opus_multistream.c @@ -159,7 +159,7 @@ int opus_multistream_encoder_init( { int coupled_size; int mono_size; - int i; + int i, ret; char *ptr; if ((channels>255) || (channels<1) || (coupled_streams>streams) || @@ -180,12 +180,14 @@ int opus_multistream_encoder_init( for (i=0;i<st->layout.nb_coupled_streams;i++) { - opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application); + ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application); + if(ret!=OPUS_OK)return ret; ptr += align(coupled_size); } for (;i<st->layout.nb_streams;i++) { - opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application); + ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application); + if(ret!=OPUS_OK)return ret; ptr += align(mono_size); } return OPUS_OK; @@ -202,7 +204,15 @@ OpusMSEncoder *opus_multistream_encoder_create( ) { int ret; - OpusMSEncoder *st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams)); + OpusMSEncoder *st; + if ((channels>255) || (channels<1) || (coupled_streams>streams) || + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams)); if (st==NULL) { if (error) @@ -647,7 +657,15 @@ OpusMSDecoder *opus_multistream_decoder_create( ) { int ret; - OpusMSDecoder *st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams)); + OpusMSDecoder *st; + if ((channels>255) || (channels<1) || (coupled_streams>streams) || + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams)); if (st==NULL) { if (error) @@ -663,8 +681,6 @@ OpusMSDecoder *opus_multistream_decoder_create( st = NULL; } return st; - - } typedef void (*opus_copy_channel_out_func)( @@ -908,6 +924,8 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) { case OPUS_GET_BANDWIDTH_REQUEST: case OPUS_GET_SAMPLE_RATE_REQUEST: + case OPUS_GET_GAIN_REQUEST: + case OPUS_GET_LAST_PACKET_DURATION_REQUEST: { OpusDecoder *dec; /* For int32* GET params, just query the first stream */ diff --git a/tests/run_vectors.sh b/tests/run_vectors.sh index 3e021af..1cc445d 100755 --- a/tests/run_vectors.sh +++ b/tests/run_vectors.sh @@ -1,5 +1,38 @@ #!/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 logs_mono.txt rm logs_stereo.txt diff --git a/tests/test_opus_api.c b/tests/test_opus_api.c index b5348c3..c2d7e10 100644 --- a/tests/test_opus_api.c +++ b/tests/test_opus_api.c @@ -126,6 +126,9 @@ opus_int32 test_dec_api(void) dec = opus_decoder_create(fs, c, &err); if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); cfgs++; + dec = opus_decoder_create(fs, c, 0); + if(dec!=NULL)test_failed(); + cfgs++; dec=malloc(opus_decoder_get_size(2)); if(dec==NULL)test_failed(); err = opus_decoder_init(dec,fs,c); @@ -224,12 +227,19 @@ opus_int32 test_dec_api(void) VG_UNDEF(packet,sizeof(packet)); packet[0]=0; if(opus_decoder_get_nb_samples(dec,packet,1)!=480)test_failed(); - cfgs++; + if(opus_packet_get_nb_samples(packet,1,48000)!=480)test_failed(); + if(opus_packet_get_nb_samples(packet,1,96000)!=960)test_failed(); + if(opus_packet_get_nb_samples(packet,1,32000)!=320)test_failed(); + if(opus_packet_get_nb_samples(packet,1,8000)!=80)test_failed(); + packet[0]=3; + if(opus_packet_get_nb_samples(packet,1,24000)!=OPUS_INVALID_PACKET)test_failed(); packet[0]=(63<<2)|3; packet[1]=63; + if(opus_packet_get_nb_samples(packet,0,24000)!=OPUS_BAD_ARG)test_failed(); + if(opus_packet_get_nb_samples(packet,2,48000)!=OPUS_INVALID_PACKET)test_failed(); if(opus_decoder_get_nb_samples(dec,packet,2)!=OPUS_INVALID_PACKET)test_failed(); - fprintf(stdout," opus_decoder_get_nb_samples() ................ OK.\n"); - cfgs++; + fprintf(stdout," opus_{packet,decoder}_get_nb_samples() ....... OK.\n"); + cfgs+=9; if(OPUS_BAD_ARG!=opus_packet_get_nb_frames(packet,0))test_failed(); for(i=0;i<256;i++) { @@ -366,6 +376,9 @@ opus_int32 test_msdec_api(void) dec = opus_multistream_decoder_create(fs, c, 1, c-1, mapping, &err); if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); cfgs++; + dec = opus_multistream_decoder_create(fs, c, 1, c-1, mapping, 0); + if(dec!=NULL)test_failed(); + cfgs++; dec=malloc(opus_multistream_decoder_get_size(1,1)); if(dec==NULL)test_failed(); err = opus_multistream_decoder_init(dec,fs,c,1,c-1, mapping); @@ -375,116 +388,128 @@ opus_int32 test_msdec_api(void) } } - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 2, 1, 0, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err==OPUS_OK || dec!=NULL)test_failed(); - cfgs++; + for(c=0;c<2;c++) + { + int *ret_err; + ret_err = c?0:&err; - VG_UNDEF(&err,sizeof(err)); - mapping[0]=mapping[1]=0; - dec = opus_multistream_decoder_create(48000, 2, 1, 0, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_OK || dec==NULL)test_failed(); - cfgs++; - opus_multistream_decoder_destroy(dec); - cfgs++; + mapping[0]=0; + mapping[1]=1; + for(i=2;i<256;i++)VG_UNDEF(&mapping[i],sizeof(unsigned char)); - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 1, 4, 1, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_OK || dec==NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 2, 1, 0, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; - err = opus_multistream_decoder_init(dec,48000, 1, 0, 0, mapping); - if(err!=OPUS_BAD_ARG)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + mapping[0]=mapping[1]=0; + dec = opus_multistream_decoder_create(48000, 2, 1, 0, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_OK) || dec==NULL)test_failed(); + cfgs++; + opus_multistream_decoder_destroy(dec); + cfgs++; - err = opus_multistream_decoder_init(dec,48000, 1, 1, -1, mapping); - if(err!=OPUS_BAD_ARG)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 1, 4, 1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_OK) || dec==NULL)test_failed(); + cfgs++; - opus_multistream_decoder_destroy(dec); - cfgs++; + err = opus_multistream_decoder_init(dec,48000, 1, 0, 0, mapping); + if(err!=OPUS_BAD_ARG)test_failed(); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 2, 1, 1, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_OK || dec==NULL)test_failed(); - cfgs++; - opus_multistream_decoder_destroy(dec); - cfgs++; + err = opus_multistream_decoder_init(dec,48000, 1, 1, -1, mapping); + if(err!=OPUS_BAD_ARG)test_failed(); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 255, 255, 1, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); - cfgs++; + opus_multistream_decoder_destroy(dec); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, -1, 1, 1, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 2, 1, 1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_OK) || dec==NULL)test_failed(); + cfgs++; + opus_multistream_decoder_destroy(dec); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 0, 1, 1, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 255, 255, 1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 1, -1, 2, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, -1, 1, 1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 1, -1, -1, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 0, 1, 1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 256, 255, 1, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 1, -1, 2, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - dec = opus_multistream_decoder_create(48000, 256, 255, 0, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 1, -1, -1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - mapping[0]=255; - mapping[1]=1; - mapping[2]=2; - dec = opus_multistream_decoder_create(48000, 3, 2, 0, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_BAD_ARG || dec!=NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 256, 255, 1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; - VG_UNDEF(&err,sizeof(err)); - mapping[0]=0; - mapping[1]=0; - mapping[2]=0; - dec = opus_multistream_decoder_create(48000, 3, 2, 1, mapping, &err); - VG_CHECK(&err,sizeof(err)); - if(err!=OPUS_OK || dec==NULL)test_failed(); - cfgs++; - opus_multistream_decoder_destroy(dec); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + dec = opus_multistream_decoder_create(48000, 256, 255, 0, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; - mapping[0]=0; - mapping[1]=255; - mapping[2]=1; - mapping[3]=2; - mapping[4]=3; - dec = opus_multistream_decoder_create(48001, 5, 4, 1, mapping, 0); - if(dec!=NULL)test_failed(); - cfgs++; + VG_UNDEF(ret_err,sizeof(*ret_err)); + mapping[0]=255; + mapping[1]=1; + mapping[2]=2; + dec = opus_multistream_decoder_create(48000, 3, 2, 0, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; + + VG_UNDEF(ret_err,sizeof(*ret_err)); + mapping[0]=0; + mapping[1]=0; + mapping[2]=0; + dec = opus_multistream_decoder_create(48000, 3, 2, 1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_OK) || dec==NULL)test_failed(); + cfgs++; + opus_multistream_decoder_destroy(dec); + cfgs++; + + VG_UNDEF(ret_err,sizeof(*ret_err)); + mapping[0]=0; + mapping[1]=255; + mapping[2]=1; + mapping[3]=2; + mapping[4]=3; + dec = opus_multistream_decoder_create(48001, 5, 4, 1, mapping, ret_err); + if(ret_err){VG_CHECK(ret_err,sizeof(*ret_err));} + if((ret_err && *ret_err!=OPUS_BAD_ARG) || dec!=NULL)test_failed(); + cfgs++; + } VG_UNDEF(&err,sizeof(err)); mapping[0]=0; @@ -1061,6 +1086,9 @@ opus_int32 test_enc_api(void) enc = opus_encoder_create(fs, c, OPUS_APPLICATION_VOIP, &err); if(err!=OPUS_BAD_ARG || enc!=NULL)test_failed(); cfgs++; + enc = opus_encoder_create(fs, c, OPUS_APPLICATION_VOIP, 0); + if(enc!=NULL)test_failed(); + cfgs++; opus_encoder_destroy(enc); enc=malloc(opus_encoder_get_size(2)); if(enc==NULL)test_failed(); @@ -1538,7 +1566,7 @@ int test_repacketizer_api(void) #ifdef MALLOC_FAIL /* GLIBC 2.14 declares __malloc_hook as deprecated, generating a warning * under GCC. However, this is the cleanest way to test malloc failure - * handling in our codebase, and the lack of thread saftey isn't an + * handling in our codebase, and the lack of thread safety isn't an * issue here. We therefore disable the warning for this function. */ #if OPUS_GNUC_PREREQ(4,6) diff --git a/tests/test_opus_decode.c b/tests/test_opus_decode.c index 2c6a872..e2c04c2 100644 --- a/tests/test_opus_decode.c +++ b/tests/test_opus_decode.c @@ -38,13 +38,15 @@ #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) -extern int jackpot; int test_decoder_code0(int no_fuzz) { @@ -102,22 +104,27 @@ int test_decoder_code0(int no_fuzz) int factor=48000/fsv[t>>1]; for(fec=0;fec<2;fec++) { + int dur; /*Test PLC on a fresh decoder*/ - out_samples = opus_decode(dec[t], 0, 0, outbuf, MAX_FRAME_SAMP, fec); + 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 null pointer input*/ - out_samples = opus_decode(dec[t], 0, -1, outbuf, MAX_FRAME_SAMP, fec); + 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, MAX_FRAME_SAMP, fec); + 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, MAX_FRAME_SAMP, fec); + 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, MAX_FRAME_SAMP, fec); + 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, MAX_FRAME_SAMP, fec); + out_samples = opus_decode(dec[t], packet, 0, outbuf, 120/factor, fec); if(out_samples!=120/factor)test_failed(); /*Zero buffer*/ @@ -149,6 +156,7 @@ int test_decoder_code0(int no_fuzz) /*Count code 0 tests*/ for(i=0;i<64;i++) { + int dur; int j,expected[5*2]; packet[0]=i<<2; packet[1]=255; @@ -168,6 +176,8 @@ int test_decoder_code0(int no_fuzz) { 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(); @@ -179,8 +189,10 @@ int test_decoder_code0(int no_fuzz) /* 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, MAX_FRAME_SAMP, 0); + 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. */ @@ -188,6 +200,8 @@ int test_decoder_code0(int no_fuzz) { 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(); @@ -289,17 +303,20 @@ int test_decoder_code0(int no_fuzz) 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, MAX_FRAME_SAMP, 1)!=expected[0])test_failed(); + 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++) { + int 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); diff --git a/tests/test_opus_encode.c b/tests/test_opus_encode.c index ad63453..b80def3 100644 --- a/tests/test_opus_encode.c +++ b/tests/test_opus_encode.c @@ -38,6 +38,9 @@ #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" @@ -141,11 +144,44 @@ int run_test1(int no_fuzz) 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(); @@ -233,7 +269,7 @@ int run_test1(int no_fuzz) 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, MAX_FRAME_SAMP, (fast_rand()&3)!=0); + 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(); @@ -281,8 +317,8 @@ int run_test1(int no_fuzz) 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, MAX_FRAME_SAMP, (fast_rand()&3)!=0); - if(loss?out_samples<120:out_samples!=(frame_size*6))test_failed(); + 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)); diff --git a/version.mk b/version.mk new file mode 100644 index 0000000..ef30573 --- /dev/null +++ b/version.mk @@ -0,0 +1,2 @@ +# static version string; update manually every release. +OPUS_VERSION = "1.0.2" diff --git a/win32/config.h b/win32/config.h index 6d32620..8450d23 100644 --- a/win32/config.h +++ b/win32/config.h @@ -1,10 +1,36 @@ +/*********************************************************************** +Copyright (c) 2011, Skype Limited. All rights reserved. +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. +***********************************************************************/ + #ifndef CONFIG_H #define CONFIG_H #define CELT_BUILD 1 #define inline __inline -#define getpid _getpid #define USE_ALLOCA 1 |