mirror of
https://github.com/xiph/opus.git
synced 2025-05-30 23:27:42 +00:00
More NaN hardening in the analysis code
This commit is contained in:
parent
fa85e3bf28
commit
122971b8cc
4 changed files with 23 additions and 9 deletions
|
@ -140,7 +140,7 @@ typedef float celt_ener;
|
|||
#ifdef FLOAT_APPROX
|
||||
/* This code should reliably detect NaN/inf even when -ffast-math is used.
|
||||
Assumes IEEE 754 format. */
|
||||
static inline int celt_isnan(float x)
|
||||
static OPUS_INLINE int celt_isnan(float x)
|
||||
{
|
||||
union {float f; opus_uint32 i;} in;
|
||||
in.f = x;
|
||||
|
|
|
@ -189,7 +189,7 @@ void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int
|
|||
info_out->music_prob = psum;
|
||||
}
|
||||
|
||||
void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix)
|
||||
static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix)
|
||||
{
|
||||
int i, b;
|
||||
const kiss_fft_state *kfft;
|
||||
|
@ -263,6 +263,15 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, con
|
|||
downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C);
|
||||
tonal->mem_fill = 240 + remaining;
|
||||
opus_fft(kfft, in, out);
|
||||
#ifndef FIXED_POINT
|
||||
/* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */
|
||||
if (celt_isnan(out[0].r))
|
||||
{
|
||||
info->valid = 0;
|
||||
RESTORE_STACK;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i=1;i<N2;i++)
|
||||
{
|
||||
|
@ -334,6 +343,16 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, con
|
|||
tE += binE*tonality[i];
|
||||
nE += binE*2.f*(.5f-noisiness[i]);
|
||||
}
|
||||
#ifndef FIXED_POINT
|
||||
/* Check for extreme band energies that could cause NaNs later. */
|
||||
if (!(E<1e9f) || celt_isnan(E))
|
||||
{
|
||||
info->valid = 0;
|
||||
RESTORE_STACK;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
tonal->E[tonal->E_count][b] = E;
|
||||
frame_noisiness += nE/(1e-15f+E);
|
||||
|
||||
|
@ -611,8 +630,6 @@ void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, con
|
|||
/*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/
|
||||
info->noisiness = frame_noisiness;
|
||||
info->valid = 1;
|
||||
if (info_out!=NULL)
|
||||
OPUS_COPY(info_out, info, 1);
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
|
@ -631,7 +648,7 @@ void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, co
|
|||
pcm_len = analysis_frame_size - analysis->analysis_offset;
|
||||
offset = analysis->analysis_offset;
|
||||
do {
|
||||
tonality_analysis(analysis, NULL, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
|
||||
tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
|
||||
offset += 480;
|
||||
pcm_len -= 480;
|
||||
} while (pcm_len>0);
|
||||
|
|
|
@ -78,9 +78,6 @@ typedef struct {
|
|||
AnalysisInfo info[DETECT_SIZE];
|
||||
} TonalityAnalysisState;
|
||||
|
||||
void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info,
|
||||
const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix);
|
||||
|
||||
void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len);
|
||||
|
||||
void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
|
||||
|
|
|
@ -1452,7 +1452,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
|
|||
sum = celt_inner_prod(&pcm_buf[total_buffer*st->channels], &pcm_buf[total_buffer*st->channels], frame_size*st->channels);
|
||||
/* This should filter out both NaNs and ridiculous signals that could
|
||||
cause NaNs further down. */
|
||||
if (!(sum < 1e9) || celt_isnan(sum))
|
||||
if (!(sum < 1e9f) || celt_isnan(sum))
|
||||
OPUS_CLEAR(&pcm_buf[total_buffer*st->channels], frame_size*st->channels);
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue