File: timewarp-file.c

package info (click to toggle)
libsamplerate 0.2.1%2Bds0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 10,448 kB
  • sloc: ansic: 371,374; sh: 121; makefile: 108
file content (234 lines) | stat: -rw-r--r-- 6,050 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
** Copyright (c) 2005-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
** All rights reserved.
**
** This code is released under 2-clause BSD license. Please see the
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <math.h>

#if (HAVE_SNDFILE)

#include <samplerate.h>
#include <sndfile.h>

#define ARRAY_LEN(x)	((int) (sizeof (x) / sizeof ((x) [0])))

#define DEFAULT_CONVERTER 	SRC_SINC_MEDIUM_QUALITY

#define	BUFFER_LEN			1024
#define	INPUT_STEP_SIZE		8

typedef struct
{	sf_count_t	index ;
	double		ratio ;
} TIMEWARP_FACTOR ;

static void usage_exit (const char *progname) ;
static sf_count_t timewarp_convert (SNDFILE *infile, SNDFILE *outfile, int converter, int channels) ;

int
main (int argc, char *argv [])
{	SNDFILE	*infile, *outfile ;
	SF_INFO sfinfo ;
	sf_count_t	count ;

	if (argc != 3)
		usage_exit (argv [0]) ;

	putchar ('\n') ;
	printf ("Input File    : %s\n", argv [argc - 2]) ;
	if ((infile = sf_open (argv [argc - 2], SFM_READ, &sfinfo)) == NULL)
	{	printf ("Error : Not able to open input file '%s'\n", argv [argc - 2]) ;
		exit (1) ;
		} ;

	if (INPUT_STEP_SIZE * sfinfo.channels > BUFFER_LEN)
	{	printf ("\n\nError : INPUT_STEP_SIZE * sfinfo.channels > BUFFER_LEN\n\n") ;
		exit (1) ;
		} ;


	/* Delete the output file length to zero if already exists. */
	remove (argv [argc - 1]) ;

	if ((outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL)
	{	printf ("Error : Not able to open output file '%s'\n", argv [argc - 1]) ;
		sf_close (infile) ;
		exit (1) ;
		} ;

	sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ;

	printf ("Output file   : %s\n", argv [argc - 1]) ;
	printf ("Converter     : %s\n", src_get_name (DEFAULT_CONVERTER)) ;

	count = timewarp_convert (infile, outfile, DEFAULT_CONVERTER, sfinfo.channels) ;

	printf ("Output Frames : %ld\n\n", (long) count) ;

	sf_close (infile) ;
	sf_close (outfile) ;

	return 0 ;
} /* main */

/*==============================================================================
*/

static TIMEWARP_FACTOR warp [] =
{	{	0		, 1.00000001 },
	{	20000	, 1.01000000 },
	{	20200	, 1.00000001 },
	{	40000	, 1.20000000 },
	{	40300	, 1.00000001 },
	{	60000	, 1.10000000 },
	{	60400	, 1.00000001 },
	{	80000	, 1.50000000 },
	{	81000	, 1.00000001 },
} ;

static sf_count_t
timewarp_convert (SNDFILE *infile, SNDFILE *outfile, int converter, int channels)
{	static float input [BUFFER_LEN] ;
	static float output [BUFFER_LEN] ;

	SRC_STATE	*src_state ;
	SRC_DATA	src_data ;
	int			error, warp_index = 0 ;
	sf_count_t	input_count = 0, output_count = 0 ;

	sf_seek (infile, 0, SEEK_SET) ;
	sf_seek (outfile, 0, SEEK_SET) ;

	/* Initialize the sample rate converter. */
	if ((src_state = src_new (converter, channels, &error)) == NULL)
	{	printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ;
		exit (1) ;
		} ;

	src_data.end_of_input = 0 ; /* Set this later. */

	/* Start with zero to force load in while loop. */
	src_data.input_frames = 0 ;
	src_data.data_in = input ;

	if (warp [0].index > 0)
		src_data.src_ratio = 1.0 ;
	else
	{	src_data.src_ratio = warp [0].ratio ;
		warp_index ++ ;
		} ;

	src_data.data_out = output ;
	src_data.output_frames = BUFFER_LEN /channels ;

	while (1)
	{
		if (warp_index < ARRAY_LEN (warp) - 1 && input_count >= warp [warp_index].index)
		{	src_data.src_ratio = warp [warp_index].ratio ;
			warp_index ++ ;
			} ;

		/* If the input buffer is empty, refill it. */
		if (src_data.input_frames == 0)
		{	src_data.input_frames = (long) sf_readf_float (infile, input, INPUT_STEP_SIZE) ;
			input_count += src_data.input_frames ;
			src_data.data_in = input ;

			/* The last read will not be a full buffer, so snd_of_input. */
			if (src_data.input_frames < INPUT_STEP_SIZE)
				src_data.end_of_input = SF_TRUE ;
			} ;

		/* Process current block. */
		if ((error = src_process (src_state, &src_data)))
		{	printf ("\nError : %s\n", src_strerror (error)) ;
			exit (1) ;
			} ;

		/* Terminate if done. */
		if (src_data.end_of_input && src_data.output_frames_gen == 0)
			break ;

		/* Write output. */
		sf_writef_float (outfile, output, src_data.output_frames_gen) ;
		output_count += src_data.output_frames_gen ;

		src_data.data_in += src_data.input_frames_used * channels ;
		src_data.input_frames -= src_data.input_frames_used ;
		} ;

	src_delete (src_state) ;

	return output_count ;
} /* timewarp_convert */

/*------------------------------------------------------------------------------
*/

static void
usage_exit (const char *progname)
{	const char	*cptr ;

	if ((cptr = strrchr (progname, '/')) != NULL)
		progname = cptr + 1 ;

	if ((cptr = strrchr (progname, '\\')) != NULL)
		progname = cptr + 1 ;

	printf ("\n"
		"  A program demonstrating the time warping capabilities of libsamplerate."
		"  It uses libsndfile for file I/O and Secret Rabbit Code (aka libsamplerate)"
		"  for performing the warping.\n"
		"  It works on any file format supported by libsndfile with any \n"
		"  number of channels (limited only by host memory).\n"
		"\n"
		"  The warping is dependant on a table hard code into the source code.\n"
		"\n"
		"  libsamplerate version : %s\n"
		"\n"
		"  Usage : \n"
		"       %s <input file> <output file>\n"
		"\n", src_get_version (), progname) ;

	puts ("") ;

	exit (1) ;
} /* usage_exit */

/*==============================================================================
*/

#else /* (HAVE_SNFILE == 0) */

/* Alternative main function when libsndfile is not available. */

int
main (void)
{	puts (
		"\n"
		"****************************************************************\n"
		"  This example program was compiled without libsndfile \n"
		"  (https://github.com/libsndfile/libsndfile/).\n"
		"  It is therefore completely broken and non-functional.\n"
		"****************************************************************\n"
		"\n"
		) ;

	return 0 ;
} /* main */

#endif