summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2012-09-15 18:15:16 -0400
committerJean-Marc Valin <jmvalin@jmvalin.ca>2012-09-15 18:15:16 -0400
commit67461be16f7d7e7052b859a7aa6dc20f3a7417bd (patch)
treeaa4a36168a7f789c82d4eeb780bbab4e513a8eba
parent454d3d595923306503fdcf083258f9558742d30d (diff)
parent02c653fa0c60e348f5a09f82f66935c5bc470583 (diff)
downloadopus-merge_attempt.tar.gz
Merge branch 'exp_analysis7' into mastermerge_attempt
Conflicts: celt/celt.c celt/mdct.c include/opus_defines.h
-rw-r--r--.gitignore20
-rw-r--r--AUTHORS6
-rw-r--r--Makefile.am43
-rw-r--r--Makefile.unix (renamed from Makefile.draft)3
-rw-r--r--README72
-rw-r--r--celt/_kiss_fft_guts.h1
-rw-r--r--celt/bands.c20
-rw-r--r--celt/bands.h4
-rw-r--r--celt/celt.c44
-rw-r--r--celt/celt.h4
-rw-r--r--celt/celt.vcxproj87
-rw-r--r--celt/celt.vcxproj.filters8
-rw-r--r--celt/cwrs.c5
-rw-r--r--celt/fixed_debug.h88
-rw-r--r--celt/float_cast.h6
-rw-r--r--celt/kiss_fft.c2
-rw-r--r--celt/mdct.c58
-rw-r--r--celt/mdct.h11
-rw-r--r--celt/pitch.c4
-rw-r--r--celt/pitch.h4
-rw-r--r--celt/tests/test_unit_mathops.c16
-rw-r--r--celt/vq.c2
-rw-r--r--configure.ac78
-rw-r--r--doc/Makefile.am2
-rwxr-xr-xdoc/build_draft.sh4
-rw-r--r--doc/draft-terriberry-oggopus.xml205
-rw-r--r--include/opus.h450
-rw-r--r--include/opus_custom.h4
-rw-r--r--include/opus_defines.h346
-rw-r--r--include/opus_multistream.h610
-rw-r--r--opus.m4117
-rw-r--r--silk/API.h10
-rw-r--r--silk/PLC.c13
-rw-r--r--silk/control_codec.c12
-rw-r--r--silk/dec_API.c25
-rw-r--r--silk/decode_core.c16
-rw-r--r--silk/decode_frame.c27
-rw-r--r--silk/enc_API.c10
-rw-r--r--silk/fixed/apply_sine_window_FIX.c2
-rw-r--r--silk/fixed/silk_fixed.vcxproj24
-rw-r--r--silk/float/prefilter_FLP.c2
-rw-r--r--silk/float/silk_float.vcxproj77
-rw-r--r--silk/log2lin.c2
-rw-r--r--silk/resampler_rom.c10
-rw-r--r--silk/resampler_rom.h8
-rw-r--r--silk/silk_common.vcxproj80
-rw-r--r--silk/tables_LTP.c18
-rw-r--r--silk/tables_NLSF_CB_NB_MB.c14
-rw-r--r--silk/tables_NLSF_CB_WB.c14
-rw-r--r--silk/tables_other.c4
-rw-r--r--src/opus.vcxproj74
-rw-r--r--src/opus.vcxproj.filters3
-rw-r--r--src/opus_decoder.c15
-rw-r--r--src/opus_demo.c18
-rw-r--r--src/opus_demo.vcxproj10
-rw-r--r--src/opus_encoder.c39
-rw-r--r--src/opus_multistream.c283
-rw-r--r--src/opus_private.h4
-rw-r--r--tests/test_opus_api.c112
-rw-r--r--tests/test_opus_api.vcxproj5
-rw-r--r--tests/test_opus_decode.c9
-rw-r--r--tests/test_opus_decode.vcxproj5
-rw-r--r--tests/test_opus_encode.c11
-rw-r--r--tests/test_opus_encode.vcxproj5
-rw-r--r--version.mk2
-rw-r--r--win32/config.h3
-rw-r--r--win32/genversion.bat46
67 files changed, 2518 insertions, 818 deletions
diff --git a/.gitignore b/.gitignore
index 3431b2f4..b7bcdcec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@ aclocal.m4
autom4te.cache
*.kdevelop.pcs
*.kdevses
+compile
config.guess
config.h
config.h.in
@@ -31,3 +32,22 @@ tools/celtenc
celt.pc
celt.spec
celt/dump_modes/dump_modes
+*.vcxproj.user
+opus.sdf
+opus.suo
+version.h
+celt/Debug
+celt/Release
+celt/x64
+silk/Debug
+silk/Release
+silk/x64
+silk/fixed/Debug
+silk/fixed/Release
+silk/fixed/x64
+silk/float/Debug
+silk/float/Release
+silk/float/x64
+src/Debug
+src/Release
+src/x64
diff --git a/AUTHORS b/AUTHORS
index 7f40ed50..b3d22a20 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,6 +1,6 @@
-Jean-Marc Valin (jean-marc.valin@octasic.com)
-Koen Vos (koen.vos@skype.net)
+Jean-Marc Valin (jmvalin@jmvalin.ca)
+Koen Vos (koenvos74@gmail.com)
Timothy Terriberry (tterribe@xiph.org)
Karsten Vandborg Sorensen (karsten.vandborg.sorensen@skype.net)
Soren Skak Jensen (ssjensen@gn.com)
-Gregory Maxwell (gmaxwell@juniper.net)
+Gregory Maxwell (greg@xiph.org)
diff --git a/Makefile.am b/Makefile.am
index 09a87c92..07876626 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,6 +22,7 @@ include silk_headers.mk
include opus_headers.mk
libopus_la_SOURCES = $(CELT_SOURCES) $(SILK_SOURCES) $(OPUS_SOURCES)
+libopus_la_LDFLAGS = -no-undefined -version-info @OPUS_LT_CURRENT@:@OPUS_LT_REVISION@:@OPUS_LT_AGE@
pkginclude_HEADERS = include/opus.h include/opus_multistream.h include/opus_types.h include/opus_defines.h
@@ -82,11 +83,39 @@ opus_custom_demo_SOURCES = celt/opus_custom_demo.c
opus_custom_demo_LDADD = libopus.la -lm
endif
-EXTRA_DIST = opus.pc.in opus-uninstalled.pc.in
+EXTRA_DIST = version.mk \
+ opus.pc.in \
+ opus-uninstalled.pc.in \
+ opus.m4 \
+ Makefile.unix \
+ tests/run_vectors.sh \
+ opus.sln \
+ celt/celt.vcxproj \
+ celt/celt.vcxproj.filters \
+ src/opus_demo.vcxproj \
+ src/opus.vcxproj \
+ src/opus.vcxproj.filters \
+ src/opus_demo.vcxproj.filters \
+ tests/test_opus_decode.vcxproj.filters \
+ tests/test_opus_decode.vcxproj \
+ tests/test_opus_encode.vcxproj.filters \
+ tests/test_opus_encode.vcxproj \
+ tests/test_opus_api.vcxproj.filters \
+ tests/test_opus_api.vcxproj \
+ silk/float/silk_float.vcxproj.filters \
+ silk/float/silk_float.vcxproj \
+ silk/fixed/silk_fixed.vcxproj.filters \
+ silk/fixed/silk_fixed.vcxproj \
+ silk/silk_common.vcxproj \
+ silk/silk_common.vcxproj.filters \
+ win32/genversion.bat \
+ win32/config.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = opus.pc
+m4datadir = $(datadir)/aclocal
+m4data_DATA = opus.m4
# Targets to build and install just the library without the docs
opus check-opus install-opus: export NO_DOXYGEN = 1
@@ -98,24 +127,24 @@ install-opus: install
# Or just the docs
docs:
- $(MAKE) $(AM_MAKEFLAGS) -C doc
+ cd doc && $(MAKE) $(AM_MAKEFLAGS)
install-docs:
- $(MAKE) $(AM_MAKEFLAGS) -C doc install
+ cd doc && $(MAKE) $(AM_MAKEFLAGS) install
# Or everything (by default)
all-local:
- @[ -n "$(NO_DOXYGEN)" ] || $(MAKE) $(AM_MAKEFLAGS) -C doc
+ @[ -n "$(NO_DOXYGEN)" ] || cd doc && $(MAKE) $(AM_MAKEFLAGS)
install-data-local:
- @[ -n "$(NO_DOXYGEN)" ] || $(MAKE) $(AM_MAKEFLAGS) -C doc install
+ @[ -n "$(NO_DOXYGEN)" ] || cd doc && $(MAKE) $(AM_MAKEFLAGS) install
clean-local:
- -$(MAKE) $(AM_MAKEFLAGS) -C doc clean
+ -cd doc && $(MAKE) $(AM_MAKEFLAGS) clean
uninstall-local:
- $(MAKE) $(AM_MAKEFLAGS) -C doc uninstall
+ cd doc && $(MAKE) $(AM_MAKEFLAGS) uninstall
.PHONY: opus check-opus install-opus docs install-docs
diff --git a/Makefile.draft b/Makefile.unix
index 440118b9..88637c1a 100644
--- a/Makefile.draft
+++ b/Makefile.unix
@@ -20,7 +20,8 @@ CFLAGS := -Drestrict= $(CFLAGS)
###################### END OF OPTIONS ######################
-CFLAGS += -DOPUS_VERSION='"0.9.14"'
+include version.mk
+CFLAGS += -DOPUS_VERSION='$(OPUS_VERSION)'
include silk_sources.mk
include celt_sources.mk
include opus_sources.mk
diff --git a/README b/README
index 3d4d94b3..ea68fe30 100644
--- a/README
+++ b/README
@@ -1,3 +1,5 @@
+== Opus audio codec ==
+
Opus is a codec for interactive speech and audio transmission over the Internet.
Opus can handle a wide range of interactive audio applications, including
@@ -5,11 +7,16 @@ Voice over IP, videoconferencing, in-game chat, and even remote live music
performances. It can scale from low bit-rate narrowband speech to very high
quality stereo music.
-The IETF draft covering Opus can be found at:
- http://tools.ietf.org/id/draft-ietf-codec-opus
+ Opus, when coupled with an appropriate container format, is also suitable
+for non-realtime stored-file applications such as music distribution, game
+soundtracks, portable music players, jukeboxes, and other applications that
+have historically used high latency formats such as MP3, AAC, or Vorbis.
+
+ Opus is specified by IETF RFC 6716:
+ http://tools.ietf.org/html/rfc6716
-Opus is subject to the royalty-free patent and copyright licenses specified
-in the file COPYING.
+ The Opus format and this implementation of it are subject to the royalty-
+free patent and copyright licenses specified in the file COPYING.
This package implements a shared library for encoding and decoding raw Opus
bitstreams. Raw Opus bitstreams should be used over RTP according to
@@ -26,10 +33,14 @@ described at:
An opus-tools package is available which provides encoding and decoding of
Ogg encapsulated Opus files and includes a number of useful features.
+
Opus-tools can be found at:
- http://git.xiph.org/?p=users/greg/opus-tools.git
+ https://git.xiph.org/?p=opus-tools.git
+or on the main Opus website:
+ http://opus-codec.org/
== Compiling libopus ==
+
To build from a distribution tarball, you only need to do the following:
% ./configure
@@ -42,14 +53,14 @@ To build from the git repository, the following steps are necessary:
% git clone git://git.opus-codec.org/opus.git
% cd opus
-1) Compiling
+2) Compiling the source
% ./autogen.sh
% ./configure
% make
-Once you have compiled the codec, there will be a opus_demo executable in
-the top directory.
+Once you have compiled the codec, there will be a opus_demo executable
+in the top directory.
Usage: opus_demo [-e] <application> <sampling rate (Hz)> <channels (1/2)>
<bits per second> [options] <input> <output>
@@ -58,27 +69,32 @@ Usage: opus_demo [-e] <application> <sampling rate (Hz)> <channels (1/2)>
mode: voip | audio | restricted-lowdelay
options:
--e : only runs the encoder (output the bit-stream)
--d : only runs the decoder (reads the bit-stream as input)
--cbr : enable constant bitrate; default: variable bitrate
--cvbr : enable constrained variable bitrate; default: unconstrained
--bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband);
- default: sampling rate
--framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20
--max_payload <bytes> : maximum payload size in bytes, default: 1024
--complexity <comp> : complexity, 0 (lowest) ... 10 (highest); default: 10
--inbandfec : enable SILK inband FEC
--forcemono : force mono encoding, even for stereo input
--dtx : enable SILK DTX
--loss <perc> : simulate packet loss, in percent (0-100); default: 0
-
-input and output are little-endian signed 16-bit PCM files or opus bitstreams
-with simple opus_demo proprietary framing.
+ -e : only runs the encoder (output the bit-stream)
+ -d : only runs the decoder (reads the bit-stream as input)
+ -cbr : enable constant bitrate; default: variable bitrate
+ -cvbr : enable constrained variable bitrate; default:
+ unconstrained
+ -bandwidth <NB|MB|WB|SWB|FB>
+ : audio bandwidth (from narrowband to fullband);
+ default: sampling rate
+ -framesize <2.5|5|10|20|40|60>
+ : frame size in ms; default: 20
+ -max_payload <bytes>
+ : maximum payload size in bytes, default: 1024
+ -complexity <comp>
+ : complexity, 0 (lowest) ... 10 (highest); default: 10
+ -inbandfec : enable SILK inband FEC
+ -forcemono : force mono encoding, even for stereo input
+ -dtx : enable SILK DTX
+ -loss <perc> : simulate packet loss, in percent (0-100); default: 0
+
+input and output are little-endian signed 16-bit PCM files or opus
+bitstreams with simple opus_demo proprietary framing.
== Testing ==
This package includes a collection of automated unit and system tests
-which should be run after compiling the package especially the first
+which SHOULD be run after compiling the package especially the first
time it is run on a new platform.
To run the integrated tests:
@@ -86,10 +102,12 @@ To run the integrated tests:
There is also collection of standard test vectors which are not
included in this package for size reasons but can be obtained from:
-http://opus-codec.org/testvectors/opus_testvectors-draft11.tar.gz
+http://opus-codec.org/testvectors/opus_testvectors.tar.gz
To run compare the code to these test vectors:
-% tar -zxf opus_testvectors-draft11.tar.gz
+
+% curl -O http://opus-codec.org/testvectors/opus_testvectors.tar.gz
+% tar -zxf opus_testvectors.tar.gz
% ./tests/run_vectors.sh ./ opus_testvectors 48000
== Portability notes ==
diff --git a/celt/_kiss_fft_guts.h b/celt/_kiss_fft_guts.h
index b683467e..33e62c6b 100644
--- a/celt/_kiss_fft_guts.h
+++ b/celt/_kiss_fft_guts.h
@@ -48,7 +48,6 @@
#include "arch.h"
-# define SAMPPROD long long
#define SAMP_MAX 2147483647
#define TWID_MAX 32767
#define TRIG_UPSCALE 1
diff --git a/celt/bands.c b/celt/bands.c
index ef83a006..531d3118 100644
--- a/celt/bands.c
+++ b/celt/bands.c
@@ -126,7 +126,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
}
/* Normalise each band such that the energy is one. */
-void normalise_bands(const CELTMode *m, const celt_sig * restrict freq, celt_norm * restrict X, const celt_ener *bandE, int end, int C, int M)
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
{
int i, c, N;
const opus_int16 *eBands = m->eBands;
@@ -168,7 +168,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
}
/* Normalise each band such that the energy is one. */
-void normalise_bands(const CELTMode *m, const celt_sig * restrict freq, celt_norm * restrict X, const celt_ener *bandE, int end, int C, int M)
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
{
int i, c, N;
const opus_int16 *eBands = m->eBands;
@@ -187,15 +187,15 @@ void normalise_bands(const CELTMode *m, const celt_sig * restrict freq, celt_nor
#endif /* FIXED_POINT */
/* De-normalise the energy to produce the synthesis from the unit-energy bands */
-void denormalise_bands(const CELTMode *m, const celt_norm * restrict X, celt_sig * restrict freq, const celt_ener *bandE, int end, int C, int M)
+void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, celt_sig * OPUS_RESTRICT freq, const celt_ener *bandE, int end, int C, int M)
{
int i, c, N;
const opus_int16 *eBands = m->eBands;
N = M*m->shortMdctSize;
celt_assert2(C<=2, "denormalise_bands() not implemented for >2 channels");
c=0; do {
- celt_sig * restrict f;
- const celt_norm * restrict x;
+ celt_sig * OPUS_RESTRICT f;
+ const celt_norm * OPUS_RESTRICT x;
f = freq+c*N;
x = X+c*N;
for (i=0;i<end;i++)
@@ -412,7 +412,7 @@ int spreading_decision(const CELTMode *m, celt_norm *X, int *average,
{
int i, c, N0;
int sum = 0, nbBands=0;
- const opus_int16 * restrict eBands = m->eBands;
+ const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
int decision;
int hf_sum=0;
@@ -427,7 +427,7 @@ int spreading_decision(const CELTMode *m, celt_norm *X, int *average,
{
int j, N, tmp=0;
int tcount[3] = {0,0,0};
- celt_norm * restrict x = X+M*eBands[i]+c*N0;
+ celt_norm * OPUS_RESTRICT x = X+M*eBands[i]+c*N0;
N = M*(eBands[i+1]-eBands[i]);
if (N<=8)
continue;
@@ -1190,8 +1190,8 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
{
int i;
opus_int32 remaining_bits;
- const opus_int16 * restrict eBands = m->eBands;
- celt_norm * restrict norm, * restrict norm2;
+ const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+ celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2;
VARDECL(celt_norm, _norm);
VARDECL(celt_norm, lowband_scratch);
int B;
@@ -1221,7 +1221,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
int N;
opus_int32 curr_balance;
int effective_lowband=-1;
- celt_norm * restrict X, * restrict Y;
+ celt_norm * OPUS_RESTRICT X, * OPUS_RESTRICT Y;
int tf_change=0;
unsigned x_cm;
unsigned y_cm;
diff --git a/celt/bands.h b/celt/bands.h
index 089e210e..47d15b6d 100644
--- a/celt/bands.h
+++ b/celt/bands.h
@@ -51,14 +51,14 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
* @param X Spectrum (returned normalised)
* @param bands Square root of the energy for each band
*/
-void normalise_bands(const CELTMode *m, const celt_sig * restrict freq, celt_norm * restrict X, const celt_ener *bandE, int end, int C, int M);
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M);
/** Denormalise each band of X to restore full amplitude
* @param m Mode data
* @param X Spectrum (returned de-normalised)
* @param bands Square root of the energy for each band
*/
-void denormalise_bands(const CELTMode *m, const celt_norm * restrict X, celt_sig * restrict freq, const celt_ener *bandE, int end, int C, int M);
+void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, celt_sig * OPUS_RESTRICT freq, const celt_ener *bandE, int end, int C, int M);
#define SPREAD_NONE (0)
#define SPREAD_LIGHT (1)
diff --git a/celt/celt.c b/celt/celt.c
index 58168d96..cd783f12 100644
--- a/celt/celt.c
+++ b/celt/celt.c
@@ -297,7 +297,7 @@ static inline opus_val16 SIG2WORD16(celt_sig x)
#endif
}
-static int transient_analysis(const opus_val32 * restrict in, int len, int C,
+static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C,
int overlap, opus_val16 *tf_estimate, int *tf_chan, AnalysisInfo *analysis)
{
int i;
@@ -425,7 +425,7 @@ static int transient_analysis(const opus_val32 * restrict in, int len, int C,
/** Apply window and compute the MDCT for all sub-frames and
all channels in a frame */
-static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * restrict in, celt_sig * restrict out, int C, int LM)
+static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * OPUS_RESTRICT in, celt_sig * OPUS_RESTRICT out, int C, int LM)
{
if (C==1 && !shortBlocks)
{
@@ -454,8 +454,8 @@ static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * rest
/** Compute the IMDCT and apply window for all sub-frames and
all channels in a frame */
static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig *X,
- celt_sig * restrict out_mem[],
- celt_sig * restrict overlap_mem[], int C, int LM)
+ celt_sig * OPUS_RESTRICT out_mem[],
+ celt_sig * OPUS_RESTRICT overlap_mem[], int C, int LM)
{
int c;
const int N = mode->shortMdctSize<<LM;
@@ -500,8 +500,8 @@ static void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsa
int count=0;
c=0; do {
int j;
- celt_sig * restrict x;
- opus_val16 * restrict y;
+ celt_sig * OPUS_RESTRICT x;
+ opus_val16 * OPUS_RESTRICT y;
celt_sig m = mem[c];
x =in[c];
y = pcm+c;
@@ -992,7 +992,7 @@ static int stereo_analysis(const CELTMode *m, const celt_norm *X,
> MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR);
}
-int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
+int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
{
int i, c, N;
opus_int32 bits;
@@ -1179,8 +1179,8 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
silence = 1;
c=0; do {
int count = 0;
- const opus_val16 * restrict pcmp = pcm+c;
- celt_sig * restrict inp = in+c*(N+st->overlap)+st->overlap;
+ const opus_val16 * OPUS_RESTRICT pcmp = pcm+c;
+ celt_sig * OPUS_RESTRICT inp = in+c*(N+st->overlap)+st->overlap;
for (i=0;i<N;i++)
{
@@ -1985,13 +1985,13 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
#ifdef CUSTOM_MODES
#ifdef FIXED_POINT
-int opus_custom_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
+int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
}
#ifndef DISABLE_FLOAT_API
-int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
+int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
int j, ret, C, N;
VARDECL(opus_int16, in);
@@ -2018,7 +2018,7 @@ int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int f
#endif /* DISABLE_FLOAT_API */
#else
-int opus_custom_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
+int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
int j, ret, C, N;
VARDECL(celt_sig, in);
@@ -2043,7 +2043,7 @@ int opus_custom_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int fr
return ret;
}
-int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
+int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
}
@@ -2052,7 +2052,7 @@ int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int f
#endif /* CUSTOM_MODES */
-int opus_custom_encoder_ctl(CELTEncoder * restrict st, int request, ...)
+int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
{
va_list ap;
@@ -2335,7 +2335,7 @@ void opus_custom_decoder_destroy(CELTDecoder *st)
}
#endif /* CUSTOM_MODES */
-static void celt_decode_lost(CELTDecoder * restrict st, opus_val16 * restrict pcm, int N, int LM)
+static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_RESTRICT pcm, int N, int LM)
{
int c;
int pitch_index;
@@ -2596,7 +2596,7 @@ static void celt_decode_lost(CELTDecoder * restrict st, opus_val16 * restrict pc
RESTORE_STACK;
}
-int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, opus_val16 * restrict pcm, int frame_size, ec_dec *dec)
+int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec)
{
int c, i, N;
int spread_decision;
@@ -2978,13 +2978,13 @@ int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, in
#ifdef CUSTOM_MODES
#ifdef FIXED_POINT
-int opus_custom_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
+int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
{
return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
}
#ifndef DISABLE_FLOAT_API
-int opus_custom_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
+int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
{
int j, ret, C, N;
VARDECL(opus_int16, out);
@@ -3009,12 +3009,12 @@ int opus_custom_decode_float(CELTDecoder * restrict st, const unsigned char *dat
#else
-int opus_custom_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
+int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
{
return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
}
-int opus_custom_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
+int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
{
int j, ret, C, N;
VARDECL(celt_sig, out);
@@ -3040,7 +3040,7 @@ int opus_custom_decode(CELTDecoder * restrict st, const unsigned char *data, int
#endif
#endif /* CUSTOM_MODES */
-int opus_custom_decoder_ctl(CELTDecoder * restrict st, int request, ...)
+int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
{
va_list ap;
@@ -3152,7 +3152,7 @@ bad_request:
const char *opus_strerror(int error)
{
- static const char *error_strings[8] = {
+ static const char * const error_strings[8] = {
"success",
"invalid argument",
"buffer too small",
diff --git a/celt/celt.h b/celt/celt.h
index 3ee434e1..4c04ddba 100644
--- a/celt/celt.h
+++ b/celt/celt.h
@@ -112,7 +112,7 @@ typedef struct {
int celt_encoder_get_size(int channels);
-int celt_encode_with_ec(OpusCustomEncoder * restrict st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
+int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels);
@@ -125,7 +125,7 @@ int celt_decoder_get_size(int channels);
int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels);
-int celt_decode_with_ec(OpusCustomDecoder * restrict st, const unsigned char *data, int len, opus_val16 * restrict pcm, int frame_size, ec_dec *dec);
+int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec);
#define celt_encoder_ctl opus_custom_encoder_ctl
#define celt_decoder_ctl opus_custom_decoder_ctl
diff --git a/celt/celt.vcxproj b/celt/celt.vcxproj
index d2e084f3..b44abc33 100644
--- a/celt/celt.vcxproj
+++ b/celt/celt.vcxproj
@@ -62,28 +62,16 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
+ <CustomBuildBeforeTargets>
+ </CustomBuildBeforeTargets>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
@@ -92,11 +80,24 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../win32;../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -104,13 +105,26 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../win32;../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -129,6 +143,18 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -138,8 +164,9 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../win32;../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -147,14 +174,24 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
- <ClInclude Include="..\..\win32\config.h" />
+ <ClInclude Include="..\win32\config.h" />
<ClInclude Include="arch.h" />
<ClInclude Include="bands.h" />
<ClInclude Include="celt.h" />
- <ClInclude Include="celt_header.h" />
- <ClInclude Include="celt_types.h" />
<ClInclude Include="cwrs.h" />
<ClInclude Include="ecintrin.h" />
<ClInclude Include="entcode.h" />
diff --git a/celt/celt.vcxproj.filters b/celt/celt.vcxproj.filters
index 66e4fc56..2773bae8 100644
--- a/celt/celt.vcxproj.filters
+++ b/celt/celt.vcxproj.filters
@@ -24,12 +24,6 @@
<ClInclude Include="celt.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="celt_header.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="celt_types.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="cwrs.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -90,7 +84,7 @@
<ClInclude Include="vq.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\..\win32\config.h">
+ <ClInclude Include="..\win32\config.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
diff --git a/celt/cwrs.c b/celt/cwrs.c
index 2c31d6fe..ac81a7eb 100644
--- a/celt/cwrs.c
+++ b/celt/cwrs.c
@@ -48,8 +48,9 @@ int log2_frac(opus_uint32 val, int frac)
l=EC_ILOG(val);
if(val&(val-1)){
/*This is (val>>l-16), but guaranteed to round up, even if adding a bias
- before the shift would cause overflow (e.g., for 0xFFFFxxxx).*/
- if(l>16)val=(val>>(l-16))+(((val&((1<<(l-16))-1))+(1<<(l-16))-1)>>(l-16));
+ before the shift would cause overflow (e.g., for 0xFFFFxxxx).
+ Doesn't work for val=0, but that case fails the test above.*/
+ if(l>16)val=((val-1)>>(l-16))+1;
else val<<=16-l;
l=(l-1)<<frac;
/*Note that we always need one iteration, since the rounding up above means
diff --git a/celt/fixed_debug.h b/celt/fixed_debug.h
index ed95cba3..f11d890d 100644
--- a/celt/fixed_debug.h
+++ b/celt/fixed_debug.h
@@ -36,9 +36,9 @@
#ifdef CELT_C
#include "opus_defines.h"
-OPUS_EXPORT long long celt_mips=0;
+OPUS_EXPORT opus_int64 celt_mips=0;
#else
-extern long long celt_mips;
+extern opus_int64 celt_mips;
#endif
#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
@@ -80,9 +80,9 @@ static inline short NEG16(int x)
celt_mips++;
return res;
}
-static inline int NEG32(long long x)
+static inline int NEG32(opus_int64 x)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_INT(x))
{
fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
@@ -179,9 +179,9 @@ static inline short SHL16_(int a, int shift, char *file, int line)
return res;
}
-static inline int SHR32(long long a, int shift)
+static inline int SHR32(opus_int64 a, int shift)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
@@ -201,9 +201,9 @@ static inline int SHR32(long long a, int shift)
return res;
}
#define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
-static inline int SHL32_(long long a, int shift, char *file, int line)
+static inline int SHL32_(opus_int64 a, int shift, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", a, shift, file, line);
@@ -280,9 +280,9 @@ static inline short SUB16_(int a, int b, char *file, int line)
}
#define ADD32(a, b) ADD32_(a, b, __FILE__, __LINE__)
-static inline int ADD32_(long long a, long long b, char *file, int line)
+static inline int ADD32_(opus_int64 a, opus_int64 b, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_INT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
@@ -303,9 +303,9 @@ static inline int ADD32_(long long a, long long b, char *file, int line)
}
#define SUB32(a, b) SUB32_(a, b, __FILE__, __LINE__)
-static inline int SUB32_(long long a, long long b, char *file, int line)
+static inline int SUB32_(opus_int64 a, opus_int64 b, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_INT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
@@ -327,9 +327,9 @@ static inline int SUB32_(long long a, long long b, char *file, int line)
#undef UADD32
#define UADD32(a, b) UADD32_(a, b, __FILE__, __LINE__)
-static inline unsigned int UADD32_(unsigned long long a, unsigned long long b, char *file, int line)
+static inline unsigned int UADD32_(opus_uint64 a, opus_uint64 b, char *file, int line)
{
- unsigned long long res;
+ opus_uint64 res;
if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
{
fprintf (stderr, "UADD32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line);
@@ -351,9 +351,9 @@ static inline unsigned int UADD32_(unsigned long long a, unsigned long long b, c
#undef USUB32
#define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__)
-static inline unsigned int USUB32_(unsigned long long a, unsigned long long b, char *file, int line)
+static inline unsigned int USUB32_(opus_uint64 a, opus_uint64 b, char *file, int line)
{
- unsigned long long res;
+ opus_uint64 res;
if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
{
fprintf (stderr, "USUB32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line);
@@ -406,7 +406,7 @@ static inline short MULT16_16_16(int a, int b)
#define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__)
static inline int MULT16_16_(int a, int b, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
@@ -414,7 +414,7 @@ static inline int MULT16_16_(int a, int b, char *file, int line)
celt_assert(0);
#endif
}
- res = ((long long)a)*b;
+ res = ((opus_int64)a)*b;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
@@ -429,9 +429,9 @@ static inline int MULT16_16_(int a, int b, char *file, int line)
#define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
#define MULT16_32_QX(a, b, Q) MULT16_32_QX_(a, b, Q, __FILE__, __LINE__)
-static inline int MULT16_32_QX_(int a, long long b, int Q, char *file, int line)
+static inline int MULT16_32_QX_(int a, opus_int64 b, int Q, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
@@ -446,7 +446,7 @@ static inline int MULT16_32_QX_(int a, long long b, int Q, char *file, int line)
celt_assert(0);
#endif
}
- res = (((long long)a)*(long long)b) >> Q;
+ res = (((opus_int64)a)*(opus_int64)b) >> Q;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
@@ -462,9 +462,9 @@ static inline int MULT16_32_QX_(int a, long long b, int Q, char *file, int line)
}
#define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__)
-static inline int MULT16_32_PX_(int a, long long b, int Q, char *file, int line)
+static inline int MULT16_32_PX_(int a, opus_int64 b, int Q, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d in %s: line %d\n\n", Q, (int)a, (int)b, file, line);
@@ -472,14 +472,14 @@ static inline int MULT16_32_PX_(int a, long long b, int Q, char *file, int line)
celt_assert(0);
#endif
}
- if (ABS32(b)>=((opus_val32)(1)<<(15+Q)))
+ if (ABS32(b)>=((opus_int64)(1)<<(15+Q)))
{
- fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q, (int)a, (int)b, file, line);
+ fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q, (int)a, (int)b,file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
- res = ((((long long)a)*(long long)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
+ res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d in %s: line %d\n\n", Q, (int)a, (int)b,(int)res, file, line);
@@ -509,7 +509,7 @@ static inline int SATURATE(int a, int b)
static inline int MULT16_16_Q11_32(int a, int b)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
@@ -517,7 +517,7 @@ static inline int MULT16_16_Q11_32(int a, int b)
celt_assert(0);
#endif
}
- res = ((long long)a)*b;
+ res = ((opus_int64)a)*b;
res >>= 11;
if (!VERIFY_INT(res))
{
@@ -531,7 +531,7 @@ static inline int MULT16_16_Q11_32(int a, int b)
}
static inline short MULT16_16_Q13(int a, int b)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
@@ -539,7 +539,7 @@ static inline short MULT16_16_Q13(int a, int b)
celt_assert(0);
#endif
}
- res = ((long long)a)*b;
+ res = ((opus_int64)a)*b;
res >>= 13;
if (!VERIFY_SHORT(res))
{
@@ -553,7 +553,7 @@ static inline short MULT16_16_Q13(int a, int b)
}
static inline short MULT16_16_Q14(int a, int b)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
@@ -561,7 +561,7 @@ static inline short MULT16_16_Q14(int a, int b)
celt_assert(0);
#endif
}
- res = ((long long)a)*b;
+ res = ((opus_int64)a)*b;
res >>= 14;
if (!VERIFY_SHORT(res))
{
@@ -577,7 +577,7 @@ static inline short MULT16_16_Q14(int a, int b)
#define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
static inline short MULT16_16_Q15_(int a, int b, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
@@ -585,7 +585,7 @@ static inline short MULT16_16_Q15_(int a, int b, char *file, int line)
celt_assert(0);
#endif
}
- res = ((long long)a)*b;
+ res = ((opus_int64)a)*b;
res >>= 15;
if (!VERIFY_SHORT(res))
{
@@ -600,7 +600,7 @@ static inline short MULT16_16_Q15_(int a, int b, char *file, int line)
static inline short MULT16_16_P13(int a, int b)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
@@ -608,7 +608,7 @@ static inline short MULT16_16_P13(int a, int b)
celt_assert(0);
#endif
}
- res = ((long long)a)*b;
+ res = ((opus_int64)a)*b;
res += 4096;
if (!VERIFY_INT(res))
{
@@ -630,7 +630,7 @@ static inline short MULT16_16_P13(int a, int b)
}
static inline short MULT16_16_P14(int a, int b)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
@@ -638,7 +638,7 @@ static inline short MULT16_16_P14(int a, int b)
celt_assert(0);
#endif
}
- res = ((long long)a)*b;
+ res = ((opus_int64)a)*b;
res += 8192;
if (!VERIFY_INT(res))
{
@@ -660,7 +660,7 @@ static inline short MULT16_16_P14(int a, int b)
}
static inline short MULT16_16_P15(int a, int b)
{
- long long res;
+ opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
@@ -668,7 +668,7 @@ static inline short MULT16_16_P15(int a, int b)
celt_assert(0);
#endif
}
- res = ((long long)a)*b;
+ res = ((opus_int64)a)*b;
res += 16384;
if (!VERIFY_INT(res))
{
@@ -691,9 +691,9 @@ static inline short MULT16_16_P15(int a, int b)
#define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
-static inline int DIV32_16_(long long a, long long b, char *file, int line)
+static inline int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (b==0)
{
fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
@@ -726,9 +726,9 @@ static inline int DIV32_16_(long long a, long long b, char *file, int line)
}
#define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
-static inline int DIV32_(long long a, long long b, char *file, int line)
+static inline int DIV32_(opus_int64 a, opus_int64 b, char *file, int line)
{
- long long res;
+ opus_int64 res;
if (b==0)
{
fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
diff --git a/celt/float_cast.h b/celt/float_cast.h
index 36a13fca..5ded2915 100644
--- a/celt/float_cast.h
+++ b/celt/float_cast.h
@@ -90,14 +90,14 @@
#include <math.h>
#define float2int(x) lrint(x)
-#elif (_MSC_VER >= 1400) && (defined (WIN64) || defined (_WIN64))
+#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN64) || defined (_WIN64))
#include <xmmintrin.h>
__inline long int float2int(float value)
{
return _mm_cvtss_si32(_mm_load_ss(&value));
}
-#elif (_MSC_VER >= 1400) && (defined (WIN32) || defined (_WIN32))
+#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN32) || defined (_WIN32))
#include <math.h>
/* Win32 doesn't seem to have these functions.
@@ -127,6 +127,7 @@
#define float2int(flt) ((int)(floor(.5+flt)))
#endif
+#ifndef DISABLE_FLOAT_API
static inline opus_int16 FLOAT2INT16(float x)
{
x = x*CELT_SIG_SCALE;
@@ -134,5 +135,6 @@ static inline opus_int16 FLOAT2INT16(float x)
x = MIN32(x, 32767);
return (opus_int16)float2int(x);
}
+#endif /* DISABLE_FLOAT_API */
#endif /* FLOAT_CAST_H */
diff --git a/celt/kiss_fft.c b/celt/kiss_fft.c
index 1a2edb84..dcd69686 100644
--- a/celt/kiss_fft.c
+++ b/celt/kiss_fft.c
@@ -559,7 +559,7 @@ kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, co
st->nfft=nfft;
#ifndef FIXED_POINT
- st->scale = 1./nfft;
+ st->scale = 1.f/nfft;
#endif
if (base != NULL)
{
diff --git a/celt/mdct.c b/celt/mdct.c
index acccb8f3..b300b2b5 100644
--- a/celt/mdct.c
+++ b/celt/mdct.c
@@ -102,7 +102,7 @@ void clt_mdct_clear(mdct_lookup *l)
#endif /* CUSTOM_MODES */
/* Forward MDCT trashes the input array */
-void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * restrict out,
+void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap, int shift, int stride)
{
int i;
@@ -128,11 +128,11 @@ void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar
/* Window, shuffle, fold */
{
/* Temp pointers to make it really clear to the compiler what we're doing */
- const kiss_fft_scalar * restrict xp1 = in+(overlap>>1);
- const kiss_fft_scalar * restrict xp2 = in+N2-1+(overlap>>1);
- kiss_fft_scalar * restrict yp = f;
- const opus_val16 * restrict wp1 = window+(overlap>>1);
- const opus_val16 * restrict wp2 = window+(overlap>>1)-1;
+ const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1);
+ const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1);
+ kiss_fft_scalar * OPUS_RESTRICT yp = f;
+ const opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1);
+ const opus_val16 * OPUS_RESTRICT wp2 = window+(overlap>>1)-1;
for(i=0;i<(overlap>>2);i++)
{
/* Real part arranged as -d-cR, Imag part arranged as -b+aR*/
@@ -166,7 +166,7 @@ void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar
}
/* Pre-rotation */
{
- kiss_fft_scalar * restrict yp = f;
+ kiss_fft_scalar * OPUS_RESTRICT yp = f;
const kiss_twiddle_scalar *t = &l->trig[0];
for(i=0;i<N4;i++)
{
@@ -187,9 +187,9 @@ void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar
/* Post-rotate */
{
/* Temp pointers to make it really clear to the compiler what we're doing */
- const kiss_fft_scalar * restrict fp = f2;
- kiss_fft_scalar * restrict yp1 = out;
- kiss_fft_scalar * restrict yp2 = out+stride*(N2-1);
+ const kiss_fft_scalar * OPUS_RESTRICT fp = f2;
+ kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
+ kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1);
const kiss_twiddle_scalar *t = &l->trig[0];
/* Temp pointers to make it really clear to the compiler what we're doing */
for(i=0;i<N4;i++)
@@ -208,8 +208,8 @@ void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar
RESTORE_STACK;
}
-void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * restrict out,
- const opus_val16 * restrict window, int overlap, int shift, int stride)
+void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
+ const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride)
{
int i;
int N, N2, N4;
@@ -233,9 +233,9 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
/* Pre-rotate */
{
/* Temp pointers to make it really clear to the compiler what we're doing */
- const kiss_fft_scalar * restrict xp1 = in;
- const kiss_fft_scalar * restrict xp2 = in+stride*(N2-1);
- kiss_fft_scalar * restrict yp = f2;
+ const kiss_fft_scalar * OPUS_RESTRICT xp1 = in;
+ const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1);
+ kiss_fft_scalar * OPUS_RESTRICT yp = f2;
const kiss_twiddle_scalar *t = &l->trig[0];
for(i=0;i<N4;i++)
{
@@ -255,7 +255,7 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
/* Post-rotate */
{
- kiss_fft_scalar * restrict fp = f;
+ kiss_fft_scalar * OPUS_RESTRICT fp = f;
const kiss_twiddle_scalar *t = &l->trig[0];
for(i=0;i<N4;i++)
@@ -273,9 +273,9 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
}
/* De-shuffle the components for the middle of the window only */
{
- const kiss_fft_scalar * restrict fp1 = f;
- const kiss_fft_scalar * restrict fp2 = f+N2-1;
- kiss_fft_scalar * restrict yp = f2;
+ const kiss_fft_scalar * OPUS_RESTRICT fp1 = f;
+ const kiss_fft_scalar * OPUS_RESTRICT fp2 = f+N2-1;
+ kiss_fft_scalar * OPUS_RESTRICT yp = f2;
for(i = 0; i < N4; i++)
{
*yp++ =-*fp1;
@@ -287,11 +287,11 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
out -= (N2-overlap)>>1;
/* Mirror on both sides for TDAC */
{
- kiss_fft_scalar * restrict fp1 = f2+N4-1;
- kiss_fft_scalar * restrict xp1 = out+N2-1;
- kiss_fft_scalar * restrict yp1 = out+N4-overlap/2;
- const opus_val16 * restrict wp1 = window;
- const opus_val16 * restrict wp2 = window+overlap-1;
+ kiss_fft_scalar * OPUS_RESTRICT fp1 = f2+N4-1;
+ kiss_fft_scalar * OPUS_RESTRICT xp1 = out+N2-1;
+ kiss_fft_scalar * OPUS_RESTRICT yp1 = out+N4-overlap/2;
+ const opus_val16 * OPUS_RESTRICT wp1 = window;
+ const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
for(i = 0; i< N4-overlap/2; i++)
{
*xp1 = *fp1;
@@ -309,11 +309,11 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
}
}
{
- kiss_fft_scalar * restrict fp2 = f2+N4;
- kiss_fft_scalar * restrict xp2 = out+N2;
- kiss_fft_scalar * restrict yp2 = out+N-1-(N4-overlap/2);
- const opus_val16 * restrict wp1 = window;
- const opus_val16 * restrict wp2 = window+overlap-1;
+ kiss_fft_scalar * OPUS_RESTRICT fp2 = f2+N4;
+ kiss_fft_scalar * OPUS_RESTRICT xp2 = out+N2;
+ kiss_fft_scalar * OPUS_RESTRICT yp2 = out+N-1-(N4-overlap/2);
+ const opus_val16 * OPUS_RESTRICT wp1 = window;
+ const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
for(i = 0; i< N4-overlap/2; i++)
{
*xp2 = *fp2;
diff --git a/celt/mdct.h b/celt/mdct.h
index 5ec26d0a..d7218213 100644
--- a/celt/mdct.h
+++ b/celt/mdct.h
@@ -42,6 +42,7 @@
#ifndef MDCT_H
#define MDCT_H
+#include "opus_defines.h"
#include "kiss_fft.h"
#include "arch.h"
@@ -49,19 +50,21 @@ typedef struct {
int n;
int maxshift;
const kiss_fft_state *kfft[4];
- const kiss_twiddle_scalar * restrict trig;
+ const kiss_twiddle_scalar * OPUS_RESTRICT trig;
} mdct_lookup;
int clt_mdct_init(mdct_lookup *l,int N, int maxshift);
void clt_mdct_clear(mdct_lookup *l);
/** Compute a forward MDCT and scale by 4/N, trashes the input array */
-void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out,
+void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in,
+ kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap, int shift, int stride);
/** Compute a backward MDCT (no scaling) and performs weighted overlap-add
(scales implicitly by 1/2) */
-void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out,
- const opus_val16 * restrict window, int overlap, int shift, int stride);
+void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in,
+ kiss_fft_scalar * OPUS_RESTRICT out,
+ const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride);
#endif
diff --git a/celt/pitch.c b/celt/pitch.c
index beea61fe..d9bba1b2 100644
--- a/celt/pitch.c
+++ b/celt/pitch.c
@@ -102,7 +102,7 @@ static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
}
}
-void pitch_downsample(celt_sig * restrict x[], opus_val16 * restrict x_lp,
+void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
int len, int C)
{
int i;
@@ -169,7 +169,7 @@ void pitch_downsample(celt_sig * restrict x[], opus_val16 * restrict x_lp,
}
-void pitch_search(const opus_val16 * restrict x_lp, opus_val16 * restrict y,
+void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
int len, int max_pitch, int *pitch)
{
int i, j;
diff --git a/celt/pitch.h b/celt/pitch.h
index 2509d64b..2757071a 100644
--- a/celt/pitch.h
+++ b/celt/pitch.h
@@ -36,10 +36,10 @@
#include "modes.h"
-void pitch_downsample(celt_sig * restrict x[], opus_val16 * restrict x_lp,
+void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
int len, int C);
-void pitch_search(const opus_val16 * restrict x_lp, opus_val16 * restrict y,
+void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
int len, int max_pitch, int *pitch);
opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
diff --git a/celt/tests/test_unit_mathops.c b/celt/tests/test_unit_mathops.c
index 8119bc1e..ea0af493 100644
--- a/celt/tests/test_unit_mathops.c
+++ b/celt/tests/test_unit_mathops.c
@@ -209,10 +209,20 @@ void testilog2(void)
opus_val32 x;
for (x=1;x<=268435455;x+=127)
{
- opus_val32 error = abs(celt_ilog2(x)-(int)floor(log2(x)));
- if (error!=0)
+ opus_val32 lg;
+ opus_val32 y;
+
+ lg = celt_ilog2(x);
+ if (lg<0 || lg>=31)
+ {
+ printf("celt_ilog2 failed: 0<=celt_ilog2(x)<31 (x = %d, celt_ilog2(x) = %d)\n",x,lg);
+ ret = 1;
+ }
+ y = 1<<lg;
+
+ if (x<y || (x>>1)>=y)
{
- printf("celt_ilog2 failed: celt_ilog2(x)!=floor(log2(x)) (x = %d, error = %d)\n",x,error);
+ printf("celt_ilog2 failed: 2**celt_ilog2(x)<=x<2**(celt_ilog2(x)+1) (x = %d, 2**celt_ilog2(x) = %d)\n",x,y);
ret = 1;
}
}
diff --git a/celt/vq.c b/celt/vq.c
index a2a4fd36..98a0f36c 100644
--- a/celt/vq.c
+++ b/celt/vq.c
@@ -109,7 +109,7 @@ static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int
/** Takes the pitch vector and the decoded residual vector, computes the gain
that will give ||p+g*y||=1 and mixes the residual with the pitch. */
-static void normalise_residual(int * restrict iy, celt_norm * restrict X,
+static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
int N, opus_val32 Ryy, opus_val16 gain)
{
int i;
diff --git a/configure.ac b/configure.ac
index 330cfdeb..0773c376 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,12 +7,25 @@ AM_CONFIG_HEADER([config.h])
dnl enable silent rules on automake 1.11 and later
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-OPUS_MAJOR_VERSION=0
-OPUS_MINOR_VERSION=9
-OPUS_MICRO_VERSION=14
-OPUS_EXTRA_VERSION=
+# Read our default version string from version.mk.
+# Please update this file for releases.
+AC_MSG_CHECKING([version.mk])
+MK_VERSION=$(awk 'BEGIN { FS = "=" }
+ /OPUS_VERSION/ { ver = $2}
+ END {
+ gsub(/"/, "", ver);
+ gsub(/^ /, "", ver);
+ gsub(/ $/, "", ver);
+ print ver;
+ }' $srcdir/version.mk)
+if test -z "$MK_VERSION"; then
+ AC_MSG_RESULT([no])
+else
+ AC_MSG_RESULT([$MK_VERSION])
+ OPUS_VERSION="$MK_VERSION"
+fi
-OPUS_VERSION="$OPUS_MAJOR_VERSION.$OPUS_MINOR_VERSION.$OPUS_MICRO_VERSION$OPUS_EXTRA_VERSION"
+# Override with the git version, if available.
AC_MSG_CHECKING([git revision])
GIT_VERSION=$(git describe --tags --match 'v*' 2>/dev/null | sed 's/^v//')
if test -z "$GIT_VERSION"; then
@@ -22,24 +35,27 @@ else
OPUS_VERSION="$GIT_VERSION"
fi
+# Use 'unknown' if all else fails.
+if test -z "$OPUS_VERSION"; then
+ OPUS_VERSION="unknown"
+fi
+
# For automake.
-VERSION=$OPUS_VERSION
PACKAGE=opus
+VERSION=$OPUS_VERSION
-# For our version string.
+# For autoconf
AC_SUBST(OPUS_VERSION)
-# For config.h
-AC_DEFINE_UNQUOTED(OPUS_VERSION, "${OPUS_VERSION}", [Complete version string])
-AC_DEFINE_UNQUOTED(OPUS_MAJOR_VERSION, ${OPUS_MAJOR_VERSION}, [Version major])
-AC_DEFINE_UNQUOTED(OPUS_MINOR_VERSION, ${OPUS_MINOR_VERSION}, [Version minor])
-AC_DEFINE_UNQUOTED(OPUS_MICRO_VERSION, ${OPUS_MICRO_VERSION}, [Version micro])
-AC_DEFINE_UNQUOTED(OPUS_EXTRA_VERSION, "${OPUS_EXTRA_VERSION}", [Version extra])
+# For config.h.
+AC_DEFINE_UNQUOTED([OPUS_VERSION], ["$OPUS_VERSION"],
+ [Opus library version string])
# For libtool.
-OPUS_LT_CURRENT=0
+dnl Please update these for releases.
+OPUS_LT_CURRENT=2
OPUS_LT_REVISION=0
-OPUS_LT_AGE=0
+OPUS_LT_AGE=2
AC_SUBST(OPUS_LT_CURRENT)
AC_SUBST(OPUS_LT_REVISION)
@@ -49,6 +65,7 @@ AM_INIT_AUTOMAKE($PACKAGE, $VERSION, no-define)
AM_MAINTAINER_MODE
AC_CANONICAL_HOST
+AC_MINGW32
AM_PROG_LIBTOOL
AM_PROG_CC_C_O
@@ -137,15 +154,15 @@ has_float_approx=no
ac_enable_fixed="no";
ac_enable_float="yes";
-AC_ARG_ENABLE(fixed-point, [ --enable-fixed-point compile without floating point],
+AC_ARG_ENABLE(fixed-point, [ --enable-fixed-point compile without floating point (for machines without a fast enough FPU)],
[if test "$enableval" = yes; then
ac_enable_fixed="yes";
ac_enable_float="no";
- AC_DEFINE([FIXED_POINT], [1], [Compile as fixed-point])
+ 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])
+ AC_DEFINE([FLOATING_POINT], , [Compile as floating-point (for machines with a fast enough FPU)])
fi],
-AC_DEFINE([FLOATING_POINT], , [Compile as floating-point]))
+AC_DEFINE([FLOATING_POINT], , [Compile as floating-point (for machines with a fast enough FPU)]))
ac_enable_fixed_debug="no"
AC_ARG_ENABLE(fixed-point-debug, [ --enable-fixed-point-debug debug fixed-point implementation],
@@ -209,29 +226,6 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
CFLAGS="$saved_CFLAGS $SYMBOL_VISIBILITY"
AC_SUBST(SYMBOL_VISIBILITY)
-ac_build_stack_protector=yes
-AC_ARG_ENABLE(stack-protector,
- AS_HELP_STRING([--disable-stack-protector],[Disable compiler stack hardening]),
- [
- if test "x$enableval" = "xno"; then
- ac_build_stack_protector=$enableval
- fi
- ], [
- ac_build_stack_protector=yes
- ])
-if test "x$ac_build_stack_protector" = "xyes"; then
-if test "x$ac_cv_c_compiler_gnu" = "xyes" ; then
-saved_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -fstack-protector-all"
-AC_MSG_CHECKING([if ${CC} supports -fstack-protector-all])
-AC_LINK_IFELSE([AC_LANG_SOURCE([void main(void){char foo;}])],
- [ AC_MSG_RESULT([yes])
- STACK_PROTECTOR="-fstack-protector-all" ],
- AC_MSG_RESULT([no]))
-CFLAGS="$saved_CFLAGS $STACK_PROTECTOR"
-fi
-fi
-
CFLAGS="$CFLAGS -W"
saved_CFLAGS="$CFLAGS"
diff --git a/doc/Makefile.am b/doc/Makefile.am
index e38e8795..ba6f64c7 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -26,7 +26,7 @@ install-data-local:
done
$(INSTALL) -d $(DESTDIR)$(mandir)/man3
- cd man && find man3 -type f \
+ cd man && find man3 -type f -name opus_*.3 \
-exec $(INSTALL_DATA) \{} $(DESTDIR)$(mandir)/man3 \;
clean-local:
diff --git a/doc/build_draft.sh b/doc/build_draft.sh
index 406b2f58..618fd5d2 100755
--- a/doc/build_draft.sh
+++ b/doc/build_draft.sh
@@ -51,8 +51,8 @@ cat opus_source.tar.gz| base64 | tr -d '\n' | fold -w 64 | \
if [[ ! -d ../opus_testvectors ]] ; then
echo "Downloading test vectors..."
- wget 'http://www.opus-codec.org/testvectors/opus_testvectors-draft11.tar.gz'
- tar -C .. -xvzf opus_testvectors-draft11.tar.gz
+ wget 'http://opus-codec.org/testvectors/opus_testvectors.tar.gz'
+ tar -C .. -xvzf opus_testvectors.tar.gz
fi
echo '<figure>' > testvectors_sha1
echo '<artwork>' >> testvectors_sha1
diff --git a/doc/draft-terriberry-oggopus.xml b/doc/draft-terriberry-oggopus.xml
index d128eb46..14f962ac 100644
--- a/doc/draft-terriberry-oggopus.xml
+++ b/doc/draft-terriberry-oggopus.xml
@@ -2,7 +2,7 @@
<!DOCTYPE rfc SYSTEM 'rfc2629.dtd'>
<?rfc toc="yes" symrefs="yes" ?>
-<rfc ipr="trust200902" category="std" docName="draft-terriberry-oggopus-00">
+<rfc ipr="trust200902" category="std" docName="draft-terriberry-oggopus-01">
<front>
<title abbrev="Ogg Opus">Ogg Encapsulation for the Opus Audio Codec</title>
@@ -36,7 +36,22 @@
</address>
</author>
-<date day="3" month="July" year="2012"/>
+<author initials="R." surname="Giles" fullname="Ralph Giles">
+<organization>Mozilla Corporation</organization>
+<address>
+<postal>
+<street>163 West Hastings Street</street>
+<city>Vancouver</city>
+<region>BC</region>
+<code>V6B 1H5</code>
+<country>Canada</country>
+</postal>
+<phone>+1 604 778 1540</phone>
+<email>giles@xiph.org</email>
+</address>
+</author>
+
+<date day="16" month="July" year="2012"/>
<area>RAI</area>
<workgroup>codec</workgroup>
@@ -46,10 +61,10 @@ This document defines the Ogg encapsulation for the Opus interactive speech and
audio codec.
This allows data encoded in the Opus format to be stored in an Ogg logical
bitstream.
-This provides Opus with a long-term storage format supporting all of the
- essential features, including metadata, fast and accurate seeking, corruption
- detection, recapture after errors, low overhead, and the ability to multiplex
- Opus with other codecs (including video) with minimal buffering.
+Ogg encapsulation provides Opus with a long-term storage format supporting
+ all of the essential features, including metadata, fast and accurate seeking,
+ corruption detection, recapture after errors, low overhead, and the ability to
+ multiplex Opus with other codecs (including video) with minimal buffering.
It also provides a live streamable format, capable of delivery over a reliable
stream-oriented transport, without requiring all the data, or even the total
length of the data, up-front, in a form that is identical to the on-disk
@@ -126,7 +141,7 @@ The first packet in the logical Ogg bitstream MUST contain the identification
(ID) header, which uniquely identifies a stream as Opus audio.
The format of this header is defined in <xref target="id_header"/>.
It MUST be placed alone (without any other packet data) on the first page of
- the logical Ogg bitstream.
+ the logical Ogg bitstream, and must complete on that page.
This page MUST have its 'beginning of stream' flag set.
</t>
<t>
@@ -139,7 +154,7 @@ However many pages it spans, the comment header packet MUST finish the page on
which it completes.
</t>
<t>
-All subsequent pages are audio data pages, and the packets they contain are
+All subsequent pages are audio data pages, and the Ogg packets they contain are
audio data packets.
Each audio data packet contains one Opus packet for each of N different
streams, where N is typically one for mono or stereo, but may be greater than
@@ -149,20 +164,23 @@ The value N is specified in the ID header (see
logical Ogg bitstream.
</t>
<t>
-The first N-1 Opus packets, if any, are packed using the self-delimiting
- framing from Appendix&nbsp;B of <xref target="RFCOpus"/>.
-The remaining Opus packet is packed using the regular, undelimited framing from
- Section&nbsp;3 of <xref target="RFCOpus"/>.
+The first N-1 Opus packets, if any, are packed one after another into the Ogg
+ packet, using the self-delimiting framing from Appendix&nbsp;B of
+ <xref target="RFCOpus"/>.
+The remaining Opus packet is packed at the end of the Ogg packet using the
+ regular, undelimited framing from Section&nbsp;3 of <xref target="RFCOpus"/>.
All of the Opus packets in a single Ogg packet MUST be constrained to have the
same duration.
+The duration and coding modes of each Opus packet are contained in the
+ TOC (table of contents) sequence in the first few bytes.
A decoder SHOULD treat any Opus packet whose duration is different from that of
the first Opus packet in an Ogg packet as if it were an Opus packet with an
illegal TOC sequence.
</t>
<t>
The first audio data page SHOULD NOT have the 'continued packet' flag set
- (which would indicated the first audio data packet is continued from a
- previous page).
+ (which would indicate the first audio data packet is continued from a previous
+ page).
Packets MUST be placed into Ogg pages in order until the end of stream.
Audio packets MAY span page boundaries.
A decoder MUST treat a zero-octet audio data packet as if it were an Opus
@@ -226,6 +244,7 @@ In order to support capturing a stream that uses discontinuous transmission
not transmitted.
</t>
+<section anchor="preskip" title="Pre-skip">
<t>
There is some amount of latency introduced during the decoding process, to
allow for overlap in the MDCT modes, stereo mixing in the LP modes, and
@@ -242,7 +261,8 @@ However, a decoder will want to skip these samples after decoding them.
<t>
A 'pre-skip' field in the ID header (see <xref target="id_header"/>) signals
- the number of samples which should be skipped at the beginning of the stream.
+ the number of samples which should be skipped (decoded but discarded) at the
+ beginning of the stream.
This provides sufficient history to the decoder so that it has already
converged before the stream's output begins.
It may also be used to perform sample-accurate cropping of existing encoded
@@ -250,7 +270,9 @@ It may also be used to perform sample-accurate cropping of existing encoded
This amount need not be a multiple of 2.5&nbsp;ms, may be smaller than a single
packet, or may span the contents of several packets.
</t>
+</section>
+<section anchor="pcm_sample_position" title="PCM Sample Position">
<t>
The PCM sample position is determined from the granule position using the
formula
@@ -287,16 +309,18 @@ In this case, the PCM sample position of the first audio sample to be played
<t>
Vorbis streams use a granule position smaller than the number of audio samples
contained in the first audio data page to indicate that some of those samples
- must be trimmed from the output.
+ must be trimmed from the output (see <xref target="vorbis-trim"/>).
However, to do so, Vorbis requires that the first audio data page contains
exactly two packets, in order to allow the decoder to perform PCM position
adjustments before needing to return any PCM data.
Opus uses the pre-skip mechanism for this purpose instead, since the encoder
may introduce more than a single packet's worth of latency, and since very
- large packets in streams with a very large number of channels might not fit on
- a single page.
+ large packets in streams with a very large number of channels might not fit
+ on a single page.
</t>
+</section>
+<section title="end_trimming" title="End Trimming">
<t>
The page with the 'end of stream' flag set MAY have a granule position that
indicates the page contains less audio data than would normally be returned by
@@ -311,7 +335,10 @@ The remaining samples are discarded.
The number of discarded samples SHOULD be no larger than the number decoded
from the last packet.
</t>
+</section>
+<section anchor="start_granpos_restrictions"
+ title="Restrictions on the Initial Granule Position">
<t>
The granule position of the first audio data page with a completed packet MAY
be larger than the number of samples contained in packets that complete on
@@ -348,6 +375,32 @@ This would indicate that more samples should be skipped from the initial
</t>
</section>
+<section anchor="seeking_and_preroll" title="Seeking and Pre-roll">
+<t>
+Seeking in Ogg files is best performed using a bisection search for a page
+ whose granule position corresponds to a PCM position at or before the seek
+ target.
+With appropriately weighted bisection, accurate seeking can be performed with
+ just three or four bisections even in multi-gigabyte files.
+See <xref target="seeking"/> for general implementation guidance.
+</t>
+
+<t>
+When seeking within an Ogg Opus stream, the decoder SHOULD start decoding (and
+ discarding the output) at least 3840&nbsp;samples (80&nbsp;ms) prior to the
+ seek target in order to ensure that the output audio is correct by the time it
+ reaches the seek target.
+This 'pre-roll' is separate from, and unrelated to, the 'pre-skip' used at the
+ beginning of the stream.
+If the point 80&nbsp;ms prior to the seek target comes before the initial PCM
+ sample position, the decoder SHOULD start decoding from the beginning of the
+ stream, applying pre-skip as normal, regardless of whether the pre-skip is
+ larger or smaller than 80&nbsp;ms.
+</t>
+</section>
+
+</section>
+
<section anchor="headers" title="Header Packets">
<t>
An Opus stream contains exactly two mandatory header packets.
@@ -454,12 +507,12 @@ The original sample rate of the encoder input is not preserved by the lossy
An Ogg Opus player SHOULD select the playback sample rate according to the
following procedure:
<list style="numbers">
-<t>If the hardware supports 48&nbsp;kHz playback, decode at 48&nbsp;kHz</t>
-<t>Else if the hardware's highest available sample rate is a supported rate,
- decode at this sample rate,</t>
-<t>Else if the hardware's highest available sample rate is less than
+<t>If the hardware supports 48&nbsp;kHz playback, decode at 48&nbsp;kHz.</t>
+<t>Otherwise, if the hardware's highest available sample rate is a supported
+ rate, decode at this sample rate.</t>
+<t>Otherwise, if the hardware's highest available sample rate is less than
48&nbsp;kHz, decode at the highest supported rate above this and resample.</t>
-<t>Else decode at 48&nbsp;kHz and resample.</t>
+<t>Otherwise, decode at 48&nbsp;kHz and resample.</t>
</list>
However, the 'Input Sample Rate' field allows the encoder to pass the sample
rate of the original input stream as metadata.
@@ -523,17 +576,36 @@ Each possible value of this octet indicates a mapping family, which defines a
allowed channel count.
The details are described in <xref target="channel_mapping"/>.
</t>
+<t><spanx style="strong">Channel Mapping Table</spanx>:
+This table defines the mapping from encoded streams to output channels.
+It is omitted when the channel mapping family is 0, but REQUIRED otherwise.
+Its contents are specified in <xref target="channel_mapping"/>.
+</t>
</list>
</t>
+<t>
+All fields in the ID headers are REQUIRED, except for the channel mapping
+ table, which is omitted when the channel mapping family is 0.
+Implementations SHOULD reject ID headers which do not contain enough data for
+ these fields, even if they contain a valid Magic Signature.
+Future versions of this specification, even backwards-compatible versions,
+ might include additional fields in the ID header.
+If an ID header has a compatible major version, but a larger minor version,
+ an implementation MUST NOT reject it for containing additional data not
+ specified here.
+However, implementations MAY reject streams in which the ID header does not
+ complete on the first page.
+</t>
+
<section anchor="channel_mapping" title="Channel Mapping">
<t>
An Ogg Opus stream allows mapping one number of Opus streams (N) to a possibly
larger number of decoded channels (M+N) to yet another number of output
channels (C), which might be larger or smaller than the number of decoded
channels.
-The order and meaning these channels is defined by a channel mapping, which
- consists of the 'channel mapping family' octet and, for channel mapping
+The order and meaning of these channels are defined by a channel mapping,
+ which consists of the 'channel mapping family' octet and, for channel mapping
families other than family&nbsp;0, a channel mapping table, as illustrated in
<xref target="channel_mapping_table"/>.
</t>
@@ -639,9 +711,8 @@ When the 'channel mapping family' octet has this value, the channel mapping
<vspace blankLines="1"/>
Allowed numbers of channels: 1...8.<vspace/>
Channel meanings depend on the number of channels.
-See <xref target="vorbis-mapping">the
- Vorbis mapping</xref> for the assignments from output channel number to
- specific speaker locations.
+See <xref target="vorbis-mapping"/> for the assignments from output channel
+ number to specific speaker locations.
<vspace blankLines="1"/>
</t>
<t>Family&nbsp;255 (no defined channel meaning):
@@ -656,7 +727,7 @@ Decoders SHOULD NOT produce output for channels mapped to stream index 255
</t>
</list>
The remaining channel mapping families (2...254) are reserved.
-A decoder encountering a reserved channel mapping family value should act as
+A decoder encountering a reserved channel mapping family value SHOULD act as
though the value is 255.
<vspace blankLines="1"/>
An Ogg Opus player MUST play any Ogg Opus stream with a channel mapping family
@@ -737,9 +808,14 @@ It MUST NOT indicate that the vendor string is longer than the rest of the
<t><spanx style="strong">Vendor String</spanx> (variable length, UTF-8 vector):
<vspace blankLines="1"/>
This is a simple human-readable tag for vendor information, encoded as a UTF-8
- string.
+ string&nbsp;<xref target="RFC3629"/>.
No terminating NUL octet is required.
<vspace blankLines="1"/>
+This tag is intended to identify the codec encoder and encapsulation
+ implementations, for tracing differences in technical behavior.
+User-facing encoding applications can use the 'ENCODER' user comment tag
+ to identify themselves.
+<vspace blankLines="1"/>
</t>
<t><spanx style="strong">User Comment List Length</spanx> (32 bits, unsigned,
little endian):
@@ -771,6 +847,17 @@ There is one for each user comment indicated by the 'user comment list length'
</t>
<t>
+The vendor string length and user comment list length are REQUIRED, and
+ implementations SHOULD reject comment headers that do not contain enough data
+ for these fields, or that do not contain enough data for the corresponding
+ vendor string or user comments they describe.
+Making this check before allocating the associated memory to contain the data
+ may help prevent a possible Denial-of-Service (DoS) attack from small comment
+ headers that claim to contain strings longer than the entire packet or more
+ user comments than than could possibly fit in the packet.
+</t>
+
+<t>
The user comment strings follow the NAME=value format described by
<xref target="vorbis-comment"/> with the same recommended tag names.
One new comment tag is introduced for Ogg Opus:
@@ -812,19 +899,11 @@ There is no Opus comment tag corresponding to REPLAYGAIN_ALBUM_GAIN.
That information should instead be stored in the ID header's 'output gain'
field.
</t>
-
</section>
</section>
-<section anchor="other_implementation_notes"
- title="Other Implementation Notes">
-<t>
-When seeking within an Ogg Opus stream, the decoder should start decoding (and
- discarding the output) at least 3840&nbsp;samples (80&nbsp;ms) prior to the
- seek point in order to ensure that the output audio is correct at the seek
- point.
-</t>
+<section anchor="packet_size_limits" title="Packet Size Limits">
<t>
Technically valid Opus packets can be arbitrarily large due to the padding
format, although the amount of non-padding data they can contain is bounded.
@@ -834,7 +913,7 @@ Encoders SHOULD use no more padding than required to make a variable bitrate
Decoders SHOULD avoid attempting to allocate excessive amounts of memory when
presented with a very large packet.
The presence of an extremely large packet in the stream could indicate a
- potential memory exhaustion attack or stream corruption.
+ memory exhaustion attack or stream corruption.
Decoders SHOULD reject a packet that is too large to process, and display a
warning message.
</t>
@@ -862,7 +941,7 @@ A more reasonable limit is (7,664*N&nbsp;-&nbsp;2) octets, or about 7.5&nbsp;kB
This corresponds to 120&nbsp;ms of audio encoded as 20&nbsp;ms stereo MDCT-mode
frames, with a total bitrate just under 511&nbsp;kbps (not counting the Ogg
encapsulation overhead).
-With N=8, the maximum number of streams currently defined by mapping
+With N=8, the maximum number of channels currently defined by mapping
family&nbsp;1, this gives a maximum packet size of 61,310&nbsp;octets, or just
under 60&nbsp;kB.
This is still quite conservative, as it assumes each output channel is taken
@@ -932,10 +1011,10 @@ This document has no actions for IANA.
<section anchor="Acknowledgments" title="Acknowledgments">
<t>
-Thanks to Ralph Giles, Greg Maxwell, Christopher "Monty" Montgomery, and
- Jean-Marc Valin for their valuable contributions to this document.
-Additional thanks to Andrew D'Addesio, Ralph Giles, Greg Maxwell, and
- Vincent Penqeurc'h for their feedback based on early implementations.
+Thanks to Greg Maxwell, Christopher "Monty" Montgomery, and Jean-Marc Valin for
+ their valuable contributions to this document.
+Additional thanks to Andrew D'Addesio, Greg Maxwell, and Vincent Penqeurc'h for
+ their feedback based on early implementations.
</t>
</section>
@@ -954,6 +1033,7 @@ The authors agree to grant third parties the irrevocable right to copy, use,
<references title="Normative References">
<?rfc include="http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml"?>
+<?rfc include="http://xml.resource.org/public/rfc/bibxml/reference.RFC.3629.xml"?>
<?rfc include="http://xml.resource.org/public/rfc/bibxml/reference.RFC.3533.xml"?>
<?rfc include="http://xml.resource.org/public/rfc/bibxml/reference.RFC.5334.xml"?>
<?rfc include="http://xml.resource.org/public/rfc/bibxml/reference.RFC.6381.xml"?>
@@ -968,12 +1048,10 @@ The authors agree to grant third parties the irrevocable right to copy, use,
<seriesInfo name="RFC" value="XXXX"/>
</reference>
-<reference anchor="vorbis-mapping"
- target="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">
+<reference anchor="EBU-R128" target="http://tech.ebu.ch/loudness">
<front>
-<title>The Vorbis I Specification, Section 4.3.9 Output Channel Order</title>
-<author initials="C." surname="Montgomery"
- fullname="Christopher &quot;Monty&quot; Montgomery"/>
+<title>"Loudness Recommendation EBU R128</title>
+<author fullname="EBU Technical Committee"/>
</front>
</reference>
@@ -987,10 +1065,12 @@ The authors agree to grant third parties the irrevocable right to copy, use,
</front>
</reference>
-<reference anchor="EBU-R128" target="http://tech.ebu.ch/loudness">
+<reference anchor="vorbis-mapping"
+ target="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">
<front>
-<title>"Loudness Recommendation EBU R128</title>
-<author fullname="EBU Technical Committee"/>
+<title>The Vorbis I Specification, Section 4.3.9 Output Channel Order</title>
+<author initials="C." surname="Montgomery"
+ fullname="Christopher &quot;Monty&quot; Montgomery"/>
</front>
</reference>
@@ -1010,6 +1090,25 @@ The authors agree to grant third parties the irrevocable right to copy, use,
</front>
</reference>
+<reference anchor="seeking"
+ target="http://wiki.xiph.org/Seeking">
+<front>
+<title>Granulepos Encoding and How Seeking Really Works</title>
+<author initials="S." surname="Pfeiffer" fullname="Silvia Pfeiffer"/>
+<author initials="C." surname="Parker" fullname="Conrad Parker"/>
+<author initials="G." surname="Maxwell" fullname="Greg Maxwell"/>
+</front>
+</reference>
+
+<reference anchor="vorbis-trim"
+ target="http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-130000A.2">
+<front>
+<title>The Vorbis I Specification, Appendix A Embedding Vorbis into an Ogg stream</title>
+<author initials="C." surname="Montgomery"
+ fullname="Christopher &quot;Monty&quot; Montgomery"/>
+</front>
+</reference>
+
</references>
</back>
diff --git a/include/opus.h b/include/opus.h
index 996c2afc..c242fec0 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
*/
@@ -161,6 +162,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 +194,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 +212,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 +232,31 @@ 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, or 960.
- * 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 variable bitrate, but should
+ * not be used as the only bitrate
+ * control.
+ * @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 +267,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, or 960.
- * 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 +274,29 @@ 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 variable bitrate, but should
+ * not be used as the only bitrate
+ * control.
+ * @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 +306,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 +315,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 +340,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 or 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
@@ -328,8 +373,20 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON
* 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
* buffer is too small to hold the decoded audio.
-
-*/
+ *
+ * Opus is a stateful codec with overlapping blocks and as a result Opus
+ * packets are not coded independently of each other. Packets must be
+ * passed into the decoder serially and in the correct order for a correct
+ * decode. Lost packets can be replaced with loss concealment by calling
+ * the decoder with a null pointer and zero length for the missing packet.
+ *
+ * A single codec state may only be accessed from a single thread at
+ * a time and any required locking must be performed by the caller. Separate
+ * streams must be decoded with separate decoder states and can be decoded
+ * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
+ * defined.
+ *
+ */
/** Opus decoder state.
* This contains the complete state of an Opus decoder.
@@ -338,16 +395,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
@@ -364,13 +424,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,
@@ -378,16 +440,17 @@ 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 frame size (120 ms), this function will
+ * not be capable of decoding some packets.
+ * @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(
@@ -399,7 +462,7 @@ 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
@@ -407,7 +470,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
* 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] 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
*/
@@ -424,11 +487,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);
@@ -467,10 +535,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,27 +573,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_custom.h b/include/opus_custom.h
index 22ca318a..e7861d6f 100644
--- a/include/opus_custom.h
+++ b/include/opus_custom.h
@@ -227,7 +227,7 @@ OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
* by a convenience macro.
* @see opus_encoderctls
*/
-OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * restrict st, int request, ...) OPUS_ARG_NONNULL(1);
+OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
/* Decoder */
@@ -318,7 +318,7 @@ OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
* by a convenience macro.
* @see opus_genericctls
*/
-OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * restrict st, int request, ...) OPUS_ARG_NONNULL(1);
+OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
/**@}*/
diff --git a/include/opus_defines.h b/include/opus_defines.h
index 5155afc8..830d225f 100644
--- a/include/opus_defines.h
+++ b/include/opus_defines.h
@@ -84,6 +84,18 @@ extern "C" {
# endif
# endif
+#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if OPUS_GNUC_PREREQ(3,0)
+# define OPUS_RESTRICT __restrict__
+# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
+# define OPUS_RESTRICT __restrict
+# else
+# define OPUS_RESTRICT
+# endif
+#else
+# define OPUS_RESTRICT restrict
+#endif
+
/**Warning attributes for opus functions
* NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
* some paranoid null checks. */
@@ -99,7 +111,8 @@ extern "C" {
#endif
/** These are the actual Encoder CTL ID numbers.
- * They should not be used directly by applications. */
+ * They should not be used directly by applications.
+ * In general, SETs should be even and GETs should be odd.*/
#define OPUS_SET_APPLICATION_REQUEST 4000
#define OPUS_GET_APPLICATION_REQUEST 4001
#define OPUS_SET_BITRATE_REQUEST 4002
@@ -126,6 +139,7 @@ extern "C" {
#define OPUS_GET_SIGNAL_REQUEST 4025
#define OPUS_GET_LOOKAHEAD_REQUEST 4027
/* #define OPUS_RESET_STATE 4028 */
+#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
#define OPUS_GET_FINAL_RANGE_REQUEST 4031
#define OPUS_GET_PITCH_REQUEST 4033
#define OPUS_SET_GAIN_REQUEST 4034
@@ -159,11 +173,11 @@ extern "C" {
#define OPUS_SIGNAL_VOICE 3001 /**< Signal being encoded is voice */
#define OPUS_SIGNAL_MUSIC 3002 /**< Signal being encoded is music */
-#define OPUS_BANDWIDTH_NARROWBAND 1101 /**< 4kHz bandpass @hideinitializer*/
-#define OPUS_BANDWIDTH_MEDIUMBAND 1102 /**< 6kHz bandpass @hideinitializer*/
-#define OPUS_BANDWIDTH_WIDEBAND 1103 /**< 8kHz bandpass @hideinitializer*/
-#define OPUS_BANDWIDTH_SUPERWIDEBAND 1104 /**<12kHz bandpass @hideinitializer*/
-#define OPUS_BANDWIDTH_FULLBAND 1105 /**<20kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_NARROWBAND 1101 /**< 4 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_MEDIUMBAND 1102 /**< 6 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_WIDEBAND 1103 /**< 8 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_SUPERWIDEBAND 1104 /**<12 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_FULLBAND 1105 /**<20 kHz bandpass @hideinitializer*/
/**@}*/
@@ -182,7 +196,7 @@ extern "C" {
* ret = opus_encoder_ctl(enc_ctx, OPUS_SET_BANDWIDTH(OPUS_AUTO));
* if (ret != OPUS_OK) return ret;
*
- * int rate;
+ * opus_int32 rate;
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&rate));
*
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
@@ -194,132 +208,230 @@ extern "C" {
/** Configures the encoder's computational complexity.
* The supported range is 0-10 inclusive with 10 representing the highest complexity.
- * The default value is 10.
- * @param[in] x <tt>int</tt>: 0-10, inclusive
+ * @see OPUS_GET_COMPLEXITY
+ * @param[in] x <tt>opus_int32</tt>: Allowed values: 0-10, inclusive.
+ *
* @hideinitializer */
#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x)
-/** Gets the encoder's complexity configuration. @see OPUS_SET_COMPLEXITY
- * @param[out] x <tt>int*</tt>: 0-10, inclusive
+/** Gets the encoder's complexity configuration.
+ * @see OPUS_SET_COMPLEXITY
+ * @param[out] x <tt>opus_int32 *</tt>: Returns a value in the range 0-10,
+ * inclusive.
* @hideinitializer */
#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x)
/** Configures the bitrate in the encoder.
- * Rates from 500 to 512000 bits per second are meaningful as well as the
- * special values OPUS_BITRATE_AUTO and OPUS_BITRATE_MAX.
- * The value OPUS_BITRATE_MAX can be used to cause the codec to use as much rate
- * as it can, which is useful for controlling the rate by adjusting the output
- * buffer size.
- * @param[in] x <tt>opus_int32</tt>: bitrate in bits per second.
+ * Rates from 500 to 512000 bits per second are meaningful, as well as the
+ * special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
+ * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
+ * rate as it can, which is useful for controlling the rate by adjusting the
+ * output buffer size.
+ * @see OPUS_GET_BITRATE
+ * @param[in] x <tt>opus_int32</tt>: Bitrate in bits per second. The default
+ * is determined based on the number of
+ * channels and the input sampling rate.
* @hideinitializer */
#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x)
-/** Gets the encoder's bitrate configuration. @see OPUS_SET_BITRATE
- * @param[out] x <tt>opus_int32*</tt>: bitrate in bits per second.
+/** Gets the encoder's bitrate configuration.
+ * @see OPUS_SET_BITRATE
+ * @param[out] x <tt>opus_int32 *</tt>: Returns the bitrate in bits per second.
+ * The default is determined based on the
+ * number of channels and the input
+ * sampling rate.
* @hideinitializer */
#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x)
-/** Configures VBR in the encoder.
- * The following values are currently supported:
- * - 0 CBR
- * - 1 VBR (default)
+/** Enables or disables variable bitrate (VBR) in the encoder.
* The configured bitrate may not be met exactly because frames must
* be an integer number of bytes in length.
* @warning Only the MDCT mode of Opus can provide hard CBR behavior.
- * @param[in] x <tt>int</tt>: 0; 1 (default)
+ * @see OPUS_GET_VBR
+ * @see OPUS_SET_VBR_CONSTRAINT
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
+ * cause noticeable quality degradation.</dd>
+ * <dt>1</dt><dd>VBR (default). The exact type of VBR is controlled by
+ * #OPUS_SET_VBR_CONSTRAINT.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x)
-/** Gets the encoder's VBR configuration. @see OPUS_SET_VBR
- * @param[out] x <tt>int*</tt>: 0; 1
+/** Determine if variable bitrate (VBR) is enabled in the encoder.
+ * @see OPUS_SET_VBR
+ * @see OPUS_GET_VBR_CONSTRAINT
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>Hard CBR.</dd>
+ * <dt>1</dt><dd>VBR (default). The exact type of VBR may be retrieved via
+ * #OPUS_GET_VBR_CONSTRAINT.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x)
-/** Configures constrained VBR in the encoder.
- * The following values are currently supported:
- * - 0 Unconstrained VBR (default)
- * - 1 Maximum one frame buffering delay assuming transport with a serialization speed of the nominal bitrate
- * This setting is irrelevant when the encoder is in CBR mode.
+/** Enables or disables constrained VBR in the encoder.
+ * This setting is ignored when the encoder is in CBR mode.
* @warning Only the MDCT mode of Opus currently heeds the constraint.
* Speech mode ignores it completely, hybrid mode may fail to obey it
* if the LPC layer uses more bitrate than the constraint would have
* permitted.
- * @param[in] x <tt>int</tt>: 0 (default); 1
+ * @see OPUS_GET_VBR_CONSTRAINT
+ * @see OPUS_SET_VBR
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Unconstrained VBR.</dd>
+ * <dt>1</dt><dd>Constrained VBR (default). This creates a maximum of one
+ * frame of buffering delay assuming a transport with a
+ * serialization speed of the nominal bitrate.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x)
-/** Gets the encoder's constrained VBR configuration @see OPUS_SET_VBR_CONSTRAINT
- * @param[out] x <tt>int*</tt>: 0; 1
+/** Determine if constrained VBR is enabled in the encoder.
+ * @see OPUS_SET_VBR_CONSTRAINT
+ * @see OPUS_GET_VBR
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>Unconstrained VBR.</dd>
+ * <dt>1</dt><dd>Constrained VBR (default).</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x)
/** Configures mono/stereo forcing in the encoder.
- * This is useful when the caller knows that the input signal is currently a mono
- * source embedded in a stereo stream.
- * @param[in] x <tt>int</tt>: OPUS_AUTO (default); 1 (forced mono); 2 (forced stereo)
+ * This can force the encoder to produce packets encoded as either mono or
+ * stereo, regardless of the format of the input audio. This is useful when
+ * the caller knows that the input signal is currently a mono source embedded
+ * in a stereo stream.
+ * @see OPUS_GET_FORCE_CHANNELS
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
+ * <dt>1</dt> <dd>Forced mono</dd>
+ * <dt>2</dt> <dd>Forced stereo</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x)
-/** Gets the encoder's forced channel configuration. @see OPUS_SET_FORCE_CHANNELS
- * @param[out] x <tt>int*</tt>: OPUS_AUTO; 0; 1
+/** Gets the encoder's forced channel configuration.
+ * @see OPUS_SET_FORCE_CHANNELS
+ * @param[out] x <tt>opus_int32 *</tt>:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
+ * <dt>1</dt> <dd>Forced mono</dd>
+ * <dt>2</dt> <dd>Forced stereo</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x)
-/** Configures the encoder's maximum bandpass allowed. @see OPUS_GET_MAX_BANDWIDTH
- * The supported values are:
- * - OPUS_BANDWIDTH_NARROWBAND 4kHz passband
- * - OPUS_BANDWIDTH_MEDIUMBAND 6kHz passband
- * - OPUS_BANDWIDTH_WIDEBAND 8kHz passband
- * - OPUS_BANDWIDTH_SUPERWIDEBAND 12kHz passband
- * - OPUS_BANDWIDTH_FULLBAND 20kHz passband (default)
- * @param[in] x <tt>int</tt>: Bandwidth value
+/** Configures the maximum bandpass that the encoder will select automatically.
+ * Applications should normally use this instead of #OPUS_SET_BANDWIDTH
+ * (leaving that set to the default, #OPUS_AUTO). This allows the
+ * application to set an upper bound based on the type of input it is
+ * providing, but still gives the encoder the freedom to reduce the bandpass
+ * when the bitrate becomes too low, for better overall quality.
+ * @see OPUS_GET_MAX_BANDWIDTH
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
+ * <dt>OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
+ * <dt>OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
+ * <dt>OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+ * <dt>OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured maximum bandpass allowed. @see OPUS_SET_MAX_BANDWIDTH
- * @param[out] x <tt>int*</tt>: Bandwidth value
+/** Gets the encoder's configured maximum allowed bandpass.
+ * @see OPUS_SET_MAX_BANDWIDTH
+ * @param[out] x <tt>opus_int32 *</tt>: Allowed values:
+ * <dl>
+ * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
-/** Configures the encoder's bandpass. @see OPUS_GET_BANDWIDTH
- * The supported values are:
- * - OPUS_AUTO (default)
- * - OPUS_BANDWIDTH_NARROWBAND 4kHz passband
- * - OPUS_BANDWIDTH_MEDIUMBAND 6kHz passband
- * - OPUS_BANDWIDTH_WIDEBAND 8kHz passband
- * - OPUS_BANDWIDTH_SUPERWIDEBAND 12kHz passband
- * - OPUS_BANDWIDTH_FULLBAND 20kHz passband
- * @param[in] x <tt>int</tt>: Bandwidth value
+/** Sets the encoder's bandpass to a specific value.
+ * This prevents the encoder from automatically selecting the bandpass based
+ * on the available bitrate. If an application knows the bandpass of the input
+ * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
+ * instead, which still gives the encoder the freedom to reduce the bandpass
+ * when the bitrate becomes too low, for better overall quality.
+ * @see OPUS_GET_BANDWIDTH
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
+ * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x)
/** Configures the type of signal being encoded.
* This is a hint which helps the encoder's mode selection.
- * The supported values are:
- * - OPUS_SIGNAL_AUTO (default)
- * - OPUS_SIGNAL_VOICE
- * - OPUS_SIGNAL_MUSIC
- * @param[in] x <tt>int</tt>: Signal type
+ * @see OPUS_GET_SIGNAL
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
+ * <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
+ * <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured signal type. @see OPUS_SET_SIGNAL
- *
- * @param[out] x <tt>int*</tt>: Signal type
+/** Gets the encoder's configured signal type.
+ * @see OPUS_SET_SIGNAL
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
+ * <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
+ * <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x)
/** Configures the encoder's intended application.
* The initial value is a mandatory argument to the encoder_create function.
- * The supported values are:
- * - OPUS_APPLICATION_VOIP Process signal for improved speech intelligibility
- * - OPUS_APPLICATION_AUDIO Favor faithfulness to the original input
- * - OPUS_APPLICATION_RESTRICTED_LOWDELAY Configure the minimum possible coding delay
- *
- * @param[in] x <tt>int</tt>: Application value
+ * @see OPUS_GET_APPLICATION
+ * @param[in] x <tt>opus_int32</tt>: Returns one of the following values:
+ * <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>
* @hideinitializer */
#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured application. @see OPUS_SET_APPLICATION
- *
- * @param[out] x <tt>int*</tt>: Application value
+/** Gets the encoder's configured application.
+ * @see OPUS_SET_APPLICATION
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <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>
* @hideinitializer */
#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
+/** Gets the sampling rate the encoder or decoder was initialized with.
+ * This simply returns the <code>Fs</code> value passed to opus_encoder_init()
+ * or opus_decoder_init().
+ * @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
+ * @hideinitializer
+ */
+#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
+
/** Gets the total samples of delay added by the entire codec.
* This can be queried by the encoder and then the provided number of samples can be
* skipped on from the start of the decoder's output to provide time aligned input
@@ -331,19 +443,27 @@ extern "C" {
* version to version, or even depend on the encoder's initial configuration.
* Applications needing delay compensation should call this CTL rather than
* hard-coding a value.
- * @param[out] x <tt>int*</tt>: Number of lookahead samples
+ * @param[out] x <tt>opus_int32 *</tt>: Number of lookahead samples
* @hideinitializer */
#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
-/** Configures the encoder's use of inband forward error correction.
+/** Configures the encoder's use of inband forward error correction (FEC).
* @note This is only applicable to the LPC layer
- *
- * @param[in] x <tt>int</tt>: FEC flag, 0 (disabled) is default
+ * @see OPUS_GET_INBAND_FEC
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Disable inband FEC (default).</dd>
+ * <dt>1</dt><dd>Enable inband FEC.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
-/** Gets encoder's configured use of inband forward error correction. @see OPUS_SET_INBAND_FEC
- *
- * @param[out] x <tt>int*</tt>: FEC flag
+/** Gets encoder's configured use of inband forward error correction.
+ * @see OPUS_SET_INBAND_FEC
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>Inband FEC disabled (default).</dd>
+ * <dt>1</dt><dd>Inband FEC enabled.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
@@ -351,25 +471,34 @@ extern "C" {
* Higher values with trigger progressively more loss resistant behavior in the encoder
* at the expense of quality at a given bitrate in the lossless case, but greater quality
* under loss.
- *
- * @param[in] x <tt>int</tt>: Loss percentage in the range 0-100, inclusive.
+ * @see OPUS_GET_PACKET_LOSS_PERC
+ * @param[in] x <tt>opus_int32</tt>: Loss percentage in the range 0-100, inclusive (default: 0).
* @hideinitializer */
#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured packet loss percentage. @see OPUS_SET_PACKET_LOSS_PERC
- *
- * @param[out] x <tt>int*</tt>: Loss percentage in the range 0-100, inclusive.
+/** Gets the encoder's configured packet loss percentage.
+ * @see OPUS_SET_PACKET_LOSS_PERC
+ * @param[out] x <tt>opus_int32 *</tt>: Returns the configured loss percentage
+ * in the range 0-100, inclusive (default: 0).
* @hideinitializer */
#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x)
-/** Configures the encoder's use of discontinuous transmission.
+/** Configures the encoder's use of discontinuous transmission (DTX).
* @note This is only applicable to the LPC layer
- *
- * @param[in] x <tt>int</tt>: DTX flag, 0 (disabled) is default
+ * @see OPUS_GET_DTX
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Disable DTX (default).</dd>
+ * <dt>1</dt><dd>Enabled DTX.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x)
-/** Gets encoder's configured use of discontinuous transmission. @see OPUS_SET_DTX
- *
- * @param[out] x <tt>int*</tt>: DTX flag
+/** Gets encoder's configured use of discontinuous transmission.
+ * @see OPUS_SET_DTX
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>DTX disabled (default).</dd>
+ * <dt>1</dt><dd>DTX enabled.</dd>
+ * </dl>
* @hideinitializer */
#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x)
/**@}*/
@@ -420,7 +549,7 @@ extern "C" {
* The encoder and decoder state should be identical after coding a payload
* (assuming no data corruption or software bugs)
*
- * @param[out] x <tt>opus_uint32*</tt>: Entropy coder state
+ * @param[out] x <tt>opus_uint32 *</tt>: Entropy coder state
*
* @hideinitializer */
#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
@@ -432,25 +561,36 @@ extern "C" {
*
* This CTL is only implemented for decoder instances.
*
- * @param[out] x <tt>opus_int32*</tt>: pitch period at 48 kHz (or 0 if not available)
+ * @param[out] x <tt>opus_int32 *</tt>: pitch period at 48 kHz (or 0 if not available)
*
* @hideinitializer */
#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
-/** Gets the encoder's configured bandpass or the decoder's last bandpass. @see OPUS_SET_BANDWIDTH
- * @param[out] x <tt>int*</tt>: Bandwidth value
+/** Gets the encoder's configured bandpass or the decoder's last bandpass.
+ * @see OPUS_SET_BANDWIDTH
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
+ * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
+ * </dl>
* @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.
- * The supported values are between 8 and 24 (default)
- * @param[in] x <tt>opus_int32</tt>: Input precision
+ * @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
+/** 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)
/**@}*/
@@ -473,7 +613,7 @@ extern "C" {
#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x)
/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
*
- * @param[out] x <tt>opus_int32*</tt>: Amount to scale PCM signal by in Q8 dB units.
+ * @param[out] x <tt>opus_int32 *</tt>: Amount to scale PCM signal by in Q8 dB units.
* @hideinitializer */
#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x)
diff --git a/include/opus_multistream.h b/include/opus_multistream.h
index 5e5364a3..f476efa6 100644
--- a/include/opus_multistream.h
+++ b/include/opus_multistream.h
@@ -39,132 +39,578 @@
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 negotation.
+ *
+ * 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 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 variable bitrate, but should
+ * not be used as the only bitrate
+ * control.
+ * @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 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 variable bitrate, but should
+ * not be used as the only bitrate
+ * control.
+ * @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 frame size
+ * (120 ms), this function will not be capable
+ * of decoding some packets.
+ * @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 frame size
+ * (120 ms), this function will not be capable
+ * of decoding some packets.
+ * @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.m4 b/opus.m4
new file mode 100644
index 00000000..20f166bc
--- /dev/null
+++ b/opus.m4
@@ -0,0 +1,117 @@
+# Configure paths for libopus
+# Gregory Maxwell <greg@xiph.org> 08-30-2012
+# Shamelessly stolen from Jack Moffitt (libogg) who
+# Shamelessly stole from Owen Taylor and Manish Singh
+
+dnl XIPH_PATH_OPUS([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Test for libopus, and define OPUS_CFLAGS and OPUS_LIBS
+dnl
+AC_DEFUN([XIPH_PATH_OPUS],
+[dnl
+dnl Get the cflags and libraries
+dnl
+AC_ARG_WITH(opus,AC_HELP_STRING([--with-opus=PFX],[Prefix where opus is installed (optional)]), opus_prefix="$withval", opus_prefix="")
+AC_ARG_WITH(opus-libraries,AC_HELP_STRING([--with-opus-libraries=DIR],[Directory where the opus library is installed (optional)]), opus_libraries="$withval", opus_libraries="")
+AC_ARG_WITH(opus-includes,AC_HELP_STRING([--with-opus-includes=DIR],[Directory where the opus header files are installed (optional)]), opus_includes="$withval", opus_includes="")
+AC_ARG_ENABLE(opustest,AC_HELP_STRING([--disable-opustest],[Do not try to compile and run a test opus program]),, enable_opustest=yes)
+
+ if test "x$opus_libraries" != "x" ; then
+ OPUS_LIBS="-L$opus_libraries"
+ elif test "x$opus_prefix" = "xno" || test "x$opus_prefix" = "xyes" ; then
+ OPUS_LIBS=""
+ elif test "x$opus_prefix" != "x" ; then
+ OPUS_LIBS="-L$opus_prefix/lib"
+ elif test "x$prefix" != "xNONE" ; then
+ OPUS_LIBS="-L$prefix/lib"
+ fi
+
+ if test "x$opus_prefix" != "xno" ; then
+ OPUS_LIBS="$OPUS_LIBS -lopus"
+ fi
+
+ if test "x$opus_includes" != "x" ; then
+ OPUS_CFLAGS="-I$opus_includes"
+ elif test "x$opus_prefix" = "xno" || test "x$opus_prefix" = "xyes" ; then
+ OPUS_CFLAGS=""
+ elif test "x$opus_prefix" != "x" ; then
+ OPUS_CFLAGS="-I$opus_prefix/include"
+ elif test "x$prefix" != "xNONE"; then
+ OPUS_CFLAGS="-I$prefix/include"
+ fi
+
+ AC_MSG_CHECKING(for Opus)
+ if test "x$opus_prefix" = "xno" ; then
+ no_opus="disabled"
+ enable_opustest="no"
+ else
+ no_opus=""
+ fi
+
+
+ if test "x$enable_opustest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $OPUS_CFLAGS"
+ LIBS="$LIBS $OPUS_LIBS"
+dnl
+dnl Now check if the installed Opus is sufficiently new.
+dnl
+ rm -f conf.opustest
+ AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <opus.h>
+
+int main ()
+{
+ system("touch conf.opustest");
+ return 0;
+}
+
+],, no_opus=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+
+ if test "x$no_opus" = "xdisabled" ; then
+ AC_MSG_RESULT(no)
+ ifelse([$2], , :, [$2])
+ elif test "x$no_opus" = "x" ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$1], , :, [$1])
+ else
+ AC_MSG_RESULT(no)
+ if test -f conf.opustest ; then
+ :
+ else
+ echo "*** Could not run Opus test program, checking why..."
+ CFLAGS="$CFLAGS $OPUS_CFLAGS"
+ LIBS="$LIBS $OPUS_LIBS"
+ AC_TRY_LINK([
+#include <stdio.h>
+#include <opus.h>
+], [ return 0; ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding Opus or finding the wrong"
+ echo "*** version of Opus. If it is not finding Opus, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ 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 "*** or that you have moved Opus since it was installed." ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ OPUS_CFLAGS=""
+ OPUS_LIBS=""
+ ifelse([$2], , :, [$2])
+ fi
+ AC_SUBST(OPUS_CFLAGS)
+ AC_SUBST(OPUS_LIBS)
+ rm -f conf.opustest
+])
diff --git a/silk/API.h b/silk/API.h
index be1671d1..4b8ca12a 100644
--- a/silk/API.h
+++ b/silk/API.h
@@ -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 */
/**************************/
@@ -121,6 +113,7 @@ opus_int silk_Decode( /* O Returns error co
opus_int32 *nSamplesOut /* O Number of samples decoded */
);
+#if 0
/**************************************/
/* Get table of contents for a packet */
/**************************************/
@@ -130,6 +123,7 @@ opus_int silk_get_TOC(
const opus_int nFramesPerPayload, /* I Number of SILK frames per payload */
silk_TOC_struct *Silk_TOC /* O Type of content */
);
+#endif
#ifdef __cplusplus
}
diff --git a/silk/PLC.c b/silk/PLC.c
index 1b93d06e..906ad33c 100644
--- a/silk/PLC.c
+++ b/silk/PLC.c
@@ -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,6 +360,7 @@ 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 */
diff --git a/silk/control_codec.c b/silk/control_codec.c
index d0ed528f..ecc338ce 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 b5acb6ba..68403b7c 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,9 +353,11 @@ opus_int silk_Decode( /* O Returns error co
} else {
psDec->prev_decode_only_middle = decode_only_middle;
}
+ RESTORE_STACK;
return ret;
}
+#if 0
/* Getting table of contents for a packet */
opus_int silk_get_TOC(
const opus_uint8 *payload, /* I Payload data */
@@ -357,7 +375,7 @@ opus_int silk_get_TOC(
return -1;
}
- silk_memset( Silk_TOC, 0, sizeof( Silk_TOC ) );
+ silk_memset( Silk_TOC, 0, sizeof( *Silk_TOC ) );
/* For stereo, extract the flags for the mid channel */
flags = silk_RSHIFT( payload[ 0 ], 7 - nFramesPerPayload ) & ( silk_LSHIFT( 1, nFramesPerPayload + 1 ) - 1 );
@@ -371,3 +389,4 @@ opus_int silk_get_TOC(
return ret;
}
+#endif
diff --git a/silk/decode_core.c b/silk/decode_core.c
index 2142dd4b..0365ffdf 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 9db93d86..3e4a6e2b 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 c0143fd5..ec7915ce 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/apply_sine_window_FIX.c b/silk/fixed/apply_sine_window_FIX.c
index d996fa08..897fdc30 100644
--- a/silk/fixed/apply_sine_window_FIX.c
+++ b/silk/fixed/apply_sine_window_FIX.c
@@ -41,7 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* Matlab code for table:
for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end
*/
-static opus_int16 freq_table_Q16[ 27 ] = {
+static const opus_int16 freq_table_Q16[ 27 ] = {
12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202,
3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422,
2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702,
diff --git a/silk/fixed/silk_fixed.vcxproj b/silk/fixed/silk_fixed.vcxproj
index 69456ddc..55c76c24 100644
--- a/silk/fixed/silk_fixed.vcxproj
+++ b/silk/fixed/silk_fixed.vcxproj
@@ -63,26 +63,10 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
diff --git a/silk/float/prefilter_FLP.c b/silk/float/prefilter_FLP.c
index 95b32da5..d6c84398 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/silk_float.vcxproj b/silk/float/silk_float.vcxproj
index 42fc28e6..51a497e6 100644
--- a/silk/float/silk_float.vcxproj
+++ b/silk/float/silk_float.vcxproj
@@ -63,25 +63,11 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
+ <CustomBuildBeforeTargets>Compile</CustomBuildBeforeTargets>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -91,6 +77,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../;../fixed;../../win32;../../celt;../../include</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -99,6 +86,18 @@
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\..\win32\genversion.bat" "$(ProjectDir)..\..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -106,8 +105,9 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../;../fixed;../../win32;../../celt;../../include</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -116,6 +116,18 @@
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\..\win32\genversion.bat" "$(ProjectDir)..\..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -137,6 +149,18 @@
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\..\win32\genversion.bat" "$(ProjectDir)..\..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -146,8 +170,9 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../;../fixed;../../win32;../../celt;../../include</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -158,6 +183,18 @@
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\..\win32\genversion.bat" "$(ProjectDir)..\..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="apply_sine_window_FLP.c" />
diff --git a/silk/log2lin.c b/silk/log2lin.c
index b0026e64..33a19ad1 100644
--- a/silk/log2lin.c
+++ b/silk/log2lin.c
@@ -47,7 +47,7 @@ opus_int32 silk_log2lin(
frac_Q7 = inLog_Q7 & 0x7F;
if( inLog_Q7 < 2048 ) {
/* Piece-wise parabolic approximation */
- out = silk_ADD_RSHIFT( out, silk_MUL( out, silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 );
+ out = silk_ADD_RSHIFT32( out, silk_MUL( out, silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 );
} else {
/* Piece-wise parabolic approximation */
out = silk_MLA( out, silk_RSHIFT( out, 7 ), silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) );
diff --git a/silk/resampler_rom.c b/silk/resampler_rom.c
index a09d1880..b50af2e2 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 0ad0686b..473b24a2 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/silk_common.vcxproj b/silk/silk_common.vcxproj
index 7435e9cd..87eca609 100644
--- a/silk/silk_common.vcxproj
+++ b/silk/silk_common.vcxproj
@@ -63,25 +63,12 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
- </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
+ <CustomBuildBeforeTargets>
+ </CustomBuildBeforeTargets>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -91,6 +78,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>fixed;float;../win32;../celt;../include</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -99,6 +87,18 @@
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -106,8 +106,9 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>fixed;float;../win32;../celt;../include</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -116,6 +117,18 @@
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -127,6 +140,7 @@
<PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>fixed;float;../win32;../celt;../include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -137,6 +151,18 @@
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -146,8 +172,10 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>fixed;float;../win32;../celt;../include</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -158,6 +186,18 @@
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="A2NLSF.c" />
diff --git a/silk/tables_LTP.c b/silk/tables_LTP.c
index 5522e326..dd1fb556 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 57bb817e..75480526 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 00b68f72..3d6052e4 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 dedff26f..3dc68d47 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/src/opus.vcxproj b/src/opus.vcxproj
index de4d3ee5..a04d4c60 100644
--- a/src/opus.vcxproj
+++ b/src/opus.vcxproj
@@ -29,7 +29,7 @@
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
@@ -38,7 +38,7 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
@@ -59,30 +59,23 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
- <TargetName>$(ProjectName)</TargetName>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
- <OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
- <IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
+ <CustomBuildBeforeTargets>
+ </CustomBuildBeforeTargets>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../silk;../celt;../win32;../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
@@ -94,12 +87,24 @@
<AdditionalLibraryDirectories>$(SolutionDir)$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>celt.lib;silk_common.lib;silk_fixed.lib;silk_float.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
- <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../silk;../celt;../win32;../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
@@ -110,6 +115,18 @@
<AdditionalLibraryDirectories>$(SolutionDir)$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>celt.lib;silk_common.lib;silk_fixed.lib;silk_float.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -130,12 +147,24 @@
<AdditionalLibraryDirectories>$(SolutionDir)$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<LinkStatus>false</LinkStatus>
</Link>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
- <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../silk;../celt;../win32;../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
@@ -148,6 +177,18 @@
<AdditionalLibraryDirectories>$(SolutionDir)$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<LinkStatus>false</LinkStatus>
</Link>
+ <PreBuildEvent>
+ <Command>"$(ProjectDir)..\win32\genversion.bat" "$(ProjectDir)..\win32\version.h" OPUS_VERSION</Command>
+ <Message>Generating version.h</Message>
+ </PreBuildEvent>
+ <CustomBuildStep>
+ <Command>
+ </Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>
+ </Outputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="opus.c" />
@@ -167,6 +208,7 @@
<ClInclude Include="..\include\opus.h" />
<ClInclude Include="..\include\opus_defines.h" />
<ClInclude Include="..\include\opus_types.h" />
+ <ClInclude Include="..\include\opus_multistream.h" />
<ClInclude Include="..\win32\config.h" />
<ClInclude Include="opus_private.h" />
</ItemGroup>
diff --git a/src/opus.vcxproj.filters b/src/opus.vcxproj.filters
index d0bec0ee..1d1cd84f 100644
--- a/src/opus.vcxproj.filters
+++ b/src/opus.vcxproj.filters
@@ -68,5 +68,8 @@
<ClInclude Include="..\include\opus_types.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\include\opus_multistream.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index 58f44ac7..161bd026 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -228,6 +228,8 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
+ /* Limit frame_size to avoid excessive stack allocations. */
+ frame_size = IMIN(frame_size, st->Fs/25*3);
/* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
if (len<=1)
{
@@ -453,7 +455,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
pcm[i] = SAT16(pcm[i] + pcm_silk[i]);
#else
for (i=0;i<frame_size*st->channels;i++)
- pcm[i] = pcm[i] + (opus_val16)((1./32768.)*pcm_silk[i]);
+ pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]);
#endif
}
@@ -856,6 +858,17 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
st->frame_size = st->Fs/400;
}
break;
+ case OPUS_GET_SAMPLE_RATE_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (value==NULL)
+ {
+ ret = OPUS_BAD_ARG;
+ break;
+ }
+ *value = st->Fs;
+ }
+ break;
case OPUS_GET_PITCH_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
diff --git a/src/opus_demo.c b/src/opus_demo.c
index bc357902..1cb153a8 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;
@@ -764,7 +764,7 @@ int main(int argc, char *argv[])
}
fprintf (stderr, "average bitrate: %7.3f kb/s\n",
1e-3*bits*sampling_rate/(frame_size*(double)count));
- fprintf (stderr, "maximum bitrate: %7.3f bkp/s\n",
+ fprintf (stderr, "maximum bitrate: %7.3f kb/s\n",
1e-3*bits_max*sampling_rate/frame_size);
if (!decode_only)
fprintf (stderr, "active bitrate: %7.3f kb/s\n",
diff --git a/src/opus_demo.vcxproj b/src/opus_demo.vcxproj
index 7eb582ee..4bbea68a 100644
--- a/src/opus_demo.vcxproj
+++ b/src/opus_demo.vcxproj
@@ -39,12 +39,12 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
+ <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
+ <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
@@ -77,7 +77,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\opus.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\celt.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_common.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(SolutionDir)$(Configuration)\opus.lib;$(SolutionDir)$(Configuration)\celt.lib;$(SolutionDir)$(Configuration)\silk_common.lib;$(SolutionDir)$(Configuration)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -91,13 +91,13 @@
<PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>../silk;../celt;../win32;../include;</AdditionalIncludeDirectories>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\opus.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\celt.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_common.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(SolutionDir)$(Configuration)\opus.lib;$(SolutionDir)$(Configuration)\celt.lib;$(SolutionDir)$(Configuration)\silk_common.lib;$(SolutionDir)$(Configuration)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 7283b1cc..1e8f5972 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -294,7 +294,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] */
@@ -310,11 +310,11 @@ void silk_biquad_float(
opus_val32 inval;
opus_val32 A[2], B[3];
- A[0] = (opus_val32)(A_Q28[0] * (1./((opus_int32)1<<28)));
- A[1] = (opus_val32)(A_Q28[1] * (1./((opus_int32)1<<28)));
- B[0] = (opus_val32)(B_Q28[0] * (1./((opus_int32)1<<28)));
- B[1] = (opus_val32)(B_Q28[1] * (1./((opus_int32)1<<28)));
- B[2] = (opus_val32)(B_Q28[2] * (1./((opus_int32)1<<28)));
+ A[0] = (opus_val32)(A_Q28[0] * (1.f/((opus_int32)1<<28)));
+ A[1] = (opus_val32)(A_Q28[1] * (1.f/((opus_int32)1<<28)));
+ B[0] = (opus_val32)(B_Q28[0] * (1.f/((opus_int32)1<<28)));
+ B[1] = (opus_val32)(B_Q28[1] * (1.f/((opus_int32)1<<28)));
+ B[2] = (opus_val32)(B_Q28[2] * (1.f/((opus_int32)1<<28)));
/* Negate A_Q28 values and split in two parts */
@@ -571,16 +571,22 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8
|| (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400)))
{
+ /*If the space is too low to do something useful, emit 'PLC' frames.*/
int tocmode = st->mode;
+ int bw = st->bandwidth == 0 ? OPUS_BANDWIDTH_NARROWBAND : st->bandwidth;
if (tocmode==0)
tocmode = MODE_SILK_ONLY;
if (frame_rate>100)
tocmode = MODE_CELT_ONLY;
if (frame_rate < 50)
tocmode = MODE_SILK_ONLY;
- data[0] = gen_toc(tocmode, frame_rate,
- st->bandwidth == 0 ? OPUS_BANDWIDTH_NARROWBAND : st->bandwidth,
- st->stream_channels);
+ if(tocmode==MODE_SILK_ONLY&&bw>OPUS_BANDWIDTH_WIDEBAND)
+ bw=OPUS_BANDWIDTH_WIDEBAND;
+ else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND)
+ bw=OPUS_BANDWIDTH_NARROWBAND;
+ else if (bw<=OPUS_BANDWIDTH_SUPERWIDEBAND)
+ bw=OPUS_BANDWIDTH_SUPERWIDEBAND;
+ data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels);
RESTORE_STACK;
return 1;
}
@@ -1160,8 +1166,8 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
g1 = g1==16384 ? Q15ONE : SHL16(g1,1);
g2 = g2==16384 ? Q15ONE : SHL16(g2,1);
#else
- g1 *= (1./16384);
- g2 *= (1./16384);
+ g1 *= (1.f/16384);
+ g2 *= (1.f/16384);
#endif
stereo_fade(pcm_buf+extra_buffer*st->channels, pcm_buf+extra_buffer*st->channels, g1, g2, celt_mode->overlap,
frame_size, st->channels, celt_mode->window, st->Fs);
@@ -1610,6 +1616,17 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
*value += st->delay_compensation;
}
break;
+ case OPUS_GET_SAMPLE_RATE_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (value==NULL)
+ {
+ ret = OPUS_BAD_ARG;
+ break;
+ }
+ *value = st->Fs;
+ }
+ break;
case OPUS_GET_FINAL_RANGE_REQUEST:
{
opus_uint32 *value = va_arg(ap, opus_uint32*);
diff --git a/src/opus_multistream.c b/src/opus_multistream.c
index 8daaba56..955dc818 100644
--- a/src/opus_multistream.c
+++ b/src/opus_multistream.c
@@ -55,7 +55,6 @@ struct OpusMSDecoder {
/* Decoder states go here */
};
-
#ifdef FIXED_POINT
#define opus_encode_native opus_encode
#else
@@ -163,6 +162,10 @@ int opus_multistream_encoder_init(
int i;
char *ptr;
+ if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
+ (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
+ return OPUS_BAD_ARG;
+
st->layout.nb_channels = channels;
st->layout.nb_streams = streams;
st->layout.nb_coupled_streams = coupled_streams;
@@ -217,23 +220,31 @@ OpusMSEncoder *opus_multistream_encoder_create(
return st;
}
+typedef void (*opus_copy_channel_in_func)(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size
+);
+
/* Max size in case the encoder decides to return three frames */
#define MS_FRAME_TMP (3*1275+7)
-#ifdef FIXED_POINT
-int opus_multistream_encode(
-#else
-int opus_multistream_encode_float(
-#endif
+static int opus_multistream_encode_native
+(
OpusMSEncoder *st,
- const opus_val16 *pcm,
+ opus_copy_channel_in_func copy_channel_in,
+ const void *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
)
{
+ opus_int32 Fs;
int coupled_size;
int mono_size;
- int s, i;
+ int s;
char *ptr;
int tot_size;
VARDECL(opus_val16, buf);
@@ -241,8 +252,18 @@ int opus_multistream_encode_float(
OpusRepacketizer rp;
ALLOC_STACK;
- ALLOC(buf, 2*frame_size, opus_val16);
ptr = (char*)st + align(sizeof(OpusMSEncoder));
+ opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
+ /* Validate frame_size before using it to allocate stack space.
+ This mirrors the checks in opus_encode[_float](). */
+ if (400*frame_size != Fs && 200*frame_size != Fs &&
+ 100*frame_size != Fs && 50*frame_size != Fs &&
+ 25*frame_size != Fs && 50*frame_size != 3*Fs)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ ALLOC(buf, 2*frame_size, opus_val16);
coupled_size = opus_encoder_get_size(2);
mono_size = opus_encoder_get_size(1);
@@ -266,16 +287,15 @@ int opus_multistream_encode_float(
int left, right;
left = get_left_channel(&st->layout, s, -1);
right = get_right_channel(&st->layout, s, -1);
- for (i=0;i<frame_size;i++)
- {
- buf[2*i] = pcm[st->layout.nb_channels*i+left];
- buf[2*i+1] = pcm[st->layout.nb_channels*i+right];
- }
+ (*copy_channel_in)(buf, 2,
+ pcm, st->layout.nb_channels, left, frame_size);
+ (*copy_channel_in)(buf+1, 2,
+ pcm, st->layout.nb_channels, right, frame_size);
ptr += align(coupled_size);
} else {
int chan = get_mono_channel(&st->layout, s, -1);
- for (i=0;i<frame_size;i++)
- buf[i] = pcm[st->layout.nb_channels*i+chan];
+ (*copy_channel_in)(buf, 1,
+ pcm, st->layout.nb_channels, chan, frame_size);
ptr += align(mono_size);
}
/* number of bytes left (+Toc) */
@@ -302,7 +322,60 @@ int opus_multistream_encode_float(
}
+#if !defined(DISABLE_FLOAT_API)
+static void opus_copy_channel_in_float(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size
+)
+{
+ const float *float_src;
+ int i;
+ float_src = (const float *)src;
+ for (i=0;i<frame_size;i++)
+#if defined(FIXED_POINT)
+ dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
+#else
+ dst[i*dst_stride] = float_src[i*src_stride+src_channel];
+#endif
+}
+#endif
+
+static void opus_copy_channel_in_short(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size
+)
+{
+ const opus_int16 *short_src;
+ int i;
+ short_src = (const opus_int16 *)src;
+ for (i=0;i<frame_size;i++)
+#if defined(FIXED_POINT)
+ dst[i*dst_stride] = short_src[i*src_stride+src_channel];
+#else
+ dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
+#endif
+}
+
#ifdef FIXED_POINT
+int opus_multistream_encode(
+ OpusMSEncoder *st,
+ const opus_val16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+)
+{
+ return opus_multistream_encode_native(st, opus_copy_channel_in_short,
+ pcm, frame_size, data, max_data_bytes);
+}
#ifndef DISABLE_FLOAT_API
int opus_multistream_encode_float(
@@ -313,22 +386,26 @@ int opus_multistream_encode_float(
opus_int32 max_data_bytes
)
{
- int i, ret;
- VARDECL(opus_int16, in);
- ALLOC_STACK;
-
- ALLOC(in, frame_size*st->layout.nb_channels, opus_int16);
-
- for (i=0;i<frame_size*st->layout.nb_channels;i++)
- in[i] = FLOAT2INT16(pcm[i]);
- ret = opus_multistream_encode(st, in, frame_size, data, max_data_bytes);
- RESTORE_STACK;
- return ret;
+ return opus_multistream_encode_native(st, opus_copy_channel_in_float,
+ pcm, frame_size, data, max_data_bytes);
}
#endif
#else
+int opus_multistream_encode_float
+(
+ OpusMSEncoder *st,
+ const opus_val16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+)
+{
+ return opus_multistream_encode_native(st, opus_copy_channel_in_float,
+ pcm, frame_size, data, max_data_bytes);
+}
+
int opus_multistream_encode(
OpusMSEncoder *st,
const opus_int16 *pcm,
@@ -337,19 +414,9 @@ int opus_multistream_encode(
opus_int32 max_data_bytes
)
{
- int i, ret;
- VARDECL(float, in);
- ALLOC_STACK;
-
- ALLOC(in, frame_size*st->layout.nb_channels, float);
-
- for (i=0;i<frame_size*st->layout.nb_channels;i++)
- in[i] = (1./32768)*pcm[i];
- ret = opus_multistream_encode_float(st, in, frame_size, data, max_data_bytes);
- RESTORE_STACK;
- return ret;
+ return opus_multistream_encode_native(st, opus_copy_channel_in_short,
+ pcm, frame_size, data, max_data_bytes);
}
-
#endif
int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
@@ -414,6 +481,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
case OPUS_GET_VBR_CONSTRAINT_REQUEST:
case OPUS_GET_SIGNAL_REQUEST:
case OPUS_GET_LOOKAHEAD_REQUEST:
+ case OPUS_GET_SAMPLE_RATE_REQUEST:
case OPUS_GET_INBAND_FEC_REQUEST:
{
OpusEncoder *enc;
@@ -536,6 +604,10 @@ int opus_multistream_decoder_init(
int i, ret;
char *ptr;
+ if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
+ (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
+ return OPUS_BAD_ARG;
+
st->layout.nb_channels = channels;
st->layout.nb_streams = streams;
st->layout.nb_coupled_streams = coupled_streams;
@@ -595,23 +667,37 @@ OpusMSDecoder *opus_multistream_decoder_create(
}
+typedef void (*opus_copy_channel_out_func)(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size
+);
+
static int opus_multistream_decode_native(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
- opus_val16 *pcm,
+ void *pcm,
+ opus_copy_channel_out_func copy_channel_out,
int frame_size,
int decode_fec
)
{
+ opus_int32 Fs;
int coupled_size;
int mono_size;
- int s, i, c;
+ int s, c;
char *ptr;
int do_plc=0;
VARDECL(opus_val16, buf);
ALLOC_STACK;
+ /* Limit frame_size to avoid excessive stack allocations. */
+ opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
+ frame_size = IMIN(frame_size, Fs/25*3);
ALLOC(buf, 2*frame_size, opus_val16);
ptr = (char*)st + align(sizeof(OpusMSDecoder));
coupled_size = opus_decoder_get_size(2);
@@ -663,16 +749,16 @@ static int opus_multistream_decode_native(
/* Copy "left" audio to the channel(s) where it belongs */
while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
{
- for (i=0;i<frame_size;i++)
- pcm[st->layout.nb_channels*i+chan] = buf[2*i];
+ (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+ buf, 2, frame_size);
prev = chan;
}
prev = -1;
/* Copy "right" audio to the channel(s) where it belongs */
while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
{
- for (i=0;i<frame_size;i++)
- pcm[st->layout.nb_channels*i+chan] = buf[2*i+1];
+ (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+ buf+1, 2, frame_size);
prev = chan;
}
} else {
@@ -681,8 +767,8 @@ static int opus_multistream_decode_native(
/* Copy audio to the channel(s) where it belongs */
while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
{
- for (i=0;i<frame_size;i++)
- pcm[st->layout.nb_channels*i+chan] = buf[i];
+ (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+ buf, 1, frame_size);
prev = chan;
}
}
@@ -692,14 +778,74 @@ static int opus_multistream_decode_native(
{
if (st->layout.mapping[c] == 255)
{
- for (i=0;i<frame_size;i++)
- pcm[st->layout.nb_channels*i+c] = 0;
+ (*copy_channel_out)(pcm, st->layout.nb_channels, c,
+ NULL, 0, frame_size);
}
}
RESTORE_STACK;
return frame_size;
}
+#if !defined(DISABLE_FLOAT_API)
+static void opus_copy_channel_out_float(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size
+)
+{
+ float *float_dst;
+ int i;
+ float_dst = (float*)dst;
+ if (src != NULL)
+ {
+ for (i=0;i<frame_size;i++)
+#if defined(FIXED_POINT)
+ float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
+#else
+ float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
+#endif
+ }
+ else
+ {
+ for (i=0;i<frame_size;i++)
+ float_dst[i*dst_stride+dst_channel] = 0;
+ }
+}
+#endif
+
+static void opus_copy_channel_out_short(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size
+)
+{
+ opus_int16 *short_dst;
+ int i;
+ short_dst = (opus_int16*)dst;
+ if (src != NULL)
+ {
+ for (i=0;i<frame_size;i++)
+#if defined(FIXED_POINT)
+ short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
+#else
+ short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
+#endif
+ }
+ else
+ {
+ for (i=0;i<frame_size;i++)
+ short_dst[i*dst_stride+dst_channel] = 0;
+ }
+}
+
+
+
#ifdef FIXED_POINT
int opus_multistream_decode(
OpusMSDecoder *st,
@@ -710,27 +856,16 @@ int opus_multistream_decode(
int decode_fec
)
{
- return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
+ return opus_multistream_decode_native(st, data, len,
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec);
}
#ifndef DISABLE_FLOAT_API
int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
- VARDECL(opus_int16, out);
- int ret, i;
- ALLOC_STACK;
-
- ALLOC(out, frame_size*st->layout.nb_channels, opus_int16);
-
- ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
- if (ret > 0)
- {
- for (i=0;i<ret*st->layout.nb_channels;i++)
- pcm[i] = (1./32768.)*(out[i]);
- }
- RESTORE_STACK;
- return ret;
+ return opus_multistream_decode_native(st, data, len,
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec);
}
#endif
@@ -739,20 +874,8 @@ int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
{
- VARDECL(float, out);
- int ret, i;
- ALLOC_STACK;
-
- ALLOC(out, frame_size*st->layout.nb_channels, float);
-
- ret = opus_multistream_decode_native(st, data, len, out, frame_size, decode_fec);
- if (ret > 0)
- {
- for (i=0;i<ret*st->layout.nb_channels;i++)
- pcm[i] = FLOAT2INT16(out[i]);
- }
- RESTORE_STACK;
- return ret;
+ return opus_multistream_decode_native(st, data, len,
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec);
}
int opus_multistream_decode_float(
@@ -764,7 +887,8 @@ int opus_multistream_decode_float(
int decode_fec
)
{
- return opus_multistream_decode_native(st, data, len, pcm, frame_size, decode_fec);
+ return opus_multistream_decode_native(st, data, len,
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec);
}
#endif
@@ -783,6 +907,7 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
switch (request)
{
case OPUS_GET_BANDWIDTH_REQUEST:
+ case OPUS_GET_SAMPLE_RATE_REQUEST:
{
OpusDecoder *dec;
/* For int32* GET params, just query the first stream */
diff --git a/src/opus_private.h b/src/opus_private.h
index 6534a5ed..52482bc1 100644
--- a/src/opus_private.h
+++ b/src/opus_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011 Xiph.Org Foundation
+/* Copyright (c) 2012 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
@@ -77,7 +77,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 le
/* Make sure everything's aligned to sizeof(void *) bytes */
static inline int align(int i)
{
- return (i+sizeof(void *)-1)&-sizeof(void *);
+ return (i+sizeof(void *)-1)&-((int)sizeof(void *));
}
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen, int self_delimited);
diff --git a/tests/test_opus_api.c b/tests/test_opus_api.c
index 66efa1bc..b5348c3a 100644
--- a/tests/test_opus_api.c
+++ b/tests/test_opus_api.c
@@ -316,7 +316,7 @@ opus_int32 test_msdec_api(void)
OpusDecoder *streamdec;
opus_int32 i,j,cfgs;
unsigned char packet[1276];
- unsigned char mapping[256] = {0,1};
+ unsigned char mapping[256];
#ifndef DISABLE_FLOAT_API
float fbuf[960*2];
#endif
@@ -328,6 +328,10 @@ opus_int32 test_msdec_api(void)
nullvalue=0;
#endif
+ mapping[0]=0;
+ mapping[1]=1;
+ for(i=2;i<256;i++)VG_UNDEF(&mapping[i],sizeof(unsigned char));
+
cfgs=0;
/*First test invalid configurations which should fail*/
fprintf(stdout,"\n Multistream decoder basic API tests\n");
@@ -373,12 +377,14 @@ 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++;
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);
@@ -386,22 +392,107 @@ opus_int32 test_msdec_api(void)
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++;
+
+ err = opus_multistream_decoder_init(dec,48000, 1, 0, 0, mapping);
+ if(err!=OPUS_BAD_ARG)test_failed();
+ cfgs++;
+
+ err = opus_multistream_decoder_init(dec,48000, 1, 1, -1, mapping);
+ if(err!=OPUS_BAD_ARG)test_failed();
+ cfgs++;
+
opus_multistream_decoder_destroy(dec);
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++;
VG_UNDEF(&err,sizeof(err));
- mapping[0]=0;
+ 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++;
+
+ 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(&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(&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(&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(&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(&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(&err,sizeof(err));
+ mapping[0]=255;
mapping[1]=1;
- dec = opus_multistream_decoder_create(48000, 2, 2, 0, mapping, &err);
+ 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(&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++;
+
+ 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(&err,sizeof(err));
+ mapping[0]=0;
+ mapping[1]=255;
+ mapping[2]=1;
+ mapping[3]=2;
+ dec = opus_multistream_decoder_create(48000, 4, 2, 1, mapping, &err);
+ VG_CHECK(&err,sizeof(err));
if(err!=OPUS_OK || dec==NULL)test_failed();
cfgs++;
@@ -460,6 +551,12 @@ opus_int32 test_msdec_api(void)
}
fprintf(stdout," OPUS_GET_GAIN ................................ OK.\n");
+ VG_UNDEF(&i,sizeof(i));
+ err=opus_multistream_decoder_ctl(dec, OPUS_GET_BANDWIDTH(&i));
+ if(err != OPUS_OK || i!=0)test_failed();
+ fprintf(stdout," OPUS_GET_BANDWIDTH ........................... OK.\n");
+ cfgs++;
+
err=opus_multistream_decoder_ctl(dec,OPUS_UNIMPLEMENTED);
if(err!=OPUS_UNIMPLEMENTED)test_failed();
fprintf(stdout," OPUS_UNIMPLEMENTED ........................... OK.\n");
@@ -467,11 +564,6 @@ opus_int32 test_msdec_api(void)
#if 0
/*Currently unimplemented for multistream*/
- VG_UNDEF(&i,sizeof(i));
- err=opus_multistream_decoder_ctl(dec, OPUS_GET_BANDWIDTH(&i));
- if(err != OPUS_OK || i!=0)test_failed();
- fprintf(stdout," OPUS_GET_BANDWIDTH ........................... OK.\n");
- cfgs++;
/*GET_PITCH has different execution paths depending on the previously decoded frame.*/
err=opus_multistream_decoder_ctl(dec, OPUS_GET_PITCH(nullvalue));
if(err!=OPUS_BAD_ARG)test_failed();
@@ -1155,6 +1247,10 @@ opus_int32 test_enc_api(void)
" OPUS_SET_SIGNAL .............................. OK.\n",
" OPUS_GET_SIGNAL .............................. OK.\n")
+ CHECK_SETGET(OPUS_SET_LSB_DEPTH(i),OPUS_GET_LSB_DEPTH(&i),7,25,16,24,
+ " OPUS_SET_LSB_DEPTH ........................... OK.\n",
+ " OPUS_GET_LSB_DEPTH ........................... OK.\n")
+
/*OPUS_SET_FORCE_MODE is not tested here because it's not a public API, however the encoder tests use it*/
if(opus_encoder_ctl(enc,OPUS_GET_FINAL_RANGE(&enc_final_range))!=OPUS_OK)test_failed();
diff --git a/tests/test_opus_api.vcxproj b/tests/test_opus_api.vcxproj
index 7a1a79d4..30ced576 100644
--- a/tests/test_opus_api.vcxproj
+++ b/tests/test_opus_api.vcxproj
@@ -58,7 +58,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\opus.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\celt.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_common.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(SolutionDir)$(Configuration)\opus.lib;$(SolutionDir)$(Configuration)\celt.lib;$(SolutionDir)$(Configuration)\silk_common.lib;$(SolutionDir)$(Configuration)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -75,10 +75,9 @@
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\opus.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\celt.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_common.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(SolutionDir)$(Configuration)\opus.lib;$(SolutionDir)$(Configuration)\celt.lib;$(SolutionDir)$(Configuration)\silk_common.lib;$(SolutionDir)$(Configuration)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/tests/test_opus_decode.c b/tests/test_opus_decode.c
index 74508a0e..2c6a872a 100644
--- a/tests/test_opus_decode.c
+++ b/tests/test_opus_decode.c
@@ -36,7 +36,7 @@
#include <math.h>
#include <string.h>
#include <time.h>
-#ifndef _WIN32
+#if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__)
#include <unistd.h>
#endif
#include "opus.h"
@@ -198,8 +198,15 @@ int test_decoder_code0(int no_fuzz)
if(no_fuzz)
{
fprintf(stdout," Skipping many tests which fuzz the decoder as requested.\n");
+ free(decbak);
for(t=0;t<5*2;t++)opus_decoder_destroy(dec[t]);
printf(" Decoders stopped.\n");
+
+ err=0;
+ for(i=0;i<8*2;i++)err|=outbuf_int[i]!=32749;
+ for(i=MAX_FRAME_SAMP*2;i<(MAX_FRAME_SAMP+8)*2;i++)err|=outbuf[i]!=32749;
+ if(err)test_failed();
+
free(outbuf_int);
free(packet);
return 0;
diff --git a/tests/test_opus_decode.vcxproj b/tests/test_opus_decode.vcxproj
index 254b5114..495f5564 100644
--- a/tests/test_opus_decode.vcxproj
+++ b/tests/test_opus_decode.vcxproj
@@ -58,7 +58,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\opus.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\celt.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_common.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(SolutionDir)$(Configuration)\opus.lib;$(SolutionDir)$(Configuration)\celt.lib;$(SolutionDir)$(Configuration)\silk_common.lib;$(SolutionDir)$(Configuration)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -75,10 +75,9 @@
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\opus.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\celt.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_common.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(SolutionDir)$(Configuration)\opus.lib;$(SolutionDir)$(Configuration)\celt.lib;$(SolutionDir)$(Configuration)\silk_common.lib;$(SolutionDir)$(Configuration)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/tests/test_opus_encode.c b/tests/test_opus_encode.c
index 7d2ad655..ad634533 100644
--- a/tests/test_opus_encode.c
+++ b/tests/test_opus_encode.c
@@ -36,7 +36,7 @@
#include <math.h>
#include <string.h>
#include <time.h>
-#ifndef _WIN32
+#if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__)
#include <unistd.h>
#endif
#include "opus_multistream.h"
@@ -113,7 +113,7 @@ int run_test1(int no_fuzz)
{
static const int fsizes[6]={960*3,960*2,120,240,480,960};
static const char *mstrings[3] = {" LP","Hybrid"," MDCT"};
- unsigned char mapping[256] = {0,1};
+ unsigned char mapping[256] = {0,1,255};
unsigned char db62[36];
opus_int32 i;
int rc,j,err;
@@ -144,13 +144,16 @@ int run_test1(int no_fuzz)
MSenc = opus_multistream_encoder_create(8000, 2, 2, 0, mapping, OPUS_APPLICATION_AUDIO, &err);
if(err != OPUS_OK || MSenc==NULL)test_failed();
+ 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();
+
dec = opus_decoder_create(48000, 2, &err);
if(err != OPUS_OK || dec==NULL)test_failed();
MSdec = opus_multistream_decoder_create(48000, 2, 2, 0, mapping, &err);
if(err != OPUS_OK || MSdec==NULL)test_failed();
- MSdec_err = opus_multistream_decoder_create(48000, 1, 2, 0, mapping, &err);
+ MSdec_err = opus_multistream_decoder_create(48000, 3, 2, 0, mapping, &err);
if(err != OPUS_OK || MSdec_err==NULL)test_failed();
dec_err[0]=(OpusDecoder *)malloc(opus_decoder_get_size(2));
@@ -178,7 +181,7 @@ int run_test1(int no_fuzz)
inbuf=(short *)malloc(sizeof(short)*SAMPLES*2);
outbuf=(short *)malloc(sizeof(short)*SAMPLES*2);
- out2buf=(short *)malloc(sizeof(short)*MAX_FRAME_SAMP*2);
+ out2buf=(short *)malloc(sizeof(short)*MAX_FRAME_SAMP*3);
if(inbuf==NULL || outbuf==NULL || out2buf==NULL)test_failed();
generate_music(inbuf,SAMPLES);
diff --git a/tests/test_opus_encode.vcxproj b/tests/test_opus_encode.vcxproj
index 2b1dfab3..7ed3ac7a 100644
--- a/tests/test_opus_encode.vcxproj
+++ b/tests/test_opus_encode.vcxproj
@@ -58,7 +58,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\opus.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\celt.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_common.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(SolutionDir)$(Configuration)\opus.lib;$(SolutionDir)$(Configuration)\celt.lib;$(SolutionDir)$(Configuration)\silk_common.lib;$(SolutionDir)$(Configuration)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -75,10 +75,9 @@
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\opus.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\celt.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_common.lib;$(SolutionDir)$(Configuration)$(PlatformArchitecture)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(SolutionDir)$(Configuration)\opus.lib;$(SolutionDir)$(Configuration)\celt.lib;$(SolutionDir)$(Configuration)\silk_common.lib;$(SolutionDir)$(Configuration)\silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/version.mk b/version.mk
new file mode 100644
index 00000000..a4fdd7f4
--- /dev/null
+++ b/version.mk
@@ -0,0 +1,2 @@
+# static version string; update manually every release.
+OPUS_VERSION = "1.0.1"
diff --git a/win32/config.h b/win32/config.h
index d95981f8..6d32620f 100644
--- a/win32/config.h
+++ b/win32/config.h
@@ -3,7 +3,6 @@
#define CELT_BUILD 1
-#define restrict
#define inline __inline
#define getpid _getpid
@@ -19,6 +18,6 @@
#pragma warning(disable : 4996)/* This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. */
#endif
-#define OPUS_VERSION "0.9.11 win32"
+#include "version.h"
#endif CONFIG_H
diff --git a/win32/genversion.bat b/win32/genversion.bat
new file mode 100644
index 00000000..7934ebfa
--- /dev/null
+++ b/win32/genversion.bat
@@ -0,0 +1,46 @@
+@echo off
+
+setlocal enableextensions enabledelayedexpansion
+
+for /f %%v in ('git describe --tags --match "v*"') do set version=%%v
+
+if not "%version%"=="" goto :gotversion
+
+if exist "%~dp0..\version.mk" goto :getversion
+
+echo Git cannot be found, nor can version.mk. Generating unknown version.
+
+set version=unknown
+
+goto :gotversion
+
+:getversion
+
+for /f "delims== tokens=2" %%v in (%~dp0..\version.mk) do set version=%%v
+
+set version=!version:^"=!
+set version=!version: =!
+
+:gotversion
+
+set version_out=#define %2 "%version%"
+set version_mk=%2 = "%version%"
+
+echo %version_out%> %1_temp
+
+if %version%==unknown goto :skipgenerate
+
+echo # static version string; update manually every release.> "%~dp0..\version.mk"
+echo %version_mk%>> "%~dp0..\version.mk"
+
+:skipgenerate
+
+echo n | comp %1_temp %1 > NUL 2> NUL
+
+if not errorlevel 1 goto exit
+
+copy /y %1_temp %1
+
+:exit
+
+del %1_temp