diff options
| author | erdgeist <> | 2013-03-28 15:31:22 +0000 |
|---|---|---|
| committer | erdgeist <> | 2013-03-28 15:31:22 +0000 |
| commit | ddcb4ab4507cac8b3ec36f9d454e98c336b920b5 (patch) | |
| tree | b571f3f5202c33adcb5fb2950b848b263415e1b6 | |
| parent | 9ae78b5594264005979cfa56b364e634b2fe168a (diff) | |
Use specialized memcpy wrapper to avoid missing a sizeof(short). Also get rid off floats around the innerloop. Use precalc table.
| -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; |
