summaryrefslogtreecommitdiff
path: root/timestretch.c
diff options
context:
space:
mode:
Diffstat (limited to 'timestretch.c')
-rw-r--r--timestretch.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/timestretch.c b/timestretch.c
index 63ba059..7f9bcd6 100644
--- a/timestretch.c
+++ b/timestretch.c
@@ -10,6 +10,7 @@
10 10
11// global values 11// global values
12static short * g_overlap_buffer; 12static short * g_overlap_buffer;
13static short * g_overlap_heuristic;
13static size_t g_overlap; 14static size_t g_overlap;
14 15
15static size_t g_input_length; // Minimal length 16static size_t g_input_length; // Minimal length
@@ -25,8 +26,11 @@ static size_t g_firstframe; // If this is set, the caller should provide ini
25#define CORR_WINDOW 15 // overlapping correlation window length (music default = 28 ms) 26#define CORR_WINDOW 15 // overlapping correlation window length (music default = 28 ms)
26#define OUTPUT_LEN 30 // one processing sequence length in milliseconds (music default = 82 ms) 27#define OUTPUT_LEN 30 // one processing sequence length in milliseconds (music default = 82 ms)
27 28
29#define sampcpy(A,B,C) memcpy((A),(B),(C)*sizeof(short))
30
28// Returns the length of one output frame 31// Returns the length of one output frame
29static size_t calc_convert_values( int sample_rate, float tempo ) { 32static size_t calc_convert_values( int sample_rate, float tempo ) {
33 unsigned int i;
30 g_overlap = ( sample_rate * OVERLAP ) / 1000; 34 g_overlap = ( sample_rate * OVERLAP ) / 1000;
31 35
32 free( g_overlap_buffer ); 36 free( g_overlap_buffer );
@@ -38,6 +42,11 @@ static size_t calc_convert_values( int sample_rate, float tempo ) {
38 g_output_length = g_overlap; 42 g_output_length = g_overlap;
39 g_corr_length = ( sample_rate * CORR_WINDOW ) / 1000; 43 g_corr_length = ( sample_rate * CORR_WINDOW ) / 1000;
40 44
45 free( g_overlap_heuristic );
46 g_overlap_heuristic = malloc( sizeof(short) * g_corr_length );
47 for( i = 0; i < g_corr_length; ++i )
48 g_overlap_heuristic[i] = (short)16384.0*(-(double)i*(double)i/((double)g_corr_length*(double)g_corr_length)+(double)i/(double)g_corr_length+0.75f);
49
41 g_skip = (size_t)( tempo * (float)g_output_length * 65536.0 ); 50 g_skip = (size_t)( tempo * (float)g_output_length * 65536.0 );
42 g_input_length = g_corr_length + g_output_length + g_overlap; 51 g_input_length = g_corr_length + g_output_length + g_overlap;
43 if( g_skip / 65536 > g_input_length ) 52 if( g_skip / 65536 > g_input_length )
@@ -62,22 +71,21 @@ static unsigned int find_corr_max(const short *input, const short *mixbuf) {
62 71
63 // Scans for the best correlation value by testing each possible position 72 // Scans for the best correlation value by testing each possible position
64 for (i = 0; i < g_corr_length; ++i) { 73 for (i = 0; i < g_corr_length; ++i) {
65 double acc, i_f = (double)i, sl_f = (double)g_corr_length; 74 int64_t acc = 0;
66 double heur = 0.75 - ( i_f * i_f ) / ( sl_f * sl_f ) + i_f / sl_f;
67 int64_t acc_i;
68 75
69 for(j = 0, acc_i = 0; j < g_overlap; ++j ) 76 for(j = 0; j < g_overlap; ++j )
70 acc_i += input[i+j] * mixbuf[j]; 77 acc += input[i+j] * mixbuf[j];
71 78
72 // boost middle of sequence by top of a flat parabola 79 // boost middle of sequence by top of a flat parabola
73 // slope stolen from soundtouch 80 // slope stolen from soundtouch
74 acc = (double)acc_i * heur; 81 acc *= g_overlap_heuristic[i];
75 if ( corr_max < acc ) { 82 if ( corr_max < acc ) {
76 offs = i; 83 offs = i;
77 corr_max = acc; 84 corr_max = acc;
78 } 85 }
79 } 86 }
80// printf( "%03d %014.0lf\n", best_offs, best_corr ); 87
88printf( "%03d %016llX\n", offs, (int64_t)corr_max );
81 return offs; 89 return offs;
82} 90}
83 91
@@ -89,7 +97,7 @@ size_t process_frame( short *input, short *output, short *overlap ) {
89 // The first frame needs to be copied verbatim, 97 // The first frame needs to be copied verbatim,
90 // we do not have anything to mix, yet. 98 // we do not have anything to mix, yet.
91 if( g_firstframe ) { 99 if( g_firstframe ) {
92 memcpy( output, input, g_output_length * sizeof(short) ); 100 sampcpy( output, input, g_output_length );
93 g_firstframe = 0; 101 g_firstframe = 0;
94 } else { 102 } else {
95 offset = find_corr_max( input, overlap ); 103 offset = find_corr_max( input, overlap );
@@ -99,11 +107,11 @@ size_t process_frame( short *input, short *output, short *overlap ) {
99 output[i] = ( i_ * overlap[i] + i * input[i+offset] ) / (int)g_overlap; 107 output[i] = ( i_ * overlap[i] + i * input[i+offset] ) / (int)g_overlap;
100 108
101 // Copy rest of the input verbatim 109 // Copy rest of the input verbatim
102 memcpy( output + g_overlap, input + offset + g_overlap, ( g_output_length - g_overlap ) * sizeof(short) ); 110 sampcpy( output + g_overlap, input + offset + g_overlap, g_output_length - g_overlap );
103 } 111 }
104 112
105 // Remember end of this frame for next frame 113 // Remember end of this frame for next frame
106 memcpy( overlap, input + offset + g_output_length, g_overlap * sizeof(short) ); 114 sampcpy( overlap, input + offset + g_output_length, g_overlap );
107 115
108 // Remove the processed samples from the input buffer. 116 // Remove the processed samples from the input buffer.
109 g_offset &= 0xffff; 117 g_offset &= 0xffff;