// 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 #include #include #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 samples to ring with size on position */ { int i,j; j=0; if( pos+size > ring_size ){ for( i=pos; i samples to ring with size on position */ { int i,p1,p2; p1=pos, p2=ringpos(p1-delay, ring_size); for( i=0; i=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 samples to ring with size on position */ { int i,p1,p2; p1=pos, p2=ringpos(p1-delay, ring_size); for( i=0; i> 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 samples to ring with size on position */ { int i,p1,p2; int actval; p1=pos, p2=ringpos(p1-delay, ring_size); for( i=0; i> 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; i0)?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( isnr_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( iis_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 && isnr_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_o ){ pos_rest-=snr_o; pos1+=chnr; } } pos1 -= snr_proc; for( ch=0; chlast_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=snr_o ){ pos_rest-=snr_o; pos1+=chnr; } } pos1 -= snr_proc; for( ch=0; ch 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 ); }