diff options
Diffstat (limited to 'timestretch.c')
-rw-r--r-- | timestretch.c | 28 |
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 |
12 | static short * g_overlap_buffer; | 12 | static short * g_overlap_buffer; |
13 | static short * g_overlap_heuristic; | ||
13 | static size_t g_overlap; | 14 | static size_t g_overlap; |
14 | 15 | ||
15 | static size_t g_input_length; // Minimal length | 16 | static 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 |
29 | static size_t calc_convert_values( int sample_rate, float tempo ) { | 32 | static 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 | |
88 | printf( "%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; |