Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • xiph/opus
  • tterribe/opus
  • markh/opus
  • cisquiers/opus
  • xnorpx/opus
  • tpm/opus
  • 0dvictor/opus
  • traud/opus
  • thesamesam/opus
  • TD-Linux/opus
  • mklingb/opus
  • jmvalin/opus
  • janbuethe/opus
  • tmatth/opus
  • MarekPikula/opus
15 results
Show changes
Commits on Source (7)
......@@ -1270,7 +1270,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
prefilter_tapset = st->tapset_decision;
pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes);
if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && st->analysis.tonality > .3
if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3)
&& (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period))
pitch_change = 1;
if (pf_on==0)
......@@ -1294,16 +1294,18 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
isTransient = 0;
shortBlocks = 0;
if (st->complexity > 1)
{
isTransient = transient_analysis(in, N+st->overlap, CC,
&tf_estimate, &tf_chan);
}
if (LM>0 && ec_tell(enc)+3<=total_bits)
{
if (st->complexity > 1)
{
isTransient = transient_analysis(in, N+st->overlap, CC,
&tf_estimate, &tf_chan);
if (isTransient)
shortBlocks = M;
}
if (isTransient)
shortBlocks = M;
ec_enc_bit_logp(enc, isTransient, 3);
} else {
isTransient = 0;
}
ALLOC(freq, CC*N, celt_sig); /**< Interleaved signal MDCTs */
......
......@@ -146,6 +146,8 @@ extern "C" {
#define OPUS_GET_GAIN_REQUEST 4045
#define OPUS_SET_LSB_DEPTH_REQUEST 4036
#define OPUS_GET_LSB_DEPTH_REQUEST 4037
#define OPUS_SET_EXPERT_VARIABLE_DURATION_REQUEST 4038
#define OPUS_GET_EXPERT_VARIABLE_DURATION_REQUEST 4039
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
......@@ -514,6 +516,32 @@ extern "C" {
* 24 (default: 24).
* @hideinitializer */
#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
/** Configures the encoder's use of variable duration frames.
* When enabled, the encoder is free to use a shorter frame size than the one
* requested in the opus_encode*() call. It is then the user's responsibility
* to verify how much audio was encoded by checking the ToC byte of the encoded
* packet. The part of the audio that was not encoded needs to be resent to the
* encoder for the next call. Do not use this option unless you <b>really</b>
* know what you are doing.
* @see OPUS_GET_EXPERT_VARIABLE_DURATION
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>0</dt><dd>Disable variable duration (default).</dd>
* <dt>1</dt><dd>Enable variable duration.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_EXPERT_VARIABLE_DURATION(x) OPUS_SET_EXPERT_VARIABLE_DURATION_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured use of variable duration frames.
* @see OPUS_SET_EXPERT_VARIABLE_DURATION
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>variable duration disabled (default).</dd>
* <dt>1</dt><dd>variable duration enabled.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_EXPERT_VARIABLE_DURATION(x) OPUS_GET_EXPERT_VARIABLE_DURATION_REQUEST, __opus_check_int_ptr(x)
/**@}*/
/** @defgroup opus_genericctls Generic CTLs
......
......@@ -135,7 +135,7 @@ static inline float fast_atan2f(float y, float x) {
}
}
void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info, CELTEncoder *celt_enc, const opus_val16 *x, int C)
void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info, CELTEncoder *celt_enc, const opus_val16 *x, int len, int C)
{
int i, b;
const CELTMode *mode;
......@@ -165,6 +165,8 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info, CELTEnc
float bandwidth_mask;
int bandwidth=0;
float bandE[NB_TBANDS];
int remaining;
celt_encoder_ctl(celt_enc, CELT_GET_MODE(&mode));
tonal->last_transition++;
......@@ -175,26 +177,43 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info, CELTEnc
if (tonal->count<4)
tonal->music_prob = .5;
kfft = mode->mdct.kfft[0];
if (tonal->count==0)
tonal->mem_fill = 240;
if (C==1)
{
for (i=0;i<N2;i++)
{
float w = analysis_window[i];
in[i].r = MULT16_16(w, x[i]);
in[i].i = MULT16_16(w, x[N-N2+i]);
in[N-i-1].r = MULT16_16(w, x[N-i-1]);
in[N-i-1].i = MULT16_16(w, x[2*N-N2-i-1]);
}
for (i=0;i<IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill);i++)
tonal->inmem[i+tonal->mem_fill] = x[i];
} else {
for (i=0;i<N2;i++)
{
float w = analysis_window[i];
in[i].r = MULT16_16(w, x[2*i]+x[2*i+1]);
in[i].i = MULT16_16(w, x[2*(N-N2+i)]+x[2*(N-N2+i)+1]);
in[N-i-1].r = MULT16_16(w, x[2*(N-i-1)]+x[2*(N-i-1)+1]);
in[N-i-1].i = MULT16_16(w, x[2*(2*N-N2-i-1)]+x[2*(2*N-N2-i-1)+1]);
}
for (i=0;i<IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill);i++)
tonal->inmem[i+tonal->mem_fill] = x[2*i]+x[2*i+1];
}
if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE)
{
tonal->mem_fill += len;
/* Don't have enough to update the analysis */
return;
}
for (i=0;i<N2;i++)
{
float w = analysis_window[i];
in[i].r = MULT16_16(w, tonal->inmem[i]);
in[i].i = MULT16_16(w, tonal->inmem[N2+i]);
in[N-i-1].r = MULT16_16(w, tonal->inmem[N-i-1]);
in[N-i-1].i = MULT16_16(w, tonal->inmem[N+N2-i-1]);
}
OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240);
remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill);
if (C==1)
{
for (i=0;i<remaining;i++)
tonal->inmem[240+i] = x[ANALYSIS_BUF_SIZE-tonal->mem_fill+i];
} else {
for (i=0;i<remaining;i++)
tonal->inmem[240+i] = x[2*(ANALYSIS_BUF_SIZE-tonal->mem_fill+i)]
+ x[2*(ANALYSIS_BUF_SIZE-tonal->mem_fill+i)+1];
}
tonal->mem_fill = 240 + remaining;
opus_fft(kfft, in, out);
for (i=1;i<N2;i++)
......
......@@ -31,16 +31,20 @@
#define NB_FRAMES 8
#define NB_TBANDS 18
#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */
typedef struct {
float angle[240];
float d_angle[240];
float d2_angle[240];
float inmem[ANALYSIS_BUF_SIZE];
int mem_fill; /* number of usable samples in the buffer */
float prev_band_tonality[NB_TBANDS];
float prev_tonality;
float E[NB_FRAMES][NB_TBANDS];
float lowE[NB_TBANDS], highE[NB_TBANDS];
float meanE[NB_TBANDS], meanRE[NB_TBANDS];
float lowE[NB_TBANDS];
float highE[NB_TBANDS];
float meanE[NB_TBANDS];
float meanRE[NB_TBANDS];
float mem[32];
float cmean[8];
float std[9];
......@@ -55,6 +59,6 @@ typedef struct {
} TonalityAnalysisState;
void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info,
CELTEncoder *celt_enc, const opus_val16 *x, int C);
CELTEncoder *celt_enc, const opus_val16 *x, int len, int C);
#endif
......@@ -53,6 +53,7 @@ void print_usage( char* argv[] )
fprintf(stderr, "-d : only runs the decoder (reads the bit-stream as input)\n" );
fprintf(stderr, "-cbr : enable constant bitrate; default: variable bitrate\n" );
fprintf(stderr, "-cvbr : enable constrained variable bitrate; default: unconstrained\n" );
fprintf(stderr, "-variable-duration : enable frames of variable duration (experts only); default: disabled\n" );
fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
......@@ -221,6 +222,8 @@ int main(int argc, char *argv[])
short *in, *out;
int application=OPUS_APPLICATION_AUDIO;
double bits=0.0, bits_max=0.0, bits_act=0.0, bits2=0.0, nrg;
double tot_samples=0;
opus_uint64 tot_in, tot_out;
int bandwidth=-1;
const char *bandwidth_string;
int lost = 0, lost_prev = 1;
......@@ -239,6 +242,9 @@ int main(int argc, char *argv[])
int curr_mode=0;
int curr_mode_count=0;
int mode_switch_time = 48000;
int nb_encoded;
int remaining=0;
int variable_duration=0;
if (argc < 5 )
{
......@@ -246,6 +252,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
tot_in=tot_out=0;
fprintf(stderr, "%s\n", opus_get_version_string());
args = 1;
......@@ -374,6 +381,10 @@ int main(int argc, char *argv[])
check_encoder_option(decode_only, "-cvbr");
cvbr = 1;
args++;
} else if( strcmp( argv[ args ], "-variable-duration" ) == 0 ) {
check_encoder_option(decode_only, "-variable-duration");
variable_duration = 1;
args++;
} else if( strcmp( argv[ args ], "-dtx") == 0 ) {
check_encoder_option(decode_only, "-dtx");
use_dtx = 1;
......@@ -499,6 +510,7 @@ int main(int argc, char *argv[])
opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));
opus_encoder_ctl(enc, OPUS_SET_EXPERT_VARIABLE_DURATION(variable_duration));
}
if (!encode_only)
{
......@@ -617,22 +629,28 @@ int main(int argc, char *argv[])
opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(mode_list[curr_mode][3]));
frame_size = mode_list[curr_mode][2];
}
err = fread(fbytes, sizeof(short)*channels, frame_size, fin);
err = fread(fbytes, sizeof(short)*channels, frame_size-remaining, fin);
curr_read = err;
tot_in += curr_read;
for(i=0;i<curr_read*channels;i++)
{
opus_int32 s;
s=fbytes[2*i+1]<<8|fbytes[2*i];
s=((s&0xFFFF)^0x8000)-0x8000;
in[i]=s;
in[i+remaining*channels]=s;
}
if (curr_read < frame_size)
if (curr_read+remaining < frame_size)
{
for (i=curr_read*channels;i<frame_size*channels;i++)
for (i=(curr_read+remaining)*channels;i<frame_size*channels;i++)
in[i] = 0;
stop = 1;
if (encode_only || decode_only)
stop = 1;
}
len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
nb_encoded = opus_packet_get_samples_per_frame(data[toggle], sampling_rate)*opus_packet_get_nb_frames(data[toggle], len[toggle]);
remaining = frame_size-nb_encoded;
for(i=0;i<remaining*channels;i++)
in[i] = in[nb_encoded*channels+i];
if (sweep_bps!=0)
{
bitrate_bps += sweep_bps;
......@@ -681,6 +699,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Error writing.\n");
return EXIT_FAILURE;
}
tot_samples += nb_encoded;
} else {
int output_samples;
lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
......@@ -699,6 +718,11 @@ int main(int argc, char *argv[])
}
if (output_samples>0)
{
if (!decode_only && tot_out + output_samples > tot_in)
{
stop=1;
output_samples = tot_in-tot_out;
}
if (output_samples>skip) {
int i;
for(i=0;i<(output_samples-skip)*channels;i++)
......@@ -712,6 +736,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Error writing.\n");
return EXIT_FAILURE;
}
tot_out += output_samples-skip;
}
if (output_samples<skip) skip -= output_samples;
else skip = 0;
......@@ -719,6 +744,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "error decoding frame: %s\n",
opus_strerror(output_samples));
}
tot_samples += output_samples;
}
}
......@@ -763,7 +789,7 @@ int main(int argc, char *argv[])
toggle = (toggle + use_inbandfec) & 1;
}
fprintf (stderr, "average bitrate: %7.3f kb/s\n",
1e-3*bits*sampling_rate/(frame_size*(double)count));
1e-3*bits*sampling_rate/tot_samples);
fprintf (stderr, "maximum bitrate: %7.3f kb/s\n",
1e-3*bits_max*sampling_rate/frame_size);
if (!decode_only)
......
......@@ -67,6 +67,7 @@ struct OpusEncoder {
opus_int32 Fs;
int use_vbr;
int vbr_constraint;
int variable_duration;
opus_int32 bitrate_bps;
opus_int32 user_bitrate_bps;
int encoder_buffer;
......@@ -87,6 +88,7 @@ struct OpusEncoder {
int first;
opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2];
#ifndef FIXED_POINT
opus_val32 subframe_mem[3];
TonalityAnalysisState analysis;
#endif
opus_uint32 rangeFinal;
......@@ -532,6 +534,209 @@ static opus_int32 user_bitrate_to_bitrate(OpusEncoder *st, int frame_size, int m
return st->user_bitrate_bps;
}
#ifndef FIXED_POINT
/* Don't use more than 60 ms for the frame size analysis */
#define MAX_DYNAMIC_FRAMESIZE 24
/* Estimates how much the bitrate will be boosted based on the sub-frame energy */
static float transient_boost(const float *E, const float *E_1, int LM, int maxM)
{
int i;
int M;
float sumE=0, sumE_1=0;
float metric;
M = IMIN(maxM, (1<<LM)+1);
for (i=0;i<M;i++)
{
sumE += E[i];
sumE_1 += E_1[i];
}
metric = sumE*sumE_1/(M*M);
/*if (LM==3)
printf("%f\n", metric);*/
/*return metric>10 ? 1 : 0;*/
/*return MAX16(0,1-exp(-.25*(metric-2.)));*/
return MIN16(1,sqrt(MAX16(0,.05*(metric-2))));
}
/* Viterbi decoding trying to find the best frame size combination using look-ahead
State numbering:
0: unused
1: 2.5 ms
2: 5 ms (#1)
3: 5 ms (#2)
4: 10 ms (#1)
5: 10 ms (#2)
6: 10 ms (#3)
7: 10 ms (#4)
8: 20 ms (#1)
9: 20 ms (#2)
10: 20 ms (#3)
11: 20 ms (#4)
12: 20 ms (#5)
13: 20 ms (#6)
14: 20 ms (#7)
15: 20 ms (#8)
*/
static int transient_viterbi(const float *E, const float *E_1, int N, int frame_cost, int rate)
{
int i;
float cost[MAX_DYNAMIC_FRAMESIZE][16];
int states[MAX_DYNAMIC_FRAMESIZE][16];
float best_cost;
int best_state;
/* Makes variable framesize less aggressive at lower bitrates, but I can't
find any valid theretical justification for this (other than it seems
to help) */
frame_cost *= 720/rate;
for (i=0;i<16;i++)
{
/* Impossible state */
states[0][i] = -1;
cost[0][i] = 1e10;
}
for (i=0;i<4;i++)
{
cost[0][1<<i] = frame_cost + rate*(1<<i)*transient_boost(E, E_1, i, N+1);
states[0][1<<i] = i;
}
for (i=1;i<N;i++)
{
int j;
/* Follow continuations */
for (j=2;j<16;j++)
{
cost[i][j] = cost[i-1][j-1];
states[i][j] = j-1;
}
/* New frames */
for(j=0;j<4;j++)
{
int k;
float min_cost;
float curr_cost;
states[i][1<<j] = 1;
min_cost = cost[i-1][1];
for(k=1;k<4;k++)
{
float tmp = cost[i-1][(1<<(k+1))-1];
if (tmp < min_cost)
{
states[i][1<<j] = (1<<(k+1))-1;
min_cost = tmp;
}
}
curr_cost = frame_cost+rate*(1<<j)*transient_boost(E+i, E_1+i, j, N-i+1);
cost[i][1<<j] = min_cost;
/* If part of the frame is outside the analysis window, only count part of the cost */
if (N-i < (1<<j))
cost[i][1<<j] += curr_cost*(float)(N-i)/(1<<j);
else
cost[i][1<<j] += curr_cost;
}
}
best_state=1;
best_cost = cost[N-1][1];
/* Find best end state (doesn't force a frame to end at N-1) */
for (i=2;i<16;i++)
{
if (cost[N-1][i]<best_cost)
{
best_cost = cost[N-1][i];
best_state = i;
}
}
/* Follow transitions back */
for (i=N-1;i>=0;i--)
{
/*printf("%d ", best_state);*/
best_state = states[i][best_state];
}
/*printf("%d\n", best_state);*/
return best_state;
}
static int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs,
int bitrate, opus_val16 tonality, opus_val32 *mem, int buffering)
{
int N;
int i;
float e[MAX_DYNAMIC_FRAMESIZE+4];
float e_1[MAX_DYNAMIC_FRAMESIZE+3];
float memx;
int bestLM=0;
int subframe;
int pos;
subframe = Fs/400;
e[0]=mem[0];
e_1[0]=1./(EPSILON+mem[0]);
if (buffering)
{
/* Consider the CELT delay when not in restricted-lowdelay */
/* We assume the buffering is between 2.5 and 5 ms */
int offset = 2*subframe - buffering;
celt_assert(offset>=0 && offset <= subframe);
x += C*offset;
len -= offset;
e[1]=mem[1];
e_1[1]=1./(EPSILON+mem[1]);
e[2]=mem[2];
e_1[2]=1./(EPSILON+mem[2]);
pos = 3;
} else {
pos=1;
}
N=IMIN(len/subframe, MAX_DYNAMIC_FRAMESIZE);
memx = x[0];
for (i=0;i<N;i++)
{
float tmp;
float tmpx;
int j;
tmp=EPSILON;
if (C==1)
{
for (j=0;j<subframe;j++)
{
tmpx = x[subframe*i+j];
tmp += (tmpx-memx)*(tmpx-memx);
memx = tmpx;
}
} else {
for (j=0;j<subframe;j++)
{
tmpx = x[(subframe*i+j)*2]+x[(subframe*i+j)*2+1];
tmp += (tmpx-memx)*(tmpx-memx);
memx = tmpx;
}
}
e[i+pos] = tmp;
e_1[i+pos] = 1.f/tmp;
}
/* Hack to get 20 ms working with APPLICATION_AUDIO
The real problem is that the corresponding memory needs to use 1.5 ms
from this frame and 1 ms from the next frame */
e[i+pos] = e[i+pos-1];
if (buffering)
N=IMIN(MAX_DYNAMIC_FRAMESIZE, N+2);
bestLM = transient_viterbi(e, e_1, N, (1.f+.5*tonality)*(40*C+40), bitrate/400);
mem[0] = e[1<<bestLM];
if (buffering)
{
mem[1] = e[(1<<bestLM)+1];
mem[2] = e[(1<<bestLM)+2];
}
return bestLM;
}
#endif
#ifdef FIXED_POINT
#define opus_encode_native opus_encode
opus_int32 opus_encode(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
......@@ -569,6 +774,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */
int extra_buffer, total_buffer;
int perform_analysis=0;
int orig_frame_size;
#ifndef FIXED_POINT
AnalysisInfo analysis_info;
#endif
......@@ -579,33 +785,52 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
max_data_bytes = IMIN(1276, out_data_bytes);
st->rangeFinal = 0;
if (400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs &&
if ((!st->variable_duration && 400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs &&
50*frame_size != st->Fs && 25*frame_size != st->Fs && 50*frame_size != 3*st->Fs)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
if (max_data_bytes<=0)
|| (400*frame_size < st->Fs)
|| max_data_bytes<=0
)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
silk_enc = (char*)st+st->silk_enc_offset;
celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
#ifndef FIXED_POINT
perform_analysis = st->silk_mode.complexity >= 7 && frame_size >= st->Fs/100 && st->Fs==48000;
#endif
if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
delay_compensation = 0;
else
delay_compensation = st->delay_compensation;
if (perform_analysis)
orig_frame_size = IMIN(frame_size,st->Fs/50);
if (st->variable_duration)
{
total_buffer = IMAX(st->Fs/200, delay_compensation);
} else {
total_buffer = delay_compensation;
int LM = 3;
#ifndef FIXED_POINT
LM = optimize_framesize(pcm, frame_size, st->channels, st->Fs, st->bitrate_bps,
st->analysis.prev_tonality, st->subframe_mem, delay_compensation);
#endif
while ((st->Fs/400<<LM)>frame_size)
LM--;
frame_size = (st->Fs/400<<LM);
}
#ifndef FIXED_POINT
/* Only perform analysis up to 20-ms frames. Longer ones will be split if
they're in CELT-only mode. */
analysis_info.valid = 0;
perform_analysis = st->silk_mode.complexity >= 7 && st->Fs==48000;
if (!perform_analysis)
st->voice_ratio = -1;
else if (frame_size <= st->Fs/50)
{
tonality_analysis(&st->analysis, &analysis_info, celt_enc, pcm, IMIN(480, frame_size), st->channels);
if (frame_size > st->Fs/100)
tonality_analysis(&st->analysis, &analysis_info, celt_enc, pcm+(st->Fs/100)*st->channels, 480, st->channels);
if (analysis_info.valid && st->signal_type == OPUS_AUTO)
st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob));
}
#endif
total_buffer = delay_compensation;
extra_buffer = total_buffer-delay_compensation;
st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes);
......@@ -931,6 +1156,14 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
RESTORE_STACK;
return ret;
}
/* Perform analysis for 40-60 ms frames */
if (perform_analysis && frame_size > st->Fs/50)
{
int nb_analysis = frame_size/(st->Fs/100);
for (i=0;i<nb_analysis;i++)
tonality_analysis(&st->analysis, &analysis_info, celt_enc, pcm+i*(st->Fs/100)*st->channels, 480, st->channels);
st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob));
}
curr_bandwidth = st->bandwidth;
......@@ -970,20 +1203,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs);
}
#ifndef FIXED_POINT
if (perform_analysis)
{
int nb_analysis_frames;
nb_analysis_frames = frame_size/(st->Fs/100);
for (i=0;i<nb_analysis_frames;i++)
tonality_analysis(&st->analysis, &analysis_info, celt_enc, pcm_buf+i*(st->Fs/100)*st->channels, st->channels);
if (st->signal_type == OPUS_AUTO)
st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob));
} else {
analysis_info.valid = 0;
st->voice_ratio = -1;
}
#endif
/* SILK processing */
HB_gain = Q15ONE;
......@@ -1178,9 +1398,18 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
} else {
if (st->use_vbr)
{
opus_int32 bonus=0;
#ifndef FIXED_POINT
if (orig_frame_size != frame_size)
{
bonus = (40*st->stream_channels+40)*(48000/frame_size-48000/orig_frame_size);
if (analysis_info.valid)
bonus = bonus*(1.f+.5*analysis_info.tonality);
}
#endif
celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1));
celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint));
celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps));
celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps+bonus));
nb_compr_bytes = max_data_bytes-1-redundancy_bytes;
} else {
nb_compr_bytes = bytes_target;
......@@ -1709,6 +1938,20 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
celt_encoder_ctl(celt_enc, OPUS_GET_LSB_DEPTH(value));
}
break;
case OPUS_SET_EXPERT_VARIABLE_DURATION_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
if (value<0 || value>1)
goto bad_arg;
st->variable_duration = value;
}
break;
case OPUS_GET_EXPERT_VARIABLE_DURATION_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
*value = st->variable_duration;
}
break;
case OPUS_RESET_STATE:
{
void *silk_enc;
......