Index: libaf/af_pitch.c =================================================================== --- libaf/af_pitch.c (revision 0) +++ libaf/af_pitch.c (revision 0) @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2007 Charlie Brej + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MPlayer; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include + +#include "af.h" +#include "dsp.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavcodec/dsputil.h" +#define OVERLAY 2 + +// Data for specific instances of this filter +typedef struct af_pitch_s +{ + float pitchshift; + float** out_chan; + float** in_chan; + float* out_buf; + float* window_shape; + int input_index; + int alloc; + int nch; + int windowsize; + int ffr_setup; + FFTContext ffr_cfg; + FFTContext ffr_cfg_inv; + +}af_pitch_t; + +// Initialization and runtime control +static int control(struct af_instance_s* af, int cmd, void* arg) +{ + af_pitch_t* s = af->setup; + + switch(cmd){ + case AF_CONTROL_REINIT:{ + af_data_t* data = arg; + int nch = af->data->nch; + int windowsize = data->rate / 20; + int windowbits = 0; + int tmp; + tmp = windowsize; + while (tmp) { + windowbits++; + tmp >>= 1; + } + windowsize = 1<nch != nch || s->windowsize != windowsize){ + int i; + if(s->out_chan) { + for (i=0; inch; i++){ + free(s->out_chan[i]); + } + free(s->out_chan); + } + s->out_chan = malloc(nch * sizeof(float*)); + if(s->in_chan) { + for (i=0; inch; i++){ + free(s->in_chan[i]); + } + free(s->in_chan); + } + s->in_chan = malloc(nch * sizeof(float*)); + for (i=0; iout_chan[i] = calloc(windowsize, sizeof(float)); + s->in_chan[i] = calloc(windowsize, sizeof(float));; + } + } + if (s->nch != nch){ + s->nch = nch; + s->alloc = nch * sizeof(float) * 64 * 1024; + if(s->out_buf) free(s->out_buf); + s->out_buf = malloc(s->alloc); + } + if (s->windowsize != windowsize){ + s->windowsize = windowsize; + if (s->window_shape) free(s->window_shape); + s->window_shape = calloc(windowsize, sizeof(float)); +// af_window_triang(windowsize, s->window_shape); + af_window_hanning(windowsize, s->window_shape); + if (s->ffr_setup) { + ff_fft_end(&s->ffr_cfg_inv); + ff_fft_end(&s->ffr_cfg); + } + ff_fft_init(&s->ffr_cfg, windowbits,0); + ff_fft_init(&s->ffr_cfg_inv, windowbits,1); + s->ffr_setup=1; + } + + af->data->rate = data->rate; + af->data->nch = data->nch; + af->data->format = AF_FORMAT_FLOAT_NE; + af->data->bps = 4; + return af_test_output(af,data); + } + case AF_CONTROL_COMMAND_LINE: + sscanf((char*)arg,"%f", &s->pitchshift); + return AF_OK; + } + return AF_UNKNOWN; +} + +// Deallocate memory +static void uninit(struct af_instance_s* af) +{ + af_pitch_t* s = af->setup; + int i; + if(s->out_chan) { + for (i=0; inch; i++){ + free(s->out_chan[i]); + } + free(s->out_chan); + } + if(s->in_chan) { + for (i=0; inch; i++){ + free(s->in_chan[i]); + } + free(s->in_chan); + } + if (s->window_shape) free(s->window_shape); + if(s->out_buf) free(s->out_buf); + ff_fft_end(&s->ffr_cfg_inv); + ff_fft_end(&s->ffr_cfg); + + if(af->data) + free(af->data); + if(af->setup) + free(af->setup); +} + + +void fftsimple(af_pitch_t* setup, int ch, float* data_in, float* data_out) +{ + int count = setup->windowsize; + int i; + FFTComplex ffr_vals[count]; + FFTComplex ffr_vals2[count]; + + for (i = 0; iffr_cfg, ffr_vals); + ff_fft_calc (&setup->ffr_cfg, ffr_vals); + + for (i = 0; ipitchshift; + if (indexpitchshift); + angle += offset*2*M_PI; + ffr_vals2[i].re=cos(angle)*amp ; + ffr_vals2[i].im=sin(angle)*amp ; + } + else { + ffr_vals2[i].re=0; + ffr_vals2[i].im=0; + } + } + + + ff_fft_permute(&setup->ffr_cfg_inv, ffr_vals2); + ff_fft_calc (&setup->ffr_cfg_inv, ffr_vals2); + + for (i=0; isetup; // Setup for this instance + float* a = cur->audio; // Audio data + int nch = cur->nch; // Number of channels + int inlen = cur->len/(4*nch); // Number of samples in current audio block + int full_len = inlen+s->input_index; + int i, ch; + float buffers[nch][full_len]; + int windowsize = s->windowsize; + int block_count = (full_len / (windowsize/OVERLAY))-(OVERLAY-1); + if (block_count<0) block_count=0; + + for (ch = 0; chinput_index; i++){ + buffers[ch][i] = s->in_chan[ch][i]; + } + for (i=0; iinput_index+i] = a[i*nch+ch]; + } + } + + + { + int block_index; + int consumed = block_count*(windowsize/OVERLAY); + int remainder = full_len-consumed; + int out_len = consumed*nch*4; + if (s->alloc < out_len){ + s->alloc = out_len*2; + s->out_buf = realloc(s->out_buf, s->alloc); + } + + for (ch=0; chwindow_shape[i]*2; + } + + fftsimple(s, ch, in_block, out_block); + for (i=0; iwindow_shape[i]*2/OVERLAY; + } + + for (i=0; iout_buf[(buffer_offset+i)*nch+ch] = out_block[i] + s->out_chan[ch][i] ; + } + for (i=windowsize/OVERLAY; iout_chan[ch][i-windowsize/OVERLAY] = out_block[i] + s->out_chan[ch][i]; + } + for (i=windowsize-windowsize/OVERLAY; iout_chan[ch][i-windowsize/OVERLAY] = out_block[i]; + } + } + } + + for (ch = 0; chin_chan[ch][i] = buffers[ch][consumed+i]; + } + } + s->input_index = remainder; + cur->audio = s->out_buf; + cur->len = out_len; + return cur; + } +} + +// Allocate memory and set function pointers +static int af_open(af_instance_t* af){ + af_pitch_t* s; + af->control=control; + af->uninit=uninit; + af->play=play; + af->mul.n=1; + af->mul.d=1; + af->data=calloc(1,sizeof(af_data_t)); + af->setup=s=calloc(1,sizeof(af_pitch_t)); + if(af->data == NULL || af->setup == NULL) + return AF_ERROR; + // Set default values + s->pitchshift = 1; + return AF_OK; +} + +// Description of this filter +af_info_t af_info_pitch = { + "Audio filter for changing the pitch", + "pitch", + "Charlie Brej", + "", + AF_FLAGS_NOT_REENTRANT, + af_open +}; Index: libaf/Makefile =================================================================== --- libaf/Makefile (revision 23395) +++ libaf/Makefile (working copy) @@ -15,6 +15,7 @@ af_hrtf.c \ af_karaoke.c \ af_pan.c \ + af_pitch.c \ af_resample.c \ af_sinesuppress.c \ af_sub.c \ @@ -30,5 +31,6 @@ SRCS_COMMON-$(HAVE_SYS_MMAN_H) += af_export.c SRCS_COMMON-$(LIBAVCODEC) += af_lavcresample.c +SRCS_COMMON-$(LIBAVCODEC_A) += af_pitch.c include ../mpcommon.mak Index: libaf/af.c =================================================================== --- libaf/af.c (revision 23395) +++ libaf/af.c (working copy) @@ -31,6 +31,7 @@ extern af_info_t af_info_center; extern af_info_t af_info_sinesuppress; extern af_info_t af_info_karaoke; +extern af_info_t af_info_pitch; static af_info_t* filter_list[]={ &af_info_dummy, @@ -61,6 +62,7 @@ &af_info_center, &af_info_sinesuppress, &af_info_karaoke, + &af_info_pitch, NULL };