Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/xiph/opus.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2014-07-30 21:41:28 +0400
committerJean-Marc Valin <jmvalin@jmvalin.ca>2014-07-30 21:47:16 +0400
commite070300a341a605b3ed08baa642b661d2587a841 (patch)
tree41485385fb650984388f0be97501decff617827d
parent1e87fea32698ac3070ebf092d2ca08feae57373f (diff)
parentbb4b6885a139644cf3ac14e7deda9f633ec2d93c (diff)
Merge remote-tracking branch 'origin/master' into derf_rtp_edits
Conflicts: doc/draft-ietf-payload-rtp-opus.xml
-rw-r--r--doc/draft-ietf-payload-rtp-opus.xml29
-rw-r--r--silk/CNG.c21
-rw-r--r--silk/decode_frame.c10
-rw-r--r--silk/fixed/burg_modified_FIX.c28
-rw-r--r--src/opus_multistream_encoder.c34
-rw-r--r--win32/genversion.bat12
6 files changed, 88 insertions, 46 deletions
diff --git a/doc/draft-ietf-payload-rtp-opus.xml b/doc/draft-ietf-payload-rtp-opus.xml
index 412ce0fc..f4f99390 100644
--- a/doc/draft-ietf-payload-rtp-opus.xml
+++ b/doc/draft-ietf-payload-rtp-opus.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY rfc2119 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml'>
+<!ENTITY rfc3389 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.3389.xml'>
<!ENTITY rfc3550 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.3550.xml'>
<!ENTITY rfc3711 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.3711.xml'>
<!ENTITY rfc3551 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.3551.xml'>
@@ -17,7 +18,7 @@
<!ENTITY nbsp "&#160;">
]>
- <rfc category="std" ipr="trust200902" docName="draft-ietf-payload-rtp-opus-01">
+ <rfc category="std" ipr="trust200902" docName="draft-ietf-payload-rtp-opus-03">
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc strict="yes" ?>
@@ -60,7 +61,7 @@
<organization>Mozilla</organization>
<address>
<postal>
- <street>650 Castro Street</street>
+ <street>331 E. Evelyn Avenue</street>
<city>Mountain View</city>
<region>CA</region>
<code>94041</code>
@@ -70,7 +71,7 @@
</address>
</author>
- <date day='14' month='January' year='2014' />
+ <date day='30' month='July' year='2014' />
<abstract>
<t>
@@ -247,14 +248,22 @@
the Opus encoder can use discontinuous
transmission (DTX), where parts of the encoded signal that
correspond to periods of silence in the input speech or audio signal
- are not transmitted to the receiver.
+ are not transmitted to the receiver. A receiver can distinguish
+ between DTX and packet loss by looking for gaps in the sequence
+ number, as described by Section 4.1
+ of&nbsp;<xref target="RFC3551"/>.
</t>
<t>
On the receiving side, the non-transmitted parts will be handled by a
frame loss concealment unit in the Opus decoder which generates a
comfort noise signal to replace the non transmitted parts of the
- speech or audio signal.
+ speech or audio signal. Use of <xref target="RFC3389"/> Comfort
+ Noise (CN) with Opus is discouraged.
+ The transmitter MUST drop whole frames only,
+ based on the size of the last transmitted frame,
+ to ensure successive RTP timestamps differ by a multiple of 120 and
+ to allow the receiver to use whole frames for concealment.
</t>
<t>
@@ -347,8 +356,9 @@
therefore no padding is necessary. The payload MAY be padded by an
integer number of octets according to <xref target="RFC3550"/>.</t>
- <t>The marker bit (M) of the RTP header is used in accordance with
- Section 4.1 of <xref target="RFC3551"/>.</t>
+ <t>The timestamp, sequence number, and marker bit (M) of the RTP header
+ are used in accordance with Section 4.1
+ of&nbsp;<xref target="RFC3551"/>.</t>
<t>The RTP payload type for Opus has not been assigned statically and is
expected to be assigned dynamically.</t>
@@ -738,8 +748,8 @@
<t>Example 2: 16000 Hz clock rate, maximum packet size of 40 ms,
recommended packet size of 40 ms, maximum average bitrate of 20000 bps,
- prefers to receive stereo but only plans to send mono, FEC is allowed,
- DTX is not allowed</t>
+ prefers to receive stereo but only plans to send mono, FEC is desired,
+ DTX is not desired</t>
<figure>
<artwork>
@@ -926,6 +936,7 @@
<back>
<references title="Normative References">
&rfc2119;
+ &rfc3389;
&rfc3550;
&rfc3711;
&rfc3551;
diff --git a/silk/CNG.c b/silk/CNG.c
index 8481d95d..bb30a7cc 100644
--- a/silk/CNG.c
+++ b/silk/CNG.c
@@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* Generates excitation for CNG LPC synthesis */
static OPUS_INLINE void silk_CNG_exc(
- opus_int32 residual_Q10[], /* O CNG residual signal Q10 */
+ opus_int32 exc_Q10[], /* O CNG excitation signal Q10 */
opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */
opus_int32 Gain_Q16, /* I Gain to apply */
opus_int length, /* I Length */
@@ -55,7 +55,7 @@ static OPUS_INLINE void silk_CNG_exc(
idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask );
silk_assert( idx >= 0 );
silk_assert( idx <= CNG_BUF_MASK_MAX );
- residual_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q14[ idx ], Gain_Q16 >> 4 ) );
+ exc_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q14[ idx ], Gain_Q16 >> 4 ) );
}
*rand_seed = seed;
}
@@ -85,7 +85,7 @@ void silk_CNG(
)
{
opus_int i, subfr;
- opus_int32 sum_Q6, max_Gain_Q16;
+ opus_int32 sum_Q6, max_Gain_Q16, gain_Q16;
opus_int16 A_Q12[ MAX_LPC_ORDER ];
silk_CNG_struct *psCNG = &psDec->sCNG;
SAVE_STACK;
@@ -125,11 +125,20 @@ void silk_CNG(
/* Add CNG when packet is lost or during DTX */
if( psDec->lossCnt ) {
VARDECL( opus_int32, CNG_sig_Q10 );
-
ALLOC( CNG_sig_Q10, length + MAX_LPC_ORDER, opus_int32 );
/* Generate CNG excitation */
- silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed );
+ gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] );
+ if( gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23) ) {
+ gain_Q16 = silk_SMULTT( gain_Q16, gain_Q16 );
+ gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
+ gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 );
+ } else {
+ gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 );
+ gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
+ gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
+ }
+ silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, gain_Q16, length, &psCNG->rand_seed );
/* Convert CNG NLSF to filter representation */
silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
@@ -162,7 +171,7 @@ void silk_CNG(
/* Update states */
CNG_sig_Q10[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 );
- frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( sum_Q6, 6 ) );
+ frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( CNG_sig_Q10[ MAX_LPC_ORDER + i ], 10 ) );
}
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
} else {
diff --git a/silk/decode_frame.c b/silk/decode_frame.c
index 37459a32..6a7cffbb 100644
--- a/silk/decode_frame.c
+++ b/silk/decode_frame.c
@@ -107,16 +107,16 @@ opus_int silk_decode_frame(
silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
- /****************************************************************/
- /* Ensure smooth connection of extrapolated and good frames */
- /****************************************************************/
- silk_PLC_glue_frames( psDec, pOut, L );
-
/************************************************/
/* Comfort noise generation / estimation */
/************************************************/
silk_CNG( psDec, psDecCtrl, pOut, L );
+ /****************************************************************/
+ /* Ensure smooth connection of extrapolated and good frames */
+ /****************************************************************/
+ silk_PLC_glue_frames( psDec, pOut, L );
+
/* Update some decoder state variables */
psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ];
diff --git a/silk/fixed/burg_modified_FIX.c b/silk/fixed/burg_modified_FIX.c
index db348295..2a260775 100644
--- a/silk/fixed/burg_modified_FIX.c
+++ b/silk/fixed/burg_modified_FIX.c
@@ -54,7 +54,7 @@ void silk_burg_modified(
int arch /* I Run-time architecture */
)
{
- opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain;
+ opus_int k, n, s, lz, rshifts, reached_max_gain;
opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
const opus_int16 *x_ptr;
opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ];
@@ -63,27 +63,23 @@ void silk_burg_modified(
opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ];
opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ];
opus_int32 xcorr[ SILK_MAX_ORDER_LPC ];
+ opus_int64 C0_64;
silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
- silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
- if( rshifts > MAX_RSHIFTS ) {
- C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS );
- silk_assert( C0 > 0 );
- rshifts = MAX_RSHIFTS;
+ C0_64 = silk_inner_prod16_aligned_64( x, x, subfr_length*nb_subfr );
+ lz = silk_CLZ64(C0_64);
+ rshifts = 32 + 1 + N_BITS_HEAD_ROOM - lz;
+ if (rshifts > MAX_RSHIFTS) rshifts = MAX_RSHIFTS;
+ if (rshifts < MIN_RSHIFTS) rshifts = MIN_RSHIFTS;
+
+ if (rshifts > 0) {
+ C0 = (opus_int32)silk_RSHIFT64(C0_64, rshifts );
} else {
- lz = silk_CLZ32( C0 ) - 1;
- rshifts_extra = N_BITS_HEAD_ROOM - lz;
- if( rshifts_extra > 0 ) {
- rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts );
- C0 = silk_RSHIFT32( C0, rshifts_extra );
- } else {
- rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts );
- C0 = silk_LSHIFT32( C0, -rshifts_extra );
- }
- rshifts += rshifts_extra;
+ C0 = silk_LSHIFT32((opus_int32)C0_64, -rshifts );
}
+
CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */
silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) );
if( rshifts > 0 ) {
diff --git a/src/opus_multistream_encoder.c b/src/opus_multistream_encoder.c
index 6e52a4db..aa464f59 100644
--- a/src/opus_multistream_encoder.c
+++ b/src/opus_multistream_encoder.c
@@ -591,7 +591,7 @@ OpusMSEncoder *opus_multistream_surround_encoder_create(
return st;
}
-static void surround_rate_allocation(
+static opus_int32 surround_rate_allocation(
OpusMSEncoder *st,
opus_int32 *rate,
int frame_size
@@ -605,6 +605,7 @@ static void surround_rate_allocation(
int lfe_offset;
int coupled_ratio; /* Q8 */
int lfe_ratio; /* Q8 */
+ opus_int32 rate_sum=0;
ptr = (char*)st + align(sizeof(OpusMSEncoder));
opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
@@ -660,7 +661,10 @@ static void surround_rate_allocation(
rate[i] = stream_offset+channel_rate;
else
rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
+ rate[i] = IMAX(rate[i], 500);
+ rate_sum += rate[i];
}
+ return rate_sum;
}
/* Max size in case the encoder decides to return three frames */
@@ -695,6 +699,8 @@ static int opus_multistream_encode_native
opus_val32 *mem = NULL;
opus_val32 *preemph_mem=NULL;
int frame_size;
+ opus_int32 rate_sum;
+ opus_int32 smallest_packet;
ALLOC_STACK;
if (st->surround)
@@ -738,6 +744,18 @@ static int opus_multistream_encode_native
RESTORE_STACK;
return OPUS_BAD_ARG;
}
+ /* Estimate (slightly overestimating) of the smallest packet the encoder can produce. */
+ if (50*frame_size <= Fs)
+ {
+ smallest_packet = st->layout.nb_streams*4;
+ } else {
+ smallest_packet = st->layout.nb_streams*4*50*frame_size/Fs;
+ }
+ if (max_data_bytes < smallest_packet)
+ {
+ 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);
@@ -755,11 +773,19 @@ static int opus_multistream_encode_native
}
/* Compute bitrate allocation between streams (this could be a lot better) */
- surround_rate_allocation(st, bitrates, frame_size);
+ rate_sum = surround_rate_allocation(st, bitrates, frame_size);
if (!vbr)
- max_data_bytes = IMIN(max_data_bytes, 3*st->bitrate_bps/(3*8*Fs/frame_size));
-
+ {
+ if (st->bitrate_bps == OPUS_AUTO)
+ {
+ max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
+ } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
+ {
+ max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
+ 3*st->bitrate_bps/(3*8*Fs/frame_size)));
+ }
+ }
ptr = (char*)st + align(sizeof(OpusMSEncoder));
for (s=0;s<st->layout.nb_streams;s++)
{
diff --git a/win32/genversion.bat b/win32/genversion.bat
index a9b9353a..cd1d4dce 100644
--- a/win32/genversion.bat
+++ b/win32/genversion.bat
@@ -23,10 +23,10 @@ set version=!version: =!
:gotversion
-set version_out=#define %2 "%version%"
-set version_mk=%2 = "%version%"
+set version_out=#define %~2 "%version%"
+set version_mk=%~2 = "%version%"
-echo %version_out%> "%1_temp"
+echo %version_out%> "%~1_temp"
if %version%==unknown goto :skipgenerate
@@ -35,12 +35,12 @@ echo %version_mk%>> "%~dp0..\version.mk"
:skipgenerate
-echo n | comp "%1_temp" "%1" > NUL 2> NUL
+echo n | comp "%~1_temp" "%~1" > NUL 2> NUL
if not errorlevel 1 goto exit
-copy /y "%1_temp" "%1"
+copy /y "%~1_temp" "%~1"
:exit
-del "%1_temp"
+del "%~1_temp"