[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