blob: f96d5f5f3d01c91954b13cfeba8a916d2b7b3048 [file] [log] [blame]
/*---------------------------------------------------------------------------*
* wav_acc.c *
* *
* Copyright 2007, 2008 Nuance Communciations, Inc. *
* *
* Licensed under the Apache License, Version 2.0 (the 'License'); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an 'AS IS' BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* *
*---------------------------------------------------------------------------*/
static const char wav_acc_c[] = "$Id: wav_acc.c,v 1.6.6.7 2007/10/15 18:06:24 dahan Exp $";
#ifndef _RTT
#include "pstdio.h"
#endif
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include "passert.h"
#include "pendian.h"
#include "portable.h"
#ifndef _RTT
#include "duk_io.h"
#endif
#include "sample.h"
#include "mulaw.h"
#include "portable.h"
void create_sample_buffer(wave_info *wave, int frame_size, int window_size)
{
ASSERT(wave);
ASSERT(frame_size > 0);
ASSERT(window_size >= frame_size);
wave->income = (samdata *) CALLOC(window_size, sizeof(samdata), "cfront.wave.income");
wave->outgo = (samdata *) CALLOC(window_size, sizeof(samdata), "cfront.wave.outgo");
wave->window_size = window_size;
wave->frame_size = frame_size;
#if DEBUG
log_report("window %d frame %d\n", window_size, frame_size);
#endif
return;
}
void free_sample_buffer(wave_info *wave)
{
ASSERT(wave);
if (wave->income)
FREE((char *)wave->income);
if (wave->outgo)
FREE((char *)wave->outgo);
wave->income = NULL;
wave->outgo = NULL;
wave->window_size = 0;
wave->frame_size = 0;
return;
}
void reset_sig_check(wave_stats *ws)
/*
** Resets the wave statistics
*/
{
int ii;
ASSERT(ws);
ws->sum = 0;
ws->sum2 = 0;
ws->sumsqu = 0;
ws->sumsqu2 = 0;
ws->nsam = 0;
ws->highclip = 0;
ws->lowclip = 0;
for (ii = 0; ii < MAXHISTBITS; ii++)
ws->bithist[ii] = 0;
}
#define OVERFLOW_MASK 0x40000000
void get_sig_check(wave_stats *ws, int *nsam, int *pclowclip, int *pchighclip,
int *dc_offset, int *amp, int *pc5, int *pc95,
int *overflow)
/*
** Returns the wave statistics
*/
{
float mean;
int num;
int ntot;
int npc;
int ii;
float sqr_devn;
ASSERT(ws);
/* *nsam = ws->nsam / 100; */
*nsam = ws->nsam;
*overflow = 0;
if (ws->nsam == 0)
{
*pclowclip = 0;
*pchighclip = 0;
*dc_offset = 0;
*amp = 0;
*pc5 = 0;
*pc95 = 0;
return;
}
if (ws->nsam > OVERFLOW_MASK) *overflow = 1;
*pclowclip = (int)(((float)ws->lowclip * 10000.0) / (float)ws->nsam);
*pchighclip = (int)(((float)ws->highclip * 10000.0) / (float)ws->nsam);
mean = ((float)ws->sum + (float)ws->sum2 * OVERFLOW_MASK) / ws->nsam;
*dc_offset = (int) mean;
sqr_devn = (((float)ws->sumsqu + (float)ws->sumsqu2 * OVERFLOW_MASK)
/ (float)ws->nsam) - (mean * mean);
*amp = integer_square_root((int)sqr_devn);
/* now analyse the histogram */
num = 0;
for (ii = 0; ii < MAXHISTBITS; ii++)
{
num += ws->bithist[ii];
}
ntot = num;
npc = ntot / 20; /* 5% cutoff */
for (ii = num = 0; (ii < MAXHISTBITS) && (num < npc); ii++)
{
num += ws->bithist[ii];
}
*pc5 = ii;
npc = (int)(0.95 * ntot); /* 95% cutoff */
for (ii = num = 0; (ii < MAXHISTBITS) && (num < npc); ii++)
{
num += ws->bithist[ii];
}
*pc95 = ii;
return;
}
void acc_wave_stats(wave_info* wave)
/*
** Updates the wave statistics
*/
{
int ii;
int val;
samdata hclip;
samdata lclip;
wave_stats *ws;
int sumabs;
int num;
ASSERT(wave);
ws = &wave->stats;
hclip = ws->highclip_level;
lclip = ws->lowclip_level;
if (ws->nsam > OVERFLOW_MASK) return;
/* as soon as we have at least 1073741824 */
/* samples, stop accumulating. */
sumabs = 0;
num = 0;
for (ii = 0; ii < wave->num_samples; ii++)
{
val = (int) wave->income[ii];
ws->sum += val;
ws->sumsqu += val * val;
if (ws->sumsqu > OVERFLOW_MASK)
{
ws->sumsqu -= OVERFLOW_MASK;
ws->sumsqu2++;
}
/* nasty bit here as ANSI C does not do >32bit */
/* Assumes that samples are no larger than */
/* signed shorts */
ws->nsam++;
if (val >= hclip) ws->highclip++;
if (val <= lclip) ws->lowclip++;
sumabs += abs(val);
num++;
}
if (ws->sum >= OVERFLOW_MASK)
{
ws->sum -= OVERFLOW_MASK;
ws->sum2++;
}
else if (ws->sum < -OVERFLOW_MASK)
{
ws->sum += OVERFLOW_MASK;
ws->sum2--;
}
/* another >32bit workaround */
/* assumes wave->num_samples < 32878 */
/* this is really overkill as we expect */
/* the mean to be around zero anyway */
if (num > 0) sumabs /= num;
ii = 0;
while (sumabs)
{
sumabs >>= 1;
ii++;
}
ASSERT(ii <= 16); /* unusual case i=16 if all samples -32678 */
ws->bithist[ii]++;
return;
}