pure sdk for main

This commit is contained in:
divadiow
2025-08-27 09:51:58 +01:00
parent f0d033f1c9
commit 0571416e7c
3283 changed files with 1577720 additions and 1 deletions
File diff suppressed because it is too large Load Diff
+72
View File
@@ -0,0 +1,72 @@
#ifndef _ADPCM_CODE_H_
#define _ADPCM_CODE_H_
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "ringbuf.h"
#include "lowcfe.h"
struct adpcm_channel {
int32_t pcmdata; // current PCM value
int32_t shaping_weight, error; // for noise shaping
int8_t index; // current index into step size table
};
struct adpcm_context {
struct adpcm_channel channels [2];
int num_channels, sample_rate, config_flags;
int16_t *dynamic_shaping_array, last_shaping_weight;
int static_shaping_weight;
};
typedef struct {
struct adpcm_context *normal_cnxt;
struct adpcm_context *rddancy_cnxt;
TYPE_RINGBUF *ringbuf_original;
TYPE_RINGBUF *ringbuf_encode;
uint32_t rddancy_num;
}AdpcmEncoder;
typedef struct {
uint8_t *rddancy_encbuf;
uint32_t rddancy_num;
uint32_t rddancy_encode_len;
uint32_t rddancy_encbuf_num;
uint32_t rddancy_encbuf_pos;
uint32_t block_size;
uint8_t plc_sta;
LowcFE_c *lowcfe;
int16_t *decode_buf;
}AdpcmDecoder;
typedef uint64_t rms_error_t; // best if "double" or "uint64_t", "float" okay in a pinch
#define MAX_RMS_ERROR UINT64_MAX
#define NOISE_SHAPING_OFF 0 // flat noise (no shaping)
#define NOISE_SHAPING_STATIC 0x100 // static 1st-order shaping (configurable, highpass default)
#define NOISE_SHAPING_DYNAMIC 0x200 // dynamically tilted noise based on signal
#define LOOKAHEAD_DEPTH 0x0ff // depth of search
#define LOOKAHEAD_EXHAUSTIVE 0x800 // full breadth of search (all branches taken)
#define LOOKAHEAD_NO_BRANCHING 0x400 // no branches taken (internal use only!)
#define CLIP(data, min, max) \
if ((data) > (max)) data = max; \
else if ((data) < (min)) data = min;
#define NIBBLE_TO_DELTA(b,n) ((n)<(1<<((b)-1))?(n)+1:(1<<((b)-1))-1-(n))
#define DELTA_TO_NIBBLE(b,d) ((d)<0?(1<<((b)-1))-1-(d):(d)-1)
#define NOISE_SHAPING_ENABLED (NOISE_SHAPING_DYNAMIC | NOISE_SHAPING_STATIC)
#define adpcm_malloc malloc
#define adpcm_free free
static void win_average_buffer (float *samples, int sample_count, int half_width);
int adpcm_encode(AdpcmEncoder *adpcm_enc, uint8_t *outbuf, int *outbufsize, int16_t *inbuf, int inbufcount, int bps);
int adpcm_decode(AdpcmDecoder *adpcm_dec, int16_t *outbuf, const uint8_t *inbuf, uint32_t inbufsize, int bps);
AdpcmEncoder *adpcm_encoder_create(int sample_rate, int lookahead, int noise_shaping, int block_size, int redundancy_num);
AdpcmDecoder *adpcm_decoder_create(int block_size, int redundancy_num);
int adpcm_decode_plc(AdpcmDecoder *adpcm_dec, int16_t *outbuf);
#endif
+189
View File
@@ -0,0 +1,189 @@
////////////////////////////////////////////////////////////////////////////
// **** ADPCM-XQ **** //
// Xtreme Quality ADPCM Encoder/Decoder //
// Copyright (c) 2024 David Bryant. //
// All Rights Reserved. //
// Distributed under the BSD Software License (see license.txt) //
////////////////////////////////////////////////////////////////////////////
// adpcm-dns.c
// This module handles the implementation of "dynamic noise shaping" which is
// designed to move the spectrum of the quantization noise introduced by lossy
// compression up or down in frequency so that it is more likely to be masked
// by the source material.
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include "adpcm_code.h"
#define FILTER_LENGTH 15
#define WINDOW_LENGTH 101
#define MIN_BLOCK_SAMPLES 16
static void win_average_buffer (float *samples, int sample_count, int half_width);
// Generate the shaping values for the specified buffer of stereo or mono samples,
// one shaping value output for each sample (or stereo pair of samples). This is
// calculated by filtering the audio at fs/6 (7350 Hz at 44.1 kHz) and comparing
// the averaged levels above and below that frequency. The output shaping values
// are nominally in the range of +/-1024, with 1024 indicating first-order HF boost
// shaping and -1024 for similar LF boost. However, since -1024 would result in
// infinite DC boost (not useful) a "min_value" is passed in. An output value of
// zero represents no noise shaping. For stereo input data the channels are summed
// for the calculation and the output is still just mono. Note that at the ends of
// the buffer the values diverge from true because not all the required source
// samples are visible. Use this formula to calculate the number of samples
// required for this process to "settle":
//
// int settle_distance = (WINDOW_LENGTH >> 1) + (FILTER_LENGTH >> 1) + 1;
//
// We also pass in a "last_value" so that we can smoothly interpolate from that
// to the first calculated value during the initial "unknown" samples. This
// reduces discontinuities.
void generate_dns_values (const int16_t *samples, int sample_count, int num_chans, int sample_rate,
int16_t *values, int16_t min_value, int16_t last_value)
{
float dB_offset = 7.3, dB_scaler = 64.0, max_dB, min_dB, max_ratio, min_ratio;
int filtered_count = sample_count - FILTER_LENGTH + 1, i;
float *low_freq, *high_freq;
(void) sample_rate; // unused.
memset (values, 0, sample_count * sizeof (values [0]));
if (filtered_count <= 0)
return;
low_freq = malloc (filtered_count * sizeof (float));
high_freq = malloc (filtered_count * sizeof (float));
// First, directly calculate the lowpassed audio using the 15-tap filter. This is
// a basic sinc with Hann windowing (for a fast transition) and because the filter
// is set to exactly fs/6, some terms are zero (which we can skip). Also, because
// it's linear-phase and has an odd number of terms, we can just subtract the LF
// result from the original to get the HF values.
if (num_chans == 1)
for (i = 0; i < filtered_count; ++i, ++samples) {
float filter_sum =
((int32_t) samples [0] + samples [14]) * 0.00150031 +
((int32_t) samples [2] + samples [12]) * -0.01703392 +
((int32_t) samples [3] + samples [11]) * -0.03449186 +
((int32_t) samples [5] + samples [ 9]) * 0.11776258 +
((int32_t) samples [6] + samples [ 8]) * 0.26543272 +
(int32_t) samples [7] * 0.33366033;
high_freq [i] = samples [FILTER_LENGTH >> 1] - filter_sum;
low_freq [i] = filter_sum;
}
else
for (i = 0; i < filtered_count; ++i, samples += 2) {
float filter_sum =
((int32_t) samples [ 0] + samples [ 1] + samples [28] + samples [29]) * 0.00150031 +
((int32_t) samples [ 4] + samples [ 5] + samples [24] + samples [25]) * -0.01703392 +
((int32_t) samples [ 6] + samples [ 7] + samples [22] + samples [23]) * -0.03449186 +
((int32_t) samples [10] + samples [11] + samples [18] + samples [19]) * 0.11776258 +
((int32_t) samples [12] + samples [13] + samples [16] + samples [17]) * 0.26543272 +
((int32_t) samples [14] + samples [15]) * 0.33366033;
high_freq [i] = samples [FILTER_LENGTH & ~1] + samples [FILTER_LENGTH] - filter_sum;
low_freq [i] = filter_sum;
}
// Apply a simple first-order "delta" filter to the lowpass because frequencies below fs/6
// become progressively less important for our purposes as the decorrelation filters make
// those frequencies less and less relevant. Note that after all this filtering, the
// magnitude level of the high frequency array will be 8.7 dB greater than the low frequency
// array when the filters are presented with pure white noise (determined empirically).
for (i = filtered_count - 1; i; --i)
low_freq [i] -= low_freq [i - 1];
low_freq [0] = low_freq [1]; // simply duplicate for the "unknown" sample
// Next we determine the averaged (absolute) levels for each sample using a box filter.
win_average_buffer (low_freq, filtered_count, WINDOW_LENGTH >> 1);
win_average_buffer (high_freq, filtered_count, WINDOW_LENGTH >> 1);
// calculate the minimum and maximum ratios that won't be clipped so that we only
// have to compute the logarithm when needed
max_dB = 1024 / dB_scaler - dB_offset;
min_dB = min_value / dB_scaler - dB_offset;
max_ratio = pow (10.0, max_dB / 20.0);
min_ratio = pow (10.0, min_dB / 20.0);
for (i = 0; i < filtered_count; ++i)
if (high_freq [i] > 1.0 && low_freq [i] > 1.0) {
float ratio = high_freq [i] / low_freq [i];
int shaping_value;
if (ratio >= max_ratio)
shaping_value = 1024;
else if (ratio <= min_ratio)
shaping_value = min_value;
else
shaping_value = (int) floor ((log10 (ratio) * 20.0 + dB_offset) * dB_scaler + 0.5);
values [i + (FILTER_LENGTH >> 1)] = shaping_value;
}
// interpolate the first 7 values from the supplied "last_value" to the first new value
for (i = 0; i < FILTER_LENGTH >> 1; ++i)
values [i] =
(
(int32_t) values [FILTER_LENGTH >> 1] * (i + 1) +
(int32_t) last_value * ((FILTER_LENGTH >> 1) - i) +
(FILTER_LENGTH >> 2)
) / ((FILTER_LENGTH >> 1) + 1);
// finally, copy the value at the end into the 7 final positions because unfortunately
// we have no "next_value" to interpolate with
for (i = filtered_count + (FILTER_LENGTH >> 1); i < sample_count; ++i)
values [i] = values [(FILTER_LENGTH >> 1) + filtered_count - 1];
free (low_freq);
free (high_freq);
}
// Given a buffer of floating values, apply a simple box filter of specified half width
// (total filter width is always odd) to determine the averaged magnitude at each point.
// For the ends, we use only the visible samples.
static void win_average_buffer (float *samples, int sample_count, int half_width)
{
float *output = malloc (sample_count * sizeof (float));
double sum = 0.0;
int m = 0, n = 0;
int i, j, k;
for (i = 0; i < sample_count; ++i) {
k = i + half_width + 1;
j = i - half_width;
if (k > sample_count) k = sample_count;
if (j < 0) j = 0;
while (m < j) {
if ((sum -= samples [m] * samples [m]) < 0.0) sum = 0.0;
m++;
}
while (n < k) {
sum += samples [n] * samples [n];
n++;
}
output [i] = sqrt (sum / (n - m));
}
memcpy (samples, output, sample_count * sizeof (float));
free (output);
}
+131
View File
@@ -0,0 +1,131 @@
#ifndef _INTERCOM_H_
#define _INTERCOM_H_
#include "lwip/sockets.h"
#include "osal/task.h"
#include "osal/mutex.h"
#include "lib/net/eloop/eloop.h"
#include "stream_frame.h"
#include "ringbuf.h"
#include "csi_kernel.h"
#define iLBC_CODE 0
#define OPUS_CODE 0
#define ADPCM_CODE 1
#define FULL_DUPLEX 0
#define HALF_DUPLEX 1
#ifdef PSRAM_HEAP
#define intercom_malloc custom_malloc_psram
#define intercom_zalloc custom_zalloc_psram
#define intercom_free custom_free_psram
#else
#define intercom_malloc custom_malloc
#define intercom_zalloc custom_zalloc
#define intercom_free custom_free
#endif
typedef struct
{
struct list_head list;
uint8* buf_addr;
}audio_node;
#if OPUS_CODE
typedef struct
{
struct list_head list;
struct list_head node_head;
uint8 seq;
uint8 status;
uint16 sort;
uint32 timestamp;
uint32 code_len;
uint32 identify_num;
uint32 node_cnt;
} __attribute__((packed)) sublist;
typedef struct
{
struct list_head list;
uint8* buf_addr;
uint32 data_len;
}ringbuf_manage;
#elif iLBC_CODE || ADPCM_CODE
typedef struct
{
struct list_head list;
struct list_head node_head;
uint8 seq;
uint8 status;
uint16 sort;
uint32 timestamp;
uint32 identify_num;
uint32 node_cnt;
} __attribute__((packed)) sublist;
typedef struct
{
struct list_head list;
uint8* buf_addr;
}ringbuf_manage;
#endif
typedef enum
{
SEND_MODE,
RECV_MODE
}transfer_mode;
typedef struct
{
int udp_sfd;
int ack_sfd;
int udp_cfd;
int ack_cfd;
struct sockaddr_in udp_s_addr;
struct sockaddr_in ack_s_addr;
struct sockaddr_in udp_c_addr;
struct sockaddr_in ack_c_addr;
#if OPUS_CODE
k_task_handle_t recv_task;
k_task_handle_t retransfer_task;
k_task_handle_t encoded_task;
k_task_handle_t decoded_task;
k_task_handle_t record_task;
#elif iLBC_CODE || ADPCM_CODE
struct os_task recv_task;
struct os_task retransfer_task;
struct os_task encoded_task;
struct os_task decoded_task;
struct os_task record_task;
#endif
volatile struct list_head srcList_head;
volatile struct list_head checkList_head;
volatile struct list_head useList_head;
#if OPUS_CODE
char *encoded_task_stack;
char *decoded_task_stack;
char *recv_task_stack;
char *retransfer_task_stack;
#endif
stream *recv_s;
stream *send_s;
} TYPE_INTERCOM_STRUCT;
extern TYPE_INTERCOM_STRUCT *intercom;
extern void intercom_init(void);
void encode_sema_up();
void intercom_encode_switch(uint8 enable);
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+402
View File
@@ -0,0 +1,402 @@
/* 24.May.2005 v.1.0
=============================================================================
U U GGG SSSS TTTTT
U U G S T
U U G GG SSSS T
U U G G S T
UUU GG SSS T
========================================
ITU-T - USER'S GROUP ON SOFTWARE TOOLS
========================================
=============================================================
COPYRIGHT NOTE: This source code, and all of its derivations,
is subject to the "ITU-T General Public License". Please have
it read in the distribution disk, or in the ITU-T
Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO
CODING STANDARDS".
** This code has (C) Copyright by AT&T Corp. **
=============================================================
MODULE: G.711 Appendix I PLC module.
ORIGINAL BY: AT&T Corp.
FUNCTIONS:
g711plc_construct: ...... LowcFE Constructor.
g711plc_dofe: ........... Generate the synthetic signal.
At the beginning of an erasure determine the pitch, and extract
one pitch period from the tail of the signal. Do an OLA for 1/4
of the pitch to smooth the signal. Then repeat the extracted signal
for the length of the erasure. If the erasure continues for more than
10 msec, increase the number of periods in the pitchbuffer. At the end
of an erasure, do an OLA with the start of the first good frame.
The gain decays as the erasure gets longer.
g711plc_addtohistory: ... A good frame was received and decoded.
If right after an erasure, do an overlap add with the synthetic signal.
Add the frame to history buffer.
HISTORY:
24.May.05 v1.0 Release of 1st G711 PLC module <AT&T>.
Integration of this module in STL2005 <Cyril Guillaume & Stephane Ragot - stephane.ragot@francetelecom.com>.
=============================================================================
*/
#include <math.h>
#include <stdio.h>
#include "lowcfe.h"
static void g711plc_scalespeech(LowcFE_c*, short *out);
static void g711plc_getfespeech(LowcFE_c*, short *out, int sz);
static void g711plc_savespeech(LowcFE_c*, short *s);
static int g711plc_findpitch(LowcFE_c*);
static int findpitch_amdf(LowcFE_c *lc);
static void g711plc_overlapadd(Float *l, Float *r, Float *o, int cnt);
static void g711plc_overlapadds(short *l, short *r, short *o, int cnt);
static void g711plc_overlapaddatend(LowcFE_c*, short *s, short *f, int cnt);
static void g711plc_convertsf(short *f, Float *t, int cnt);
static void g711plc_convertfs(Float *f, short *t, int cnt);
static void g711plc_copyf(Float *f, Float *t, int cnt);
static void g711plc_copys(short *f, short *t, int cnt);
static void g711plc_zeros(short *s, int cnt);
void g711plc_construct(LowcFE_c *lc)
{
lc->erasecnt = 0;
lc->pitchbufend = &lc->pitchbuf[HISTORYLEN];
g711plc_zeros(lc->history, HISTORYLEN);
}
/*
* Get samples from the circular pitch buffer. Update poffset so
* when subsequent frames are erased the signal continues.
*/
static void g711plc_getfespeech(LowcFE_c *lc, short *out, int sz)
{
while (sz) {
int cnt = lc->pitchblen - lc->poffset;
if (cnt > sz)
cnt = sz;
g711plc_copys(&lc->pitchbufstart[lc->poffset], out, cnt);
lc->poffset += cnt;
if (lc->poffset == lc->pitchblen)
lc->poffset = 0;
out += cnt;
sz -= cnt;
}
}
static void g711plc_scalespeech(LowcFE_c *lc, short *out)
{
int i;
Float g = (Float)1. - (lc->erasecnt - 1) * ATTENFAC;
for (i = 0; i < FRAMESZ; i++) {
out[i] = (short)(out[i] * g);
g -= ATTENINCR;
}
}
/*
* Generate the synthetic signal.
* At the beginning of an erasure determine the pitch, and extract
* one pitch period from the tail of the signal. Do an OLA for 1/4
* of the pitch to smooth the signal. Then repeat the extracted signal
* for the length of the erasure. If the erasure continues for more than
* 10 msec, increase the number of periods in the pitchbuffer. At the end
* of an erasure, do an OLA with the start of the first good frame.
* The gain decays as the erasure gets longer.
*/
void g711plc_dofe(LowcFE_c *lc,short *out)
{
if (lc->erasecnt == 0) {
/* get history */
g711plc_copys(lc->history, lc->pitchbuf, HISTORYLEN);
lc->pitch = g711plc_findpitch(lc); /* find pitch */
lc->poverlap = lc->pitch >> 2; /* OLA 1/4 wavelength */
/* save original last poverlap samples */
g711plc_copys(lc->pitchbufend - lc->poverlap, lc->lastq,
lc->poverlap);
lc->poffset = 0; /* create pitch buffer with 1 period */
lc->pitchblen = lc->pitch;
lc->pitchbufstart = lc->pitchbufend - lc->pitchblen;
g711plc_overlapadds(lc->lastq, lc->pitchbufstart - lc->poverlap,
lc->pitchbufend - lc->poverlap, lc->poverlap);
/* update last 1/4 wavelength in history buffer */
g711plc_copys(lc->pitchbufend - lc->poverlap,
&lc->history[HISTORYLEN-lc->poverlap], lc->poverlap);
/* get synthesized speech */
g711plc_getfespeech(lc, out, FRAMESZ);
} else if (lc->erasecnt == 1 || lc->erasecnt == 2) {
/* tail of previous pitch estimate */
short tmp[POVERLAPMAX];
int saveoffset = lc->poffset; /* save offset for OLA */
/* continue with old pitchbuf */
g711plc_getfespeech(lc, tmp, lc->poverlap);
/* add periods to the pitch buffer */
lc->poffset = saveoffset;
while (lc->poffset > lc->pitch)
lc->poffset -= lc->pitch;
lc->pitchblen += lc->pitch; /* add a period */
lc->pitchbufstart = lc->pitchbufend - lc->pitchblen;
g711plc_overlapadds(lc->lastq, lc->pitchbufstart - lc->poverlap,
lc->pitchbufend - lc->poverlap, lc->poverlap);
/* overlap add old pitchbuffer with new */
g711plc_getfespeech(lc, out, FRAMESZ);
g711plc_overlapadds(tmp, out, out, lc->poverlap);
g711plc_scalespeech(lc, out);
} else if (lc->erasecnt > 2) {
g711plc_zeros(out, FRAMESZ);
} else {
g711plc_getfespeech(lc, out, FRAMESZ);
g711plc_scalespeech(lc, out);
}
lc->erasecnt++;
g711plc_savespeech(lc, out);
}
/*
* Save a frames worth of new speech in the history buffer.
* Return the output speech delayed by POVERLAPMAX.
*/
static void g711plc_savespeech(LowcFE_c *lc, short *s)
{
/* make room for new signal */
g711plc_copys(&lc->history[FRAMESZ], lc->history, HISTORYLEN - FRAMESZ);
/* copy in the new frame */
g711plc_copys(s, &lc->history[HISTORYLEN - FRAMESZ], FRAMESZ);
/* copy out the delayed frame */
g711plc_copys(&lc->history[HISTORYLEN - FRAMESZ - POVERLAPMAX], s,
FRAMESZ);
}
/*
* A good frame was received and decoded.
* If right after an erasure, do an overlap add with the synthetic signal.
* Add the frame to history buffer.
*/
void g711plc_addtohistory(LowcFE_c *lc, short *s)
{
if (lc->erasecnt) {
short overlapbuf[FRAMESZ];
/*
* longer erasures require longer overlaps
* to smooth the transition between the synthetic
* and real signal.
*/
int olen = lc->poverlap + (lc->erasecnt - 1) * EOVERLAPINCR;
if (olen > FRAMESZ)
olen = FRAMESZ;
g711plc_getfespeech(lc, overlapbuf, olen);
g711plc_overlapaddatend(lc, s, overlapbuf, olen);
lc->erasecnt = 0;
}
g711plc_savespeech(lc, s);
}
/*
* Overlapp add the end of the erasure with the start of the first good frame
* Scale the synthetic speech by the gain factor before the OLA.
*/
static void g711plc_overlapaddatend(LowcFE_c *lc, short *s, short *f, int cnt)
{
int i;
Float incrg;
Float lw, rw;
Float t;
Float incr = (Float)1. / cnt;
Float gain = (Float)1. - (lc->erasecnt - 1) * ATTENFAC;
if (gain < 0.)
gain = (Float)0.;
incrg = incr * gain;
lw = ((Float)1. - incr) * gain;
rw = incr;
for (i = 0; i < cnt; i++) {
t = lw * f[i] + rw * s[i];
if (t > 32767.)
t = (Float)32767.;
else if (t < -32768.)
t = (Float)-32768.;
s[i] = (short)t;
lw -= incrg;
rw += incr;
}
}
/*
* Overlapp add left and right sides
*/
static void g711plc_overlapadd(Float *l, Float *r, Float *o, int cnt)
{
int i;
Float incr, lw, rw, t;
if (cnt == 0)
return;
incr = (Float)1. / cnt;
lw = (Float)1. - incr;
rw = incr;
for (i = 0; i < cnt; i++) {
t = lw * l[i] + rw * r[i];
if (t > (Float)32767.)
t = (Float)32767.;
else if (t < (Float)-32768.)
t = (Float)-32768.;
o[i] = t;
lw -= incr;
rw += incr;
}
}
/*
* Overlapp add left and right sides
*/
static void g711plc_overlapadds(short *l, short *r, short *o, int cnt)
{
int i;
Float incr, lw, rw, t;
if (cnt == 0)
return;
incr = (Float)1. / cnt;
lw = (Float)1. - incr;
rw = incr;
for (i = 0; i < cnt; i++) {
t = lw * l[i] + rw * r[i];
if (t > (Float)32767.)
t = (Float)32767.;
else if (t < (Float)-32768.)
t = (Float)-32768.;
o[i] = (short)t;
lw -= incr;
rw += incr;
}
}
/*
* Estimate the pitch.
* l - pointer to first sample in last 20 msec of speech.
* r - points to the sample PITCH_MAX before l
*/
static int g711plc_findpitch(LowcFE_c *lc)
{
int i, j, k;
int bestmatch;
int bestcorr;
int corr; /* correlation */
unsigned int energy; /* running energy */
unsigned int scale; /* scale correlation by average power */
short *rp; /* segment to match */
short *l = lc->pitchbufend - CORRLEN;
short *r = lc->pitchbufend - CORRBUFLEN;
/* coarse search */
rp = r;
energy = 0;
corr = 0;
for (i = 0; i < CORRLEN; i += NDEC) {
energy += rp[i] * rp[i];
corr += rp[i] * l[i];
}
scale = energy;
if (scale < CORRMINPOWER)
scale = CORRMINPOWER;
corr = corr / sqrt(scale);
bestcorr = corr;
bestmatch = 0;
for (j = NDEC; j <= PITCHDIFF; j += NDEC) {
energy -= rp[0] * rp[0];
energy += rp[CORRLEN] * rp[CORRLEN];
rp += NDEC;
corr = 0;
for (i = 0; i < CORRLEN; i += NDEC)
corr += rp[i] * l[i];
scale = energy;
if (scale < CORRMINPOWER)
scale = CORRMINPOWER;
corr /= sqrt(scale);
if (corr >= bestcorr) {
bestcorr = corr;
bestmatch = j;
}
}
/* fine search */
j = bestmatch - (NDEC - 1);
if (j < 0)
j = 0;
k = bestmatch + (NDEC - 1);
if (k > PITCHDIFF)
k = PITCHDIFF;
rp = &r[j];
energy = 0;
corr = 0;
for (i = 0; i < CORRLEN; i++) {
energy += rp[i] * rp[i];
corr += rp[i] * l[i];
}
scale = energy;
if (scale < CORRMINPOWER)
scale = CORRMINPOWER;
corr = corr / sqrt(scale);
bestcorr = corr;
bestmatch = j;
for (j++; j <= k; j++) {
energy -= rp[0] * rp[0];
energy += rp[CORRLEN] * rp[CORRLEN];
rp++;
corr = 0;
for (i = 0; i < CORRLEN; i++)
corr += rp[i] * l[i];
scale = energy;
if (scale < CORRMINPOWER)
scale = CORRMINPOWER;
corr = corr / sqrt(scale);
if (corr > bestcorr) {
bestcorr = corr;
bestmatch = j;
}
}
return PITCH_MAX - bestmatch;
}
static void g711plc_convertsf(short *f, Float *t, int cnt)
{
int i;
for (i = 0; i < cnt; i++)
t[i] = (Float)f[i];
}
static void g711plc_convertfs(Float *f, short *t, int cnt)
{
int i;
for (i = 0; i < cnt; i++)
t[i] = (short)f[i];
}
static void g711plc_copyf(Float *f, Float *t, int cnt)
{
int i;
for (i = 0; i < cnt; i++)
t[i] = f[i];
}
static void g711plc_copys(short *f, short *t, int cnt)
{
int i;
for (i = 0; i < cnt; i++)
t[i] = f[i];
}
static void g711plc_zeros(short *s, int cnt)
{
int i;
for (i = 0; i < cnt; i++)
s[i] = 0;
}
+65
View File
@@ -0,0 +1,65 @@
/*
============================================================================
File: lowcfe.h V.1.0-24.MAY-2005
============================================================================
UGST/ITU-T G711 Appendix I PLC MODULE
GLOBAL FUNCTION PROTOTYPES
History:
24.May.05 v1.0 First version <AT&T>
Integration in STL2005 <Cyril Guillaume & Stephane Ragot - stephane.ragot@francetelecom.com>
============================================================================
*/
#ifndef __LOWCFE_C_H__
#define __LOWCFE_C_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef USEDOUBLES
typedef double Float; /* likely to be bit-exact between machines */
#else
typedef float Float;
#endif
#define PITCH_MIN 40 /* minimum allowed pitch, 200 Hz */
#define PITCH_MAX 120 /* maximum allowed pitch, 66 Hz */
#define PITCHDIFF (PITCH_MAX - PITCH_MIN)
#define POVERLAPMAX (PITCH_MAX >> 2)/* maximum pitch OLA window */
#define HISTORYLEN (PITCH_MAX * 3 + POVERLAPMAX) /* history buffer length*/
#define NDEC 2 /* 2:1 decimation */
#define CORRLEN 160 /* 20 msec correlation length */
#define CORRBUFLEN (CORRLEN + PITCH_MAX) /* correlation buffer length */
#define CORRMINPOWER (250) /* minimum power */
#define EOVERLAPINCR 32 /* end OLA increment per frame, 4ms */
#define FRAMESZ 80 /* 10 msec at 8kHz */
#define ATTENFAC ((Float).2) /* attenuation factor per 10ms frame */
#define ATTENINCR (ATTENFAC/FRAMESZ) /* attenuation per sample */
typedef struct _LowcFE_c {
int erasecnt; /* consecutive erased frames */
int poverlap; /* overlap based on pitch */
int poffset; /* offset into pitch period */
int pitch; /* pitch estimate */
int pitchblen; /* current pitch buffer length */
short *pitchbufend; /* end of pitch buffer */
short *pitchbufstart; /* start of pitch buffer */
short pitchbuf[HISTORYLEN]; /* buffer for cycles of speech */
short lastq[POVERLAPMAX]; /* saved last quarter wavelengh */
short history[HISTORYLEN]; /* history buffer */
} LowcFE_c;
/* public functions */
void g711plc_construct(LowcFE_c*); /* constructor */
void g711plc_dofe(LowcFE_c*, short *s); /* synthesize speech for erasure */
void g711plc_addtohistory(LowcFE_c*, short *s);
/* add a good frame to history buffer */
#ifdef __cplusplus
}
#endif
#endif /* __LOWCFE_C_H__ */
+107
View File
@@ -0,0 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include "ringbuf.h"
#include "osal/string.h"
#include "custom_mem/custom_mem.h"
int ringbuf_Init(TYPE_RINGBUF *buf, unsigned int buf_size)
{
if(buf == NULL) {
printf("Fail to init ringbuf!\r\n");
return -1;
}
buf->front = 0;
buf->rear = 0;
buf->size = buf_size;
printf("create ringbuf succes,size:%d\n",buf->size);
return 0;
}
int push_ringbuf(TYPE_RINGBUF *buf, void *data, unsigned int len)
{
if(buf->data == NULL) {
printf("Push ringbuf err!\r\n");
return -1;
}
if( (buf->rear + len) > (buf->size))
{
os_memcpy( (buf->data + buf->rear), data, (buf->size - buf->rear));
os_memcpy( buf->data, (data+(buf->size - buf->rear)), (len - buf->size + buf->rear));
}
else
os_memcpy( buf->data + buf->rear, data, len);
buf->rear = (buf->rear+len)%(buf->size);
return 0;
}
int pop_ringbuf(TYPE_RINGBUF *buf, void *data, unsigned int len)
{
if(buf->data == NULL) {
printf("Pop ringbuf err!!\r\n");
return -1;
}
if(buf->front == buf->rear) {
printf("Ringbuf is empty!\r\n");
return -1;
}
if( (buf->front + len) > (buf->size) )
{
os_memcpy( data, (buf->data + buf->front), (buf->size - buf->front));
os_memcpy( (data+(buf->size - buf->front)), buf->data, (len - buf->size + buf->front));
}
else
os_memcpy(data, (buf->data + buf->front), len);
buf->front = (buf->front+len)%(buf->size);
return 0;
}
int pop_ringbuf_notmove(TYPE_RINGBUF *buf, void *data, unsigned int len)
{
if(buf->data == NULL) {
printf("Pop ringbuf err!!\r\n");
return -1;
}
if(buf->front == buf->rear) {
printf("Ringbuf is empty!\r\n");
return -1;
}
if( (buf->front + len) > (buf->size) )
{
os_memcpy( data, (buf->data + buf->front), (buf->size - buf->front));
os_memcpy( (data+(buf->size - buf->front)), buf->data, (len - buf->size + buf->front));
}
else
os_memcpy(data, (buf->data + buf->front), len);
return 0;
}
int ringbuf_pop_available(TYPE_RINGBUF *buf)
{
if(buf == NULL) {
printf(" Get ringbuf available err!\r\n");
return -1;
}
return ( ((buf->rear+buf->size)-buf->front) % (buf->size) );
}
int ringbuf_push_available(TYPE_RINGBUF *buf)
{
if(buf == NULL) {
printf(" Get ringbuf available err!\r\n");
return -1;
}
return ( ((buf->front+buf->size)-buf->rear-1) % (buf->size) );
}
int ringbuf_del(TYPE_RINGBUF *buf)
{
if(buf == NULL) {
printf("Ringbuf del err!\r\n");
return -1;
}
#ifdef PSRAM_HEAP
custom_free_psram(buf);
#else
custom_free(buf);
#endif
buf = NULL;
return 0;
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef __RINGBUF_H
#define __RINGBUF_H
typedef struct ringbuf {
void *data;
volatile unsigned int front;
volatile unsigned int rear;
volatile unsigned int size;
} TYPE_RINGBUF;
extern int ringbuf_Init(TYPE_RINGBUF *buf, unsigned int buf_size);
extern int push_ringbuf(TYPE_RINGBUF *buf, void *data, unsigned int len);
extern int pop_ringbuf(TYPE_RINGBUF *buf, void *data, unsigned int len);
extern int pop_ringbuf_notmove(TYPE_RINGBUF *buf, void *data, unsigned int len);
extern int ringbuf_pop_available(TYPE_RINGBUF *buf);
extern int ringbuf_push_available(TYPE_RINGBUF *buf);
extern int ringbuf_del(TYPE_RINGBUF *buf);
#endif