Mercurial > audlegacy-plugins
view src/sndstretch/sndstretch.c @ 2284:d19b53359b24
cleaned up the sndfile wav plugin, currently limiting it ONLY TO WAV
PLAYBACK. if somebody is more experienced with it and wants to restore
the other formats, go ahead (maybe change the name of the plugin too?).
author | mf0102 <0102@gmx.at> |
---|---|
date | Wed, 09 Jan 2008 15:41:22 +0100 |
parents | 6bb0e52df3d6 |
children |
line wrap: on
line source
// sndstretch.c // // sndstretch - algorithm for adjusting pitch and speed of s16le data // Copyright (C) 2000 Florian Berger // Email: florian.berger@jk.uni-linz.ac.at // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License Version 2 as // published by the Free Software Foundation; // // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // //#define DEBUG #include<stdio.h> #include<stdlib.h> #include<math.h> #include"sndstretch.h" static double _1_div_e = 0.367879441; // 1/e static double _1_m_1_div_e = 0.632120558; // 1-1/e #define RESMAX 65536 #define RESMAXVC 32768 #define LOG2RESMAX 16 #define LOG2RESMAXVC 15 static int _1_div_e_i = 24109; // 1/e * 2^LOG2RESMAX static int _1_m_1_div_e_i = 41427; // 1-1/e * 2^LOG2RESMAX static int _1_div_e_i_vc = 12055; // 1/e * 2^LOG2RESMAXVC static int _1_m_1_div_e_i_vc = 28333; // sqrt(1-1/e^2) * 2^LOG2RESMAXVC //static int _1_div_e_i = 12055; // 1/e * 2^LOG2RESMAX //static int _1_m_1_div_e_i = 20713; // 1-1/e * 2^LOG2RESMAX void InitScaleJob( ScaleJob * job ) { /* nothing to do */ } void InitStretchJob( StretchJob * job ) { job->is_initialized=0; job->snr_rest=0.0; } void InitPitchSpeedJob( PitchSpeedJob * job ) { job->ring_buff = (s16*)0; // init me = (s16*)0 job->ring_buff_old = (s16*)0; // init me = (s16*)0 job->buff_help = (s16*)0; // init me = (s16*)0 job->ring_size = 1; // init me = 1 job->ring_size_old = 0; // init me = 0 job->ring_pos_w = 0; // init me = 0 job->ring_pos_r = 0; // init me = 0 job->is_init = 0; // init me = 0 job->speed_act = 0; // init me = 0 job->pitch_act = 0; // init me = 0 job->fade_shift_act = 0; InitStretchJob(&(job->stretch_job)); InitScaleJob(&(job->scale_job)); } void CleanupPitchSpeedJob( PitchSpeedJob * job ) { free(job->ring_buff); free(job->ring_buff_old); free(job->buff_help); } inline int ringpos( int pos, int size ) { while ( pos >= size ) pos-=size; while ( pos < 0 ) pos+=size; return( pos ); } void ringload( s16 * ringbuff, int ring_size, int pos, s16 *buffer, int size ) /* put <size> samples to ring with size <ring_size> on position <pos> */ { int i,j; j=0; if( pos+size > ring_size ){ for( i=pos; i<ring_size; i++,j++ ) ringbuff[i]=buffer[j]; for( i=0; i<size-ring_size+pos; i++,j++ ) ringbuff[i]=buffer[j]; }else{ for( i=pos; i<size+pos; i++,j++ ) ringbuff[i]=buffer[j]; } } void ringcopy( s16 * src_ring, int src_size, int src_from, int src_to, s16 * dest_ring, int dest_size, int dest_pos ) { int is,id; is=src_from; id=dest_pos; while( is!=src_to ){ dest_ring[id]=src_ring[is]; is=ringpos(is+1,src_size); id=ringpos(id+1,dest_size); } } void ringload_IIR_1_div_e_echo_d( s16 * ringbuff, int ring_size, int pos, s16 *buffer, int size , int delay) /* put <size> samples to ring with size <ring_size> on position <pos> */ { int i,p1,p2; p1=pos, p2=ringpos(p1-delay, ring_size); for( i=0; i<size; i++ ){ ringbuff[p1] =(s16)( (double)buffer[i]*_1_m_1_div_e + (double)ringbuff[p2]*_1_div_e ); p1++; if(p1>=ring_size) p1-=ring_size; p2++; if(p2>=ring_size) p2-=ring_size; } } void ringload_IIR_1_div_e_echo_i( s16 * ringbuff, int ring_size, int pos, s16 *buffer, int size , int delay) /* put <size> samples to ring with size <ring_size> on position <pos> */ { int i,p1,p2; p1=pos, p2=ringpos(p1-delay, ring_size); for( i=0; i<size; i++ ){ ringbuff[p1] =(s16)( ( _1_m_1_div_e_i * buffer[i] + _1_div_e_i * ringbuff[p2] ) >> LOG2RESMAX ); p1++; if(p1>=ring_size) p1-=ring_size; p2++; if(p2>=ring_size) p2-=ring_size; } } void ringload_IIR_1_div_e_echo_i_vc( s16 * ringbuff, int ring_size, int pos, s16 *buffer, int size , int delay) /* put <size> samples to ring with size <ring_size> on position <pos> */ { int i,p1,p2; int actval; p1=pos, p2=ringpos(p1-delay, ring_size); for( i=0; i<size; i++ ){ /* ringbuff[p1] =(s16)( ( _1_m_1_div_e_i_vc * buffer[i] + _1_div_e_i_vc * ringbuff[p2] ) >> LOG2RESMAXVC );*/ actval = _1_m_1_div_e_i_vc * buffer[i] + _1_div_e_i_vc * ringbuff[p2]; /* prevent overflow */ if( actval > (int)0x3FFFFFFF ) actval=(int)0x3FFFFFFF; if( actval < (int)0xC0000000 ) actval=(int)0xC0000000; ringbuff[p1] = actval >> LOG2RESMAXVC; p1++; if(p1>=ring_size) p1-=ring_size; p2++; if(p2>=ring_size) p2-=ring_size; } } /*void ringget ( s16 * ringbuff, int ring_size, int pos, s16 *buffer, int size ) { int i; if( pos+size > ring_size ){ for( i=pos; i<ring_size; i++ ) buffer[i]=ringbuff[i]; for( i=0; i<size-ring_size+pos; i++ ) buffer[i]=ringbuff[i]; }else{ for( i=pos; i<size+pos; i++ ) buffer[i]=ringbuff[i]; } } */ //int sndstretch( // not optimized int sndstretch_not_optimized( /* stretches the sound (not changing pitch !!!) */ /* returns number of output samples produced */ /* chnr simply gives multiples of chnr as snr_prod */ s16 * buffer, int buff_size, /* ring buffer */ int pos_init, /* only initial pos in ringbuffer */ int snr_i, int snr_o, /* enlarge - spec */ int chnr, /* # of channels */ s16 * outbuff, /* output */ int * out_prod, /* # of output-samples produced */ int snr_proc, /* # of in-samples to process */ int initialize /* bool */ ) { static int is_initialized=0; static int snr_o_prod; static int snr_i_act; static int snr_o_act; /* static int snr_offs; */ static int pos_act; static int dsnr; /* static int p1,p2; */ static double snr_rest=0.0; int snr; double snr_d; int i,p1,p2; double fade_in, fade_out; double outd; /* s16 * outbuff; */ /* reset */ if( !is_initialized || initialize || snr_i!=snr_i_act || snr_o!=snr_o_act ){ snr_rest = 0.0; snr_o_prod = 0; snr_i_act = snr_i; snr_o_act = snr_o; dsnr = snr_o_act-snr_i_act; pos_act = pos_init; is_initialized = 1; } /* fprintf(stderr,"pos_act=%d\n",pos_act); */ snr_d = (double)snr_proc*(double)snr_o_act/(double)snr_i_act + snr_rest; snr = (int) (snr_d) / 2 * 2; snr_rest = snr_d - (double)snr; /* fprintf(stderr,"snr=%d\n",snr); */ /* outbuff=malloc(snr*sizeof(s16)); */ /* produce snr samples */ i=0; do { if( snr_o_prod == snr_o_act ) { snr_o_prod=0; /* fprintf(stderr,"!!!!!!!!!!!!!!!!!!!!!!!!!! dsnr = %d\n",dsnr);*/ pos_act = ringpos( pos_act-dsnr, buff_size ); } for ( ; snr_o_prod < snr_o_act && i<snr ; snr_o_prod++,i++ ){ p1=pos_act; p2=ringpos( p1-dsnr, buff_size ); // p3=ringpos( p2-dsnr, buff_size ); // p4=ringpos( p3-dsnr, buff_size ); // p2=ringpos( p1-abs(dsnr), buff_size ); // p3=ringpos( p2-abs(dsnr), buff_size ); // p4=ringpos( p3-abs(dsnr), buff_size ); fade_in = (double)snr_o_prod/(double)snr_o_act; fade_out = 1.0-fade_in; // fade1 = (dsnr>0)?fade_out:fade_in; // fade2 = (dsnr>0)?fade_in:fade_out; outd = ( (double)buffer[p1] * fade_out /* fade out */ + (double)buffer[p2] * fade_in /* fade in */ // +( 0.67 * (double)buffer[p1] /* fade out for lengthen */ // + 0.24 * (double)buffer[p2] /* fade out */ // + 0.09 * (double)buffer[p3]) * fade_out /* fade out */ // +( 0.67 * (double)buffer[p2] /* fade in */ // + 0.24 * (double)buffer[p3] /* fade in */ // + 0.09 * (double)buffer[p4]) * fade_in /* fade in */ ); outbuff[i] = outd+0.5; pos_act=ringpos( pos_act+1, buff_size ); } } while( i<snr ); /* fwrite( outbuff, sizeof(s16), snr, stdout ); */ /* free(outbuff); */ *out_prod = snr; /* fprintf(stderr,"snr = %d\n",snr); */ return( *out_prod ); } int sndstretch( // optimized //int sndstretch_optimized( // optimized /* stretches the sound (not changing pitch !!!) */ /* returns number of output samples produced */ /* chnr simply gives multiples of chnr as snr_prod */ s16 * buffer, int buff_size, /* ring buffer */ int pos_init, /* only initial pos in ringbuffer */ int snr_i, int snr_o, /* enlarge - spec */ int chnr, /* # of channels */ s16 * outbuff, /* output */ int * out_prod, /* # of output-samples produced */ int snr_proc, /* # of in-samples to process */ int initialize /* bool */ ) { static int is_initialized=0; static int snr_o_prod; static int snr_i_act; static int snr_o_act; static int pos_act; static int dsnr; static double snr_rest=0.0; static int _RESMAX_div_max, _RESMAX_mod_max; static int fade_in_i, fade_out_i, fade_rest_i; /* not necessarily static */ static int snr; static double snr_d; static int i,p2; /* reset */ if( !is_initialized || initialize || snr_i!=snr_i_act || snr_o!=snr_o_act ){ snr_rest = 0.0; snr_o_prod = 0; snr_i_act = snr_i; snr_o_act = snr_o; dsnr = snr_o_act-snr_i_act; pos_act = pos_init; is_initialized = 1; } snr_d = (double)snr_proc*(double)snr_o_act/(double)snr_i_act + snr_rest; snr = (int) (snr_d) / 2 * 2; snr_rest = snr_d - (double)snr; /* produce snr samples */ i=0; do { if( snr_o_prod == snr_o_act ) { snr_o_prod=0; pos_act = ringpos( pos_act-dsnr, buff_size ); } fade_in_i = RESMAX*((double)snr_o_prod/(double)snr_o_act); fade_out_i = RESMAX-fade_in_i; fade_rest_i= (RESMAX*snr_o_prod)%snr_o_act; _RESMAX_div_max=RESMAX/snr_o_act; _RESMAX_mod_max=RESMAX%snr_o_act; p2=ringpos( pos_act-dsnr, buff_size ); for ( ; snr_o_prod < snr_o_act && i<snr ; snr_o_prod++,i++ ){ fade_in_i +=_RESMAX_div_max; fade_out_i -=_RESMAX_div_max; fade_rest_i+=_RESMAX_mod_max; if(fade_rest_i>snr_o_act){ fade_rest_i-=snr_o_act; fade_in_i++; fade_out_i--; } outbuff[i] = (s16)( ( + (int)buffer[pos_act] * fade_out_i + (int)buffer[p2] * fade_in_i ) >> LOG2RESMAX ); pos_act++; if(pos_act>=buff_size) pos_act-=buff_size; p2++; if(p2 >=buff_size) p2 -=buff_size; } } while( i<snr ); *out_prod = snr; return( *out_prod ); } int sndstretch_job( // optimized //int sndstretch_optimized( // optimized /* stretches the sound (not changing pitch !!!) */ /* returns number of output samples produced */ /* chnr simply gives multiples of chnr as snr_prod */ s16 * buffer, int buff_size, /* ring buffer */ int pos_init, /* only initial pos in ringbuffer */ int snr_i, int snr_o, /* enlarge - spec */ int chnr, /* # of channels */ s16 * outbuff, /* output */ int * out_prod, /* # of output-samples produced */ int snr_proc, /* # of in-samples to process */ int initialize, /* bool */ StretchJob * job ) { /* static int is_initialized=0; static int snr_o_prod; static int snr_i_act; static int snr_o_act; static int pos_act; static int dsnr; static double snr_rest=0.0; static int _RESMAX_div_max, _RESMAX_mod_max; static int fade_in_i, fade_out_i, fade_rest_i;*/ /* not necessarily static */ static int snr; static double snr_d; static int i,p2; #define is_initialized (job->is_initialized ) #define snr_o_prod (job->snr_o_prod ) #define snr_i_act (job->snr_i_act ) #define snr_o_act (job->snr_o_act ) #define pos_act (job->pos_act ) #define dsnr (job->dsnr ) #define snr_rest (job->snr_rest ) #define _RESMAX_div_max (job->_RESMAX_div_max) #define _RESMAX_mod_max (job->_RESMAX_mod_max) #define fade_in_i (job->fade_in_i ) #define fade_out_i (job->fade_out_i ) #define fade_rest_i (job->fade_rest_i ) /* reset */ if( !is_initialized || initialize || snr_i!=snr_i_act || snr_o!=snr_o_act ){ snr_rest = 0.0; snr_o_prod = 0; snr_i_act = snr_i; snr_o_act = snr_o; dsnr = snr_o_act-snr_i_act; pos_act = pos_init; is_initialized = 1; } snr_d = (double)snr_proc*(double)snr_o_act/(double)snr_i_act + snr_rest; snr = (int) (snr_d) / 2 * 2; snr_rest = snr_d - (double)snr; /* produce snr samples */ i=0; do { if( snr_o_prod == snr_o_act ) { snr_o_prod=0; pos_act = ringpos( pos_act-dsnr, buff_size ); } fade_in_i = RESMAX*((double)snr_o_prod/(double)snr_o_act); fade_out_i = RESMAX-fade_in_i; fade_rest_i= (RESMAX*snr_o_prod)%snr_o_act; _RESMAX_div_max=RESMAX/snr_o_act; _RESMAX_mod_max=RESMAX%snr_o_act; p2=ringpos( pos_act-dsnr, buff_size ); for ( ; snr_o_prod < snr_o_act && i<snr ; snr_o_prod++,i++ ){ fade_in_i +=_RESMAX_div_max; fade_out_i -=_RESMAX_div_max; fade_rest_i+=_RESMAX_mod_max; if(fade_rest_i>snr_o_act){ fade_rest_i-=snr_o_act; fade_in_i++; fade_out_i--; } outbuff[i] = (s16)( ( + (int)buffer[pos_act] * fade_out_i + (int)buffer[p2] * fade_in_i ) >> LOG2RESMAX ); pos_act++; if(pos_act>=buff_size) pos_act-=buff_size; p2++; if(p2 >=buff_size) p2 -=buff_size; } } while( i<snr ); *out_prod = snr; return( *out_prod ); #undef is_initialized #undef snr_o_prod #undef snr_i_act #undef snr_o_act #undef pos_act #undef dsnr #undef snr_rest #undef _RESMAX_div_max #undef _RESMAX_mod_max #undef fade_in_i #undef fade_out_i #undef fade_rest_i } //int sndscale( int sndscale_not_optimized( /* rescales the sound (including pitch) */ /* returns number of output samples produced */ s16 * buffer, /* ring buffer */ int snr_i, int snr_o, /* enlarge - spec */ int chnr, /* # of channels */ s16 * outbuff, /* output */ int * out_prod, /* # of output-samples produced */ int snr_proc, /* # of in-samples to process */ /* must be manifold of channels */ int initialize /* bool */ ) { static s16 last_samp[10]; /* 10 channels maximum ;) */ static double pos_d = 0.0; int snr; int pos1, pos2; s16 samp1, samp2; int index1, index2; int ch; double ds; double ratio1, ratio2, outd; if ( initialize ){ for( ch=0; ch<chnr; ch++ ){ last_samp[ch] = 0; } pos_d = 0.0; } ds = 1.0*(double)snr_i/(double)snr_o; /* fprintf(stderr,"ds=%f\n",ds); */ /* fprintf(stderr,"pos_d =%f\n",pos_d);*/ /* produce proper amount of samples */ for( snr=0 ; pos_d < snr_proc/chnr-1 ; pos_d+=ds ){ pos1 = (int)floor(pos_d); pos2 = pos1+1; ratio1 = 1-pos_d+floor(pos_d); ratio2 = pos_d-floor(pos_d); for( ch=0; ch<chnr; ch++ ){ index1 = pos1*chnr+ch; index2 = pos2*chnr+ch; samp1 = (pos_d<0) ? last_samp[ch] : buffer[index1] ; samp2 = buffer[index2]; outd = (double)samp1 * ratio1 + (double)samp2 * ratio2 ; outbuff[snr+ch] = outd+0.5; } snr+=chnr; } pos_d -= (double)(snr_proc/chnr); for( ch=0; ch<chnr; ch++ ){ last_samp[ch] = buffer[snr_proc-chnr+ch]; } *out_prod = snr; /* fprintf(stderr,"snr = %d\n",snr);*/ /* last_samp = buffer[snr_proc-1]; */ return( snr ); } int sndscale( //optimized //int sndscale2p_optimized( /* rescales the sound (including pitch) */ /* returns number of output samples produced */ s16 * buffer, /* ring buffer */ int snr_i, int snr_o, /* enlarge - spec snr_o must not exceed RESMAX */ int chnr, /* # of channels */ s16 * outbuff, /* output */ int * out_prod, /* # of output-samples produced */ int snr_proc, /* # of in-samples to process */ /* must be manifold of channels */ int initialize /* bool */ ) { static s16 last_samp[10]; /* 10 channels maximum ;) */ static int pos_rest; static int snr; static int pos1, pos2; static int ch; static int ratio1_i; static int ds_li, ds_li_c, ds_rest; static int snr_proc_m_chnr; if ( initialize ){ for( ch=0; ch<chnr; ch++ ){ last_samp[ch] = 0; } pos1 = 0; } ds_li = snr_i/snr_o; ds_li_c = ds_li*chnr; ds_rest = snr_i%snr_o; snr_proc_m_chnr = snr_proc-chnr; for( snr=0 ; pos1 < snr_proc_m_chnr ; pos1+=ds_li_c ){ pos2 = pos1+chnr; ratio1_i = snr_o-pos_rest; if (pos1<0){ for( ch=0; ch<chnr; ch++ ){ outbuff[snr+ch] = (s16) ( ( (int)last_samp[ch] * ratio1_i + (int)buffer[pos2+ch] * pos_rest ) / snr_o ) ; } } else { for( ch=0; ch<chnr; ch++ ){ outbuff[snr+ch] = (s16) ( ( (int)buffer[pos1+ch] * ratio1_i + (int)buffer[pos2+ch] * pos_rest ) / snr_o ) ; } } snr+=chnr; pos_rest+=ds_rest; if( pos_rest>=snr_o ){ pos_rest-=snr_o; pos1+=chnr; } } pos1 -= snr_proc; for( ch=0; ch<chnr; ch++ ){ last_samp[ch] = buffer[snr_proc-chnr+ch]; } *out_prod = snr; return( snr ); } int sndscale_job( //optimized //int sndscale2p_optimized( /* rescales the sound (including pitch) */ /* returns number of output samples produced */ s16 * buffer, /* ring buffer */ int snr_i, int snr_o, /* enlarge - spec snr_o must not exceed RESMAX */ int chnr, /* # of channels */ s16 * outbuff, /* output */ int * out_prod, /* # of output-samples produced */ int snr_proc, /* # of in-samples to process */ /* must be manifold of channels */ int initialize, /* bool */ ScaleJob * job ) { /* static s16 * last_samp; static int pos_rest; static int snr; static int pos1, pos2; static int ch; static int ratio1_i; static int ds_li, ds_li_c, ds_rest; static int snr_proc_m_chnr;*/ #define last_samp job->last_samp #define pos_rest job->pos_rest #define snr job->snr #define pos1 job->pos1 #define pos2 job->pos2 #define ch job->ch #define ratio1_i job->ratio1_i #define ds_li job->ds_li #define ds_li_c job->ds_li_c #define ds_rest job->ds_rest #define snr_proc_m_chnr job->snr_proc_m_chnr if ( initialize ){ for( ch=0; ch<chnr; ch++ ){ last_samp[ch] = 0; } pos1 = 0; } ds_li = snr_i/snr_o; ds_li_c = ds_li*chnr; ds_rest = snr_i%snr_o; snr_proc_m_chnr = snr_proc-chnr; for( snr=0 ; pos1 < snr_proc_m_chnr ; pos1+=ds_li_c ){ pos2 = pos1+chnr; ratio1_i = snr_o-pos_rest; if (pos1<0){ for( ch=0; ch<chnr; ch++ ){ outbuff[snr+ch] = (s16) ( ( (int)last_samp[ch] * ratio1_i + (int)buffer[pos2+ch] * pos_rest ) / snr_o ) ; } } else { for( ch=0; ch<chnr; ch++ ){ outbuff[snr+ch] = (s16) ( ( (int)buffer[pos1+ch] * ratio1_i + (int)buffer[pos2+ch] * pos_rest ) / snr_o ) ; } } snr+=chnr; pos_rest+=ds_rest; if( pos_rest>=snr_o ){ pos_rest-=snr_o; pos1+=chnr; } } pos1 -= snr_proc; for( ch=0; ch<chnr; ch++ ){ last_samp[ch] = buffer[snr_proc-chnr+ch]; } *out_prod = snr; return( snr ); #undef last_samp #undef pos_rest #undef snr #undef pos1 #undef pos2 #undef ch #undef ratio1_i #undef ds_li #undef ds_li_c #undef ds_rest #undef snr_proc_m_chnr } int snd_pitch_speed( /* input */ s16 *buff_i, int channels, int snr_proc, /* algorihm parameters */ int initialize, double pitch, double speed, int fade_shift, /* output */ s16 * buff_o, int * snr_produced ) { static s16 * ring_buff = (s16*)0; static s16 * ring_buff_old = (s16*)0; static s16 * buff_help = (s16*)0; static int ring_size = 1; static int ring_size_old = 0; static int ring_pos_w = 0; static int ring_pos_r = 0; static int snr_scale_i; static int snr_scale_o; static int snr_stretch_i; static int snr_stretch_o; static int snr_proc_scale; static int snr_proc_stretch; static int is_init = 0; static int dsnr; static double speed_act = 0; static double pitch_act = 0; static double fade_shift_act = 0; int snr_prod; double speed_eff; double pitch_eff; int scaling_first; int snr_stretching_i_max; int snr_stretching_o_max; // int channels = 2; int init_me = 0; speed_eff = speed/pitch; pitch_eff = pitch; scaling_first=0; // if( pitch > 1.0 ) scaling_first=0; else scaling_first=1; if ( !is_init || initialize || speed!=speed_act || pitch!=pitch_act || fade_shift!=fade_shift_act ){ if( !is_init || initialize ) init_me=1; else init_me=0; #ifdef DEBUG fprintf(stderr,"snd_stretch_scale - init - pitch:%f, speed:%f\n",pitch,speed); #endif speed_act = speed; pitch_act = pitch; fade_shift_act = fade_shift; // if (ring_buff!=0) free(ring_buff); // if (buff_help!=0) free(buff_help); if (initialize != -1){ dsnr = fade_shift; // dsnr = 1764; // 25Hz // dsnr = 1536; // 30Hz // dsnr = 1102; // 40Hz // dsnr = 882; // 50Hz if( scaling_first ){ snr_stretching_i_max = ceil((double)snr_proc/pitch_act); snr_stretching_i_max += channels-1; snr_stretching_i_max /= channels; snr_stretching_i_max *= channels; } else { snr_stretching_i_max = (snr_proc+channels-1)/channels*channels; } snr_stretching_o_max = ceil((double)snr_stretching_i_max / speed_eff); snr_stretching_o_max = (snr_stretching_o_max+channels-1)/channels*channels; ring_size = snr_stretching_o_max /* for reading */ + dsnr*channels /* for grabbing back */ + dsnr*channels /* for readpos catching */ /* up with writepos */ + 2*dsnr*channels ; /* for 2 pre - echos */ // ring_size = snr_stretching_o_max+3*dsnr*channels; if( ring_size <= ring_size_old ){ ring_size = ring_size_old; #ifdef DEBUG fprintf(stderr," ring_size = %d \n",ring_size); #endif } else { /* if (ring_buff!=0) free(ring_buff); if (buff_help!=0) free(buff_help); ring_buff = calloc( ring_size, sizeof(s16) ); buff_help = calloc( 65536, sizeof(s16) ); ring_pos_r = 0;*/ if (buff_help!=0) free(buff_help); ring_buff_old = ring_buff; ring_buff = calloc( ring_size, sizeof(s16) ); buff_help = calloc( 65536, sizeof(s16) ); if (ring_buff_old!=0) ringcopy( ring_buff, ring_size, ring_pos_r, ring_pos_w, ring_buff_old, ring_size_old, ring_pos_r ); if (ring_buff_old!=0) free(ring_buff_old); // ring_pos_w=ringpos(ring_pos_w+ring_size_old,ring_size); #ifdef DEBUG fprintf(stderr," %d s16-samples reserved\n",ring_size); #endif } ring_pos_w = ringpos( ring_pos_r + /* base */ dsnr*channels /* for grabing back */ // dsnr*2 /* for grabing back */ // why *2 , ring_size ); #ifdef DEBUG fprintf(stderr," ring_pos_w = %d\n",ring_pos_w); #endif ring_pos_w = (ring_pos_w+(channels-1))/channels*channels; ring_size_old = ring_size; is_init = 1; } else { /* initialize == -1 */ if (ring_buff!=0) free(ring_buff); if (buff_help!=0) free(buff_help); /* buffers are released -> leave the function */ return 0; /* !!! sloppy */ } } if ( fabs(speed_eff-1.0)>0.001 ){ /* 0.001 ?! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! this should be examined to the limits !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ snr_stretch_i = (double)dsnr/(1.0/speed_eff-1.0); snr_stretch_o = fabs(snr_stretch_i + dsnr); snr_stretch_i = abs(snr_stretch_i); // fprintf(stderr,"snd_stretch_scale - snr_str_i=%d\n",snr_stretch_i); // fprintf(stderr,"snd_stretch_scale - snr_str_o=%d\n",snr_stretch_o); } else { snr_stretch_i = 10; snr_stretch_o = 10; } if ( pitch_eff!=1.0 ){ snr_scale_i = (double)dsnr/(1.0/pitch_eff-1.0); snr_scale_o = fabs(snr_scale_i + dsnr); snr_scale_i = abs(snr_scale_i); if( 1 /* optimized version doesnt support all scaling */ ){ if( snr_scale_o > 65536 ){ snr_scale_i = (int)((double)snr_scale_i*((double)65536/(double)snr_scale_o)+0.5); snr_scale_o = 65536; // make sure that snr_o for sndscale wont exceed 2^16 } } // fprintf(stderr,"snd_stretch_scale - snr_sc_i=%d\n",snr_stretch_i); // fprintf(stderr,"snd_stretch_scale - snr_sc_o=%d\n",snr_stretch_o); } else { // fprintf(stderr,"snd_stretch_scale - snr_scale_i=snr_scale_o=10\n"); snr_scale_i = 65536; snr_scale_o = 65536; } if( 0/*scaling_first*/ ){ snr_proc_scale = snr_proc; sndscale ( buff_i, snr_scale_i, snr_scale_o, channels, buff_help, &snr_prod, snr_proc_scale, init_me ); /* buff_o, &snr_prod, snr_proc_scale, 0 ); */ if( speed_eff!=1.0 ){ /* add echo only when really stretching */ ringload_IIR_1_div_e_echo_i( ring_buff, ring_size, ring_pos_w, buff_help, snr_prod, dsnr*channels ); } else { ringload( ring_buff, ring_size, ring_pos_w, buff_help, snr_prod ); } ring_pos_w = ringpos( ring_pos_w+snr_prod, ring_size ); snr_proc_stretch = snr_prod; sndstretch ( ring_buff, ring_size, ring_pos_r, snr_stretch_i*channels, snr_stretch_o*channels, channels, buff_o, &snr_prod, snr_proc_stretch, init_me ); ring_pos_r = ringpos( ring_pos_r+snr_prod, ring_size ); } else { // fprintf(stderr,"sndstretch: ring_pos_r = %d\n",ring_pos_r); // fprintf(stderr,"sndstretch: ring_pos_w = %d\n\n",ring_pos_w); snr_prod = snr_proc; if( speed_eff!=1.0 ){ /* add echo only when really stretching */ ringload_IIR_1_div_e_echo_i( ring_buff, ring_size, ring_pos_w, buff_i, snr_proc, dsnr*channels ); } else { ringload( ring_buff, ring_size, ring_pos_w, buff_i, snr_proc ); } ring_pos_w = ringpos( ring_pos_w+snr_proc, ring_size ); snr_proc_stretch = snr_proc; sndstretch ( ring_buff, ring_size, ring_pos_r, snr_stretch_i*channels, snr_stretch_o*channels, channels, buff_help, &snr_prod, snr_proc_stretch, init_me ); ring_pos_r = ringpos( ring_pos_r+snr_prod, ring_size ); snr_proc_scale = snr_prod; // fprintf(stderr,"snr_scale_i, snr_scale_o = %d,%d\n",snr_scale_i, snr_scale_o); sndscale ( buff_help, snr_scale_i, snr_scale_o, channels, buff_o, &snr_prod, snr_proc_scale, init_me ); } *snr_produced = snr_prod; return snr_prod; } int snd_pitch_speed_job( /* input */ s16 *buff_i, int channels, int snr_proc, /* algorihm parameters */ int initialize, double pitch, double speed, int fade_shift, /* output */ s16 * buff_o, int * snr_produced, PitchSpeedJob * job, int vol_corr ) { /* static s16 * ring_buff = (s16*)0; static s16 * ring_buff_old = (s16*)0; static s16 * buff_help = (s16*)0; static int ring_size = 1; static int ring_size_old = 0; static int ring_pos_w = 0; static int ring_pos_r = 0; static int snr_scale_i; static int snr_scale_o; static int snr_stretch_i; static int snr_stretch_o; static int snr_proc_scale; static int snr_proc_stretch; static int is_init = 0; static int dsnr; static double speed_act = 0; static double pitch_act = 0;*/ int snr_prod; double speed_eff; double pitch_eff; int scaling_first; int snr_stretching_i_max; int snr_stretching_o_max; // int channels = 2; int init_me = 0; #define ring_buff job->ring_buff #define ring_buff_old job->ring_buff_old #define buff_help job->buff_help #define ring_size job->ring_size #define ring_size_old job->ring_size_old #define ring_pos_w job->ring_pos_w #define ring_pos_r job->ring_pos_r #define snr_scale_i job->snr_scale_i #define snr_scale_o job->snr_scale_o #define snr_stretch_i job->snr_stretch_i #define snr_stretch_o job->snr_stretch_o #define snr_proc_scale job->snr_proc_scale #define snr_proc_stretch job->snr_proc_stretch #define is_init job->is_init #define dsnr job->dsnr #define speed_act job->speed_act #define pitch_act job->pitch_act #define fade_shift_act job->fade_shift_act speed_eff = speed/pitch; pitch_eff = pitch; scaling_first=0; // if( pitch > 1.0 ) scaling_first=0; else scaling_first=1; if ( !is_init || initialize || speed!=speed_act || pitch!=pitch_act || fade_shift != fade_shift_act ){ if( !is_init || initialize ) init_me=1; else init_me=0; #ifdef DEBUG fprintf(stderr,"snd_stretch_scale - init - pitch:%f, speed:%f\n",pitch,speed); #endif speed_act = speed; pitch_act = pitch; if ( fade_shift != fade_shift_act ){ fprintf(stderr,"changed fade_shift_act\n"); } fade_shift_act = fade_shift; // if (ring_buff!=0) free(ring_buff); // if (buff_help!=0) free(buff_help); if (initialize != -1){ dsnr = fade_shift; // dsnr = 1764; // 25Hz // dsnr = 1536; // 30Hz // dsnr = 1102; // 40Hz // dsnr = 882; // 50Hz if( scaling_first ){ snr_stretching_i_max = ceil((double)snr_proc/pitch_act); snr_stretching_i_max += channels-1; snr_stretching_i_max /= channels; snr_stretching_i_max *= channels; } else { snr_stretching_i_max = (snr_proc+channels-1)/channels*channels; } snr_stretching_o_max = ceil((double)snr_stretching_i_max / speed_eff); snr_stretching_o_max = (snr_stretching_o_max+channels-1)/channels*channels; ring_size = snr_stretching_o_max /* for reading */ + dsnr*channels /* for grabbing back */ + dsnr*channels /* for readpos catching */ /* up with writepos */ + 2*dsnr*channels ; /* for 2 pre - echos */ // ring_size = snr_stretching_o_max+3*dsnr*channels; if( ring_size <= ring_size_old ){ ring_size = ring_size_old; #ifdef DEBUG fprintf(stderr," ring_size = %d \n",ring_size); #endif } else { /* if (ring_buff!=0) free(ring_buff); if (buff_help!=0) free(buff_help); ring_buff = calloc( ring_size, sizeof(s16) ); buff_help = calloc( 65536, sizeof(s16) ); ring_pos_r = 0;*/ if (buff_help!=0) free(buff_help); ring_buff_old = ring_buff; ring_buff = calloc( ring_size, sizeof(s16) ); buff_help = calloc( 65536, sizeof(s16) ); if (ring_buff_old!=0) ringcopy( ring_buff, ring_size, ring_pos_r, ring_pos_w, ring_buff_old, ring_size_old, ring_pos_r ); if (ring_buff_old!=0) free(ring_buff_old); // ring_pos_w=ringpos(ring_pos_w+ring_size_old,ring_size); #ifdef DEBUG fprintf(stderr," %d s16-samples reserved\n",ring_size); #endif } ring_pos_w = ringpos( ring_pos_r + /* base */ dsnr*channels /* for grabing back */ // dsnr*2 /* for grabing back */ // why *2 , ring_size ); #ifdef DEBUG fprintf(stderr," ring_pos_w = %d\n",ring_pos_w); #endif ring_pos_w = (ring_pos_w+(channels-1))/channels*channels; ring_size_old = ring_size; is_init = 1; } else { /* initialize == -1 */ if (ring_buff!=0) free(ring_buff); if (buff_help!=0) free(buff_help); /* buffers are released -> leave the function */ return 0; /* !!! sloppy */ } } if ( fabs(speed_eff-1.0)>0.001 ){ /* 0.001 ?! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! this should be examined to the limits !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ snr_stretch_i = (double)dsnr/(1.0/speed_eff-1.0); snr_stretch_o = fabs(snr_stretch_i + dsnr); snr_stretch_i = abs(snr_stretch_i); // fprintf(stderr,"snd_stretch_scale - snr_str_i=%d\n",snr_stretch_i); // fprintf(stderr,"snd_stretch_scale - snr_str_o=%d\n",snr_stretch_o); } else { snr_stretch_i = 10; snr_stretch_o = 10; } if ( pitch_eff!=1.0 ){ snr_scale_i = (double)dsnr/(1.0/pitch_eff-1.0); snr_scale_o = fabs(snr_scale_i + dsnr); snr_scale_i = abs(snr_scale_i); if( 1 /* optimized version doesnt support all scaling */ ){ if( snr_scale_o > 65536 ){ snr_scale_i = (int)((double)snr_scale_i*((double)65536/(double)snr_scale_o)+0.5); snr_scale_o = 65536; // make sure that snr_o for sndscale wont exceed 2^16 } } // fprintf(stderr,"snd_stretch_scale - snr_sc_i=%d\n",snr_stretch_i); // fprintf(stderr,"snd_stretch_scale - snr_sc_o=%d\n",snr_stretch_o); } else { // fprintf(stderr,"snd_stretch_scale - snr_scale_i=snr_scale_o=10\n"); snr_scale_i = 65536; snr_scale_o = 65536; } if( 0/*scaling_first*/ ){ snr_proc_scale = snr_proc; sndscale_job ( buff_i, snr_scale_i, snr_scale_o, channels, buff_help, &snr_prod, snr_proc_scale, init_me, &(job->scale_job) ); /* buff_o, &snr_prod, snr_proc_scale, 0 ); */ if( speed_eff!=1.0 ){ /* add echo only when really stretching */ if( !vol_corr ){ ringload_IIR_1_div_e_echo_i( ring_buff, ring_size, ring_pos_w, buff_help, snr_prod, dsnr*channels ); } else { ringload_IIR_1_div_e_echo_i_vc( ring_buff, ring_size, ring_pos_w, buff_help, snr_prod, dsnr*channels ); } } else { ringload( ring_buff, ring_size, ring_pos_w, buff_help, snr_prod ); } ring_pos_w = ringpos( ring_pos_w+snr_prod, ring_size ); snr_proc_stretch = snr_prod; sndstretch_job ( ring_buff, ring_size, ring_pos_r, snr_stretch_i*channels, snr_stretch_o*channels, channels, buff_o, &snr_prod, snr_proc_stretch, init_me, &(job->stretch_job) ); ring_pos_r = ringpos( ring_pos_r+snr_prod, ring_size ); } else { // fprintf(stderr,"sndstretch: ring_pos_r = %d\n",ring_pos_r); // fprintf(stderr,"sndstretch: ring_pos_w = %d\n\n",ring_pos_w); snr_prod = snr_proc; if( speed_eff!=1.0 ){ /* add echo only when really stretching */ if( !vol_corr ){ ringload_IIR_1_div_e_echo_i( ring_buff, ring_size, ring_pos_w, buff_i, snr_proc, dsnr*channels ); }else{ ringload_IIR_1_div_e_echo_i_vc( ring_buff, ring_size, ring_pos_w, buff_i, snr_proc, dsnr*channels ); } } else { ringload( ring_buff, ring_size, ring_pos_w, buff_i, snr_proc ); } ring_pos_w = ringpos( ring_pos_w+snr_proc, ring_size ); snr_proc_stretch = snr_proc; sndstretch_job ( ring_buff, ring_size, ring_pos_r, snr_stretch_i*channels, snr_stretch_o*channels, channels, buff_help, &snr_prod, snr_proc_stretch, init_me, &(job->stretch_job) ); ring_pos_r = ringpos( ring_pos_r+snr_prod, ring_size ); snr_proc_scale = snr_prod; // fprintf(stderr,"snr_scale_i, snr_scale_o = %d,%d\n",snr_scale_i, snr_scale_o); sndscale_job ( buff_help, snr_scale_i, snr_scale_o, channels, buff_o, &snr_prod, snr_proc_scale, init_me, &(job->scale_job) ); } *snr_produced = snr_prod; return snr_prod; #undef ring_buff #undef ring_buff_old #undef buff_help #undef ring_size #undef ring_size_old #undef ring_pos_w #undef ring_pos_r #undef snr_scale_i #undef snr_scale_o #undef snr_stretch_i #undef snr_stretch_o #undef snr_proc_scale #undef snr_proc_stretch #undef is_init #undef dsnr #undef speed_act #undef pitch_act #undef fade_shift_act } int snd_stretch_scale(s16 *buff_i, s16 * buff_o, double pitch, double speed, int channels, int snr_proc, int * snr_produced, int initialize ) { return snd_pitch_speed( /* input */ buff_i, channels, snr_proc, /* algorihm parameters */ initialize, pitch, speed, 1764, /* output */ buff_o, snr_produced ); } int snd_stretch_scale_job(s16 *buff_i, s16 * buff_o, double pitch, double speed, int channels, int snr_proc, int * snr_produced, int initialize, PitchSpeedJob * job, int init_job) /* init_job should be set to one the first time the routine is called with the actual job (e.g. for creating a new job) */ { if(init_job){ InitPitchSpeedJob(job); } return snd_pitch_speed_job( /* input */ buff_i, channels, snr_proc, /* algorihm parameters */ initialize, pitch, speed, 1764 , /* output */ buff_o, snr_produced, /* job data */ job, 0 ); }