diff options
| -rw-r--r-- | timestretch.c | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/timestretch.c b/timestretch.c index b15bfe7..1f94837 100644 --- a/timestretch.c +++ b/timestretch.c | |||
| @@ -17,7 +17,9 @@ static size_t g_corr_length; | |||
| 17 | 17 | ||
| 18 | static size_t g_skip; // Per frame skip | 18 | static size_t g_skip; // Per frame skip |
| 19 | static size_t g_offset; // Offset into stream, lower bits | 19 | static size_t g_offset; // Offset into stream, lower bits |
| 20 | static size_t g_firstframe; // If this is set, the caller should provide initial data in g_overlap_buffer | 20 | |
| 21 | #define FRAME_FIRST 0x01 | ||
| 22 | #define FRAME_LAST 0x02 | ||
| 21 | 23 | ||
| 22 | /* some good default for mixing voice, values in micro seconds */ | 24 | /* some good default for mixing voice, values in micro seconds */ |
| 23 | #define OVERLAP 10 // overlapping length (music default = 12 ms) | 25 | #define OVERLAP 10 // overlapping length (music default = 12 ms) |
| @@ -33,7 +35,6 @@ static size_t calc_convert_values( int sample_rate, float tempo ) { | |||
| 33 | 35 | ||
| 34 | free( g_overlap_buffer ); | 36 | free( g_overlap_buffer ); |
| 35 | g_overlap_buffer = malloc( sizeof(short) * g_overlap ); | 37 | g_overlap_buffer = malloc( sizeof(short) * g_overlap ); |
| 36 | g_firstframe = 1; | ||
| 37 | g_offset = 0; | 38 | g_offset = 0; |
| 38 | 39 | ||
| 39 | g_output_length = (sample_rate * OUTPUT_LEN ) / 1000; | 40 | g_output_length = (sample_rate * OUTPUT_LEN ) / 1000; |
| @@ -47,7 +48,7 @@ static size_t calc_convert_values( int sample_rate, float tempo ) { | |||
| 47 | // boost middle of sequence by top of a flat parabola | 48 | // boost middle of sequence by top of a flat parabola |
| 48 | // slope stolen from soundtouch, precalc table | 49 | // slope stolen from soundtouch, precalc table |
| 49 | for( i = 0; i < g_corr_length; ++i ) | 50 | for( i = 0; i < g_corr_length; ++i ) |
| 50 | 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); | 51 | g_overlap_heuristic[i] = (short)16384.0*(-(double)(i*i)/((double)(g_corr_length*g_corr_length))+(double)i/(double)g_corr_length+0.75f); |
| 51 | 52 | ||
| 52 | g_skip = (size_t)( tempo * (float)g_output_length * 65536.0 ); | 53 | g_skip = (size_t)( tempo * (float)g_output_length * 65536.0 ); |
| 53 | g_input_length = g_corr_length + g_output_length + g_overlap; | 54 | g_input_length = g_corr_length + g_output_length + g_overlap; |
| @@ -88,16 +89,15 @@ static unsigned int find_corr_max(const short *input, const short *mixbuf) { | |||
| 88 | } | 89 | } |
| 89 | 90 | ||
| 90 | // Returns the amount of samples that can be discarded from begin of the input buffer | 91 | // Returns the amount of samples that can be discarded from begin of the input buffer |
| 91 | size_t process_frame( short *input, short *output, short *overlap, int lastframe ) { | 92 | size_t process_frame( short *input, short *output, short *overlap, int frame_flag ) { |
| 92 | int i, i_ = (int)g_overlap; | 93 | int i, i_ = (int)g_overlap; |
| 93 | unsigned int offset = 0; | 94 | unsigned int offset = 0; |
| 94 | 95 | ||
| 95 | // The first frame needs to be copied verbatim, | 96 | // The first frame needs to be copied verbatim, |
| 96 | // we do not have anything to mix, yet. | 97 | // we do not have anything to mix, yet. |
| 97 | if( g_firstframe ) { | 98 | if( frame_flag & FRAME_FIRST ) |
| 98 | sampcpy( output, input, g_output_length ); | 99 | sampcpy( output, input, g_output_length ); |
| 99 | g_firstframe = 0; | 100 | else { |
| 100 | } else { | ||
| 101 | offset = find_corr_max( input, overlap ); | 101 | offset = find_corr_max( input, overlap ); |
| 102 | 102 | ||
| 103 | // Cross fade end of last frame with begin of this frame | 103 | // Cross fade end of last frame with begin of this frame |
| @@ -109,7 +109,7 @@ size_t process_frame( short *input, short *output, short *overlap, int lastframe | |||
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | // On the last frame help connect the next frame from input seamlessly | 111 | // On the last frame help connect the next frame from input seamlessly |
| 112 | if( lastframe ) | 112 | if( frame_flag & FRAME_LAST ) |
| 113 | return offset + g_output_length; | 113 | return offset + g_output_length; |
| 114 | 114 | ||
| 115 | // Remember end of this frame for next frame | 115 | // Remember end of this frame for next frame |
| @@ -126,14 +126,13 @@ int main( int args, char **argv ) { | |||
| 126 | size_t in_fill = 0; | 126 | size_t in_fill = 0; |
| 127 | short outbuf[ g_output_length ]; | 127 | short outbuf[ g_output_length ]; |
| 128 | short inbuf [ g_input_length ]; | 128 | short inbuf [ g_input_length ]; |
| 129 | int fd_in = open( "in.raw", O_RDONLY ); | ||
| 130 | int fd_out = open( "out.raw", O_CREAT | O_WRONLY | O_TRUNC ); | ||
| 131 | int first_frame = FRAME_FIRST; | ||
| 132 | (void)args; (void)argv; (void)out_chunk_size; | ||
| 129 | 133 | ||
| 130 | // printf( "DEBUG: OL: %zd SWL: %zd SL: %zd SK: %zd ICM: %zd\n", g_overlap, g_output_length, g_corr_length, g_skip / 65536, g_input_length ); | 134 | // printf( "DEBUG: OL: %zd SWL: %zd SL: %zd SK: %zd ICM: %zd\n", g_overlap, g_output_length, g_corr_length, g_skip / 65536, g_input_length ); |
| 131 | 135 | ||
| 132 | int fd_in = open( "in.raw", O_RDONLY ); | ||
| 133 | int fd_out = open( "out.raw", O_CREAT | O_WRONLY | O_TRUNC ); | ||
| 134 | |||
| 135 | (void)args; (void)argv; (void)out_chunk_size; | ||
| 136 | |||
| 137 | while( 1 ) { | 136 | while( 1 ) { |
| 138 | size_t processed; | 137 | size_t processed; |
| 139 | size_t missing = g_input_length - in_fill; | 138 | size_t missing = g_input_length - in_fill; |
| @@ -148,7 +147,8 @@ int main( int args, char **argv ) { | |||
| 148 | } | 147 | } |
| 149 | 148 | ||
| 150 | // Do one cycle of processing and outputting | 149 | // Do one cycle of processing and outputting |
| 151 | processed = process_frame( inbuf, outbuf, g_overlap_buffer, 0 ); | 150 | processed = process_frame( inbuf, outbuf, g_overlap_buffer, first_frame ); |
| 151 | first_frame = 0; | ||
| 152 | write( fd_out, outbuf, g_output_length * sizeof(short) ); | 152 | write( fd_out, outbuf, g_output_length * sizeof(short) ); |
| 153 | 153 | ||
| 154 | memmove( inbuf, inbuf + processed, ( in_fill - processed ) * sizeof(short) ); | 154 | memmove( inbuf, inbuf + processed, ( in_fill - processed ) * sizeof(short) ); |
