[prev in list] [next in list] [prev in thread] [next in thread]
List: mplayer-dev-eng
Subject: Re: [MPlayer-dev-eng] [PATCH] AF Pitch filter
From: Charlie Brej <mplayer () brej ! org>
Date: 2007-05-28 17:09:16
Message-ID: 465B0CBC.7080901 () brej ! org
[Download RAW message or body]
Diego Biurrun wrote:
> On Mon, May 28, 2007 at 03:44:36PM +0100, Charlie Brej wrote:
>> The new patch is attached.
>>
>> --- libaf/af_pitch.c (revision 0)
>> +++ libaf/af_pitch.c (revision 0)
>> @@ -0,0 +1,284 @@
>> +/*
>> + (C) Charlie Brej
>> + License: GPL
>> +
>> +*/
>
> Add a standard license header as found in other files, for example
> vidix/*.c.
Attached
["pitch.patch" (text/plain)]
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 <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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<<windowbits;
+ if(s->nch != nch || s->windowsize != windowsize){
+ int i;
+ if(s->out_chan) {
+ for (i=0; i<s->nch; i++){
+ free(s->out_chan[i]);
+ }
+ free(s->out_chan);
+ }
+ s->out_chan = malloc(nch * sizeof(float*));
+ if(s->in_chan) {
+ for (i=0; i<s->nch; i++){
+ free(s->in_chan[i]);
+ }
+ free(s->in_chan);
+ }
+ s->in_chan = malloc(nch * sizeof(float*));
+ for (i=0; i<nch; i++){
+ s->out_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; i<s->nch; i++){
+ free(s->out_chan[i]);
+ }
+ free(s->out_chan);
+ }
+ if(s->in_chan) {
+ for (i=0; i<s->nch; 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; i<count; i++){
+ ffr_vals[i].re=data_in[i];
+ ffr_vals[i].im=0;
+ }
+
+ ff_fft_permute(&setup->ffr_cfg, ffr_vals);
+ ff_fft_calc (&setup->ffr_cfg, ffr_vals);
+
+ for (i = 0; i<count; i++){
+ int index = i*setup->pitchshift;
+ if (index<count/2){
+ float real = ffr_vals[index].re;
+ float imag = ffr_vals[index].im;
+ float angle = atan2(imag, real);
+ float amp = sqrt(real*real+imag*imag);
+ float offset = (float)i/(setup->pitchshift);
+ 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; i<count; i++){
+ data_out[i] = ffr_vals2[i%count].re / count;
+ }
+
+
+}
+
+
+
+
+// Filter data through filter
+static af_data_t* play(struct af_instance_s* af, af_data_t* data)
+{
+ af_data_t* cur = data; // Current working data
+ af_pitch_t* s = af->setup; // 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; ch<nch; ch++){
+ for (i=0; i<s->input_index; i++){
+ buffers[ch][i] = s->in_chan[ch][i];
+ }
+ for (i=0; i<inlen; i++){
+ buffers[ch][s->input_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; ch<nch; ch++){
+ for (block_index=0; block_index<block_count; block_index++){
+ float out_block[windowsize];
+ int buffer_offset = block_index*(windowsize/OVERLAY);
+ float in_block[windowsize];
+ for (i=0; i<windowsize; i++){
+ in_block[i] = buffers[ch][buffer_offset+i] * s->window_shape[i]*2;
+ }
+
+ fftsimple(s, ch, in_block, out_block);
+ for (i=0; i<windowsize; i++){
+ out_block[i] *= s->window_shape[i]*2/OVERLAY;
+ }
+
+ for (i=0; i<windowsize/OVERLAY; i++){
+ s->out_buf[(buffer_offset+i)*nch+ch] = out_block[i] + s->out_chan[ch][i] ;
+ }
+ for (i=windowsize/OVERLAY; i<windowsize-windowsize/OVERLAY; i++){
+ s->out_chan[ch][i-windowsize/OVERLAY] = out_block[i] + s->out_chan[ch][i];
+ }
+ for (i=windowsize-windowsize/OVERLAY; i<windowsize; i++){
+ s->out_chan[ch][i-windowsize/OVERLAY] = out_block[i];
+ }
+ }
+ }
+
+ for (ch = 0; ch<nch; ch++){
+ for (i=0; i<remainder; i++){
+ s->in_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
};
_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@mplayerhq.hu
http://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic