[FFmpeg-soc] GSoC 2008 qualification task Nellymoser forward transform
Tomasz Żernicki
tzernicki at o2.pl
Fri Apr 18 21:24:26 CEST 2008
Hi,
I'm enclosing an implementation of Nellymoser forward transform.
The main part is in function
void apply_mdct(MDCTContext *mdct_ctx, float *in, float *coefs);
The usage of this program is:
./mdct_test ./input_file ./output_file
where input and output files are in text format.
Example of input_file:
1
2
4
5
...
nellymoserenc_test.c
-------------------------------------
#include "avcodec.h"
#include "random.h"
#include "dsputil.h"
#include <stdio.h>
#define PI 3.141592653589
#define NELLY_BANDS 23
#define NELLY_BLOCK_LEN 64
#define NELLY_HEADER_BITS 116
#define NELLY_DETAIL_BITS 198
#define NELLY_BUF_LEN 128
#define NELLY_FILL_LEN 124
#define NELLY_BIT_CAP 6
#define NELLY_BASE_OFF 4228
#define NELLY_BASE_SHIFT 19
#define NELLY_SAMPLES (2 * NELLY_BUF_LEN)
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
float state[64];
int add_bias;
int scale_bias;
DSPContext dsp;
MDCTContext imdct_ctx;
DECLARE_ALIGNED_16(float,imdct_tmp[NELLY_BUF_LEN]);
DECLARE_ALIGNED_16(float,imdct_out[NELLY_BUF_LEN * 2]);
float sine_window[128];
float mdct_tmp[NELLY_BUF_LEN];
void overlap_and_window(float *state, float *audio)
{
int bot, mid_up, mid_down, top;
float s_bot, s_top;
bot = 0;
top = NELLY_BUF_LEN-1;
mid_up = NELLY_BUF_LEN/2;
mid_down = (NELLY_BUF_LEN/2)-1;
while (bot < NELLY_BUF_LEN/4) {
s_bot = audio[bot];
s_top = -audio[top];
audio[bot] = (-audio[mid_up]*sine_window[bot]-state[bot ]*sine_window[top])/scale_bias + add_bias;
audio[top] = (-state[bot ]*sine_window[bot]+audio[mid_up]*sine_window[top])/scale_bias + add_bias;
state[bot] = audio[mid_down];
audio[mid_down] = (s_top *sine_window[mid_down]-state[mid_down]*sine_window[mid_up])/scale_bias + add_bias;
audio[mid_up ] = (-state[mid_down]*sine_window[mid_down]-s_top *sine_window[mid_up])/scale_bias + add_bias;
state[mid_down] = s_bot;
bot++;
mid_up++;
mid_down--;
top--;
}
}
/**
Nellymoser forward transform
*/
void apply_mdct(MDCTContext *mdct_ctx, float *in, float *coefs)
{
float in_buff[NELLY_BUF_LEN];
int k;
memcpy(&in_buff[0], &in[NELLY_BUF_LEN], NELLY_BUF_LEN*sizeof(float));
for(k=0;k<NELLY_BUF_LEN;k++) in[k+NELLY_BUF_LEN] *= sine_window[NELLY_BUF_LEN - 1 - k];
for(k=0;k<NELLY_BUF_LEN;k++) in[k] *= sine_window[k];
//memset(&in[NELLY_FILL_LEN], 0, 8 * sizeof(float));
ff_mdct_calc(mdct_ctx, coefs, in, mdct_tmp);
for(k=0;k<NELLY_BUF_LEN;k++) coefs[k] /= 8.0;
memcpy(&in[0], &in_buff[0], NELLY_BUF_LEN*sizeof(float));
}
void apply_imdct(MDCTContext *mdct_ctx, float *coefs, float *aptr)
{
memset(&aptr[NELLY_FILL_LEN], 0,
(NELLY_BUF_LEN - NELLY_FILL_LEN) * sizeof(float));
ff_imdct_calc(mdct_ctx, imdct_out,
coefs, imdct_tmp);
/* XXX: overlapping and windowing should be part of a more
generic imdct function */
memcpy(&aptr[0],&imdct_out[NELLY_BUF_LEN+NELLY_BUF_LEN/2], (NELLY_BUF_LEN/2)*sizeof(float));
memcpy(&aptr[NELLY_BUF_LEN / 2],&imdct_out[0],(NELLY_BUF_LEN/2)*sizeof(float));
overlap_and_window(state, aptr);
}
int main(int argc, char **argv)
{
FILE *f, *fout;
MDCTContext mdct_ctx;
int k,i;
float in[256];
float audio[128];
float imdct_in[128];
float imdct_out[256];
float audio_out[128];
memset(&in[0], 0, 2*NELLY_BUF_LEN*sizeof(float) );
memset(&audio[0], 0, NELLY_BUF_LEN*sizeof(float) );
memset(&imdct_in[0], 0, NELLY_BUF_LEN*sizeof(float) );
memset(&imdct_out[0], 0, 2*NELLY_BUF_LEN*sizeof(float) );
if(argc!=3) {
fprintf(stderr, "usage:\n");
fprintf(stderr, "\tmdct_test input_file output_file\n");
fprintf(stderr, "Input and output files should be in text format\n");
exit(1);
}
printf("Audio encoding\n");
f = fopen(argv[1], "r");
if (!f) {
fprintf(stderr, "could not open %s\n", argv[1]);
exit(1);
}
fout = fopen(argv[2], "w");
if (!f) {
fprintf(stderr, "could not open %s\n", argv[2]);
exit(1);
}
/* Generate overlap window */
for (i=0 ; i<NELLY_BUF_LEN; i++) {
sine_window[i] = sin((i + 0.5) / 256.0 * PI);
}
ff_mdct_init(&mdct_ctx, 8, 0);
ff_mdct_init(&imdct_ctx, 8, 1);
add_bias = 0;
scale_bias = 1*8;
while(!feof(f))
{
for(k=0;k<NELLY_BUF_LEN;k++) fscanf(f, "%f", &in[k+NELLY_BUF_LEN]);
apply_mdct (&mdct_ctx, in, imdct_in);
apply_imdct(&imdct_ctx, &imdct_in[0], &audio[0]);
for(k=0;k<NELLY_BUF_LEN;k++) fprintf(fout, "%d\n", round(audio[k]));
}
fclose(f);
fclose(fout);
return 0;
}
More information about the FFmpeg-soc
mailing list