-
Notifications
You must be signed in to change notification settings - Fork 0
/
ConvertWav2Mp3.c
317 lines (235 loc) · 8.36 KB
/
ConvertWav2Mp3.c
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#include <dirent.h>
#include <lame/lame.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define WAV_BUFFER_SIZE 8192
#define MP3_BUFFER_SIZE 8192
/* Structure for thread parameters */
typedef struct MP3ConvertorThreadParams{
char *wav_file_path;
char *mp3_file_path;
int *number_of_threads;
pthread_mutex_t *mutex;
} MP3ConvertorThreadParams;
/* Routine to encode wav to mp3 */
static void * Encode2Mp3ThreadRoutine( void *params ){
/* Cast the given parameter to MP3ConvertorThreadParams */
struct MP3ConvertorThreadParams *MP3ConvertorThreadParamsPtr = ((MP3ConvertorThreadParams *) (params));
/* Print start information */
if( pthread_mutex_lock(MP3ConvertorThreadParamsPtr->mutex) == 0 ) {
// printf( "\nEncoding: %ld \n", pthread_self() );
printf( " %s from %s\n", MP3ConvertorThreadParamsPtr->mp3_file_path, MP3ConvertorThreadParamsPtr->wav_file_path );
pthread_mutex_unlock( MP3ConvertorThreadParamsPtr->mutex );
}
/* Encode */
if( Encode_Wav2Mp3(MP3ConvertorThreadParamsPtr->wav_file_path, MP3ConvertorThreadParamsPtr->mp3_file_path, MP3ConvertorThreadParamsPtr->mutex) != EXIT_SUCCESS ){
/* Close thread with failure */
pthread_exit( (void*) EXIT_FAILURE );
}
/* Lock mutex, decrement number of running threads, unlock */
if( pthread_mutex_lock(MP3ConvertorThreadParamsPtr->mutex) == 0 ){
if( *MP3ConvertorThreadParamsPtr->number_of_threads > 0 ){
*MP3ConvertorThreadParamsPtr->number_of_threads -= 1;
}
pthread_mutex_unlock( MP3ConvertorThreadParamsPtr->mutex );
}
/* Print finish information */
if( pthread_mutex_lock(MP3ConvertorThreadParamsPtr->mutex) == 0 ){
// printf( "\nEND: %ld ", pthread_self() );
printf( "%s encoded succesfully\n", MP3ConvertorThreadParamsPtr->wav_file_path );
pthread_mutex_unlock( MP3ConvertorThreadParamsPtr->mutex );
}
/* Free Memory*/
free( MP3ConvertorThreadParamsPtr->wav_file_path );
free( MP3ConvertorThreadParamsPtr->mp3_file_path );
free( MP3ConvertorThreadParamsPtr );
/* Close thread with success */
pthread_exit( (void*)EXIT_SUCCESS );
}
/* Encode a wave file to a mp3 file */
int Encode_Wav2Mp3( char *wav_file_path, char *mp3_file_path, pthread_mutex_t *mutex ){
/* Encoder flags */
lame_global_flags *lameflags;
/* Source and destination file */
FILE *wavfile, *mp3file;
/* Holder for return values */
size_t bytesread, byteswrote;
/* Stream buffers */
short *wav_buffer;
unsigned char *mp3_buffer;
/* Channel buffers */
short *buffer_left;
short *buffer_right;
int i, j;
/* initialize the lame encoder */
lameflags = lame_init( );
/* default options are 2, 44.1khz, 128kbps CBR, jstereo, quality 5 */
lame_set_num_channels( lameflags, 2 );
lame_set_in_samplerate( lameflags, 44100 );
lame_set_brate( lameflags, 128 );
lame_set_mode( lameflags, 1 ); /* 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono */
lame_set_quality( lameflags, 0 ); /* 0=best 5=good 9=worst */
/* set internal parameters */
if( lame_init_params(lameflags) < 0 ) {
if( pthread_mutex_lock(mutex) == 0 ){
pthread_mutex_unlock( mutex );
}
}
/* Open files */
if( (wavfile = fopen(wav_file_path, "rb")) == NULL ){
if( pthread_mutex_lock(mutex) == 0 ){
fprintf( stderr, "ERROR: cannot find path %s pls check again\n", wav_file_path );
pthread_mutex_unlock( mutex );
}
/* Return with failure */
return( EXIT_FAILURE );
}
if( (mp3file = fopen(mp3_file_path, "wb")) == NULL ){
if( pthread_mutex_lock(mutex) == 0 ){
fprintf( stderr, "ERROR: cannot find path %s pls check again\n", mp3_file_path );
pthread_mutex_unlock( mutex );
}
/* return with failure */
return( EXIT_FAILURE );
}
/* Initialize wave & mp3 buffers */
wav_buffer = malloc( sizeof(short) * 2 * WAV_BUFFER_SIZE );
mp3_buffer = malloc( sizeof(unsigned char) * MP3_BUFFER_SIZE );
/* Read wave file, encode, write mp3 file */
do{
/* Read wave file */
bytesread = fread( wav_buffer, 2 * sizeof(short), WAV_BUFFER_SIZE, wavfile);
/* Bytes from wave file available */
if( bytesread != 0 ){
/* Initialize buffers for left and right channel */
buffer_left = malloc( sizeof(short)*bytesread );
buffer_right = malloc( sizeof(short)*bytesread );
/* Copy / split streambuffer to channelbuffers */
j=0;
for( i = 0; i < bytesread; i++ ){
buffer_left[i] = wav_buffer[j++];
buffer_right[i] = wav_buffer[j++];
}
/* Encode channelbuffers to mp3 buffer */
byteswrote = lame_encode_buffer( lameflags, buffer_left, buffer_right, bytesread, mp3_buffer, MP3_BUFFER_SIZE );
/* Free channelbuffers */
free( buffer_left );
free( buffer_right );
}else{ /* No (more) byte from wave file available */
byteswrote = lame_encode_flush( lameflags, mp3_buffer, MP3_BUFFER_SIZE );
}
/* Check for encoding errors */
if( byteswrote < 0 ){
if( pthread_mutex_lock(mutex) == 0 ){
fprintf( stderr, "ERROR during encoding, bytes wrote: %ld\n", byteswrote );
pthread_mutex_unlock( mutex );
}
/* Return with failure */
return( EXIT_FAILURE );
}
/* Write mp3 buffer to mp3 file */
fwrite( mp3_buffer, byteswrote, 1, mp3file );
} while( bytesread != 0 );
/* Close lame flags */
lame_close( lameflags );
/* Free memory */
free( wav_buffer );
free( mp3_buffer );
/* Close files */
fclose( wavfile );
fclose( mp3file );
/* Return with success */
return( EXIT_SUCCESS );
}
int main( int argc, char **argv ){
// cpu_set_t cpuset;
// CPU_ZERO(&cpuset);
/* Source directory */
DIR *src_directory;
/* File entry in directory */
struct dirent *entry;
/* Path/file names */
char *path, *wav_file_path, *mp3_file_path, *extension;
/* Parameters for encoding thread(s) */
MP3ConvertorThreadParams *parameters;
/* Temporary threadt */
pthread_t tmpThread;
/* Mutex */
pthread_mutex_t mutex;
/* Number of cpu cores, running threads */
long number_of_processors = 0;
int number_of_threads = 0;
/* Get commandline arguments */
if( argc != 2 ){
fprintf( stderr, "Usage: %s <path_to_folder_with_wav_files>\n", argv[0] );
/* Exit with failure */
return( EXIT_FAILURE );
}
path = malloc( strlen(argv[1]) + 2 );
strcpy( path, argv[1] );
number_of_processors = sysconf( _SC_NPROCESSORS_ONLN );
/* Set affinity mask to include all CPUs */
// int j = 0;
// for (j = 0; j < number_of_processors; j++){
// CPU_SET(j, &cpuset);
// }
/* Open src_directory containing wave files */
if( (src_directory = opendir(path)) == NULL ){
fprintf( stderr, "ERROR opening src_directory: %s\n", path );
/* Exit with failure */
return( EXIT_FAILURE );
}
/* Initialize mutex */
pthread_mutex_init( &mutex, NULL );
/* Run through files in src_directory */
while( (entry = readdir(src_directory)) != NULL ){
/* If file has the '.wav' extension */
if( strcmp(strrchr(entry->d_name, '.'), ".wav") == 0 ){
/* Build filepaths */
if( path[strlen(path)-1] != '/' ){
strcat( path, "/" );
}
wav_file_path = malloc( sizeof(char) * (strlen(path) + strlen(entry->d_name) + 1) );
strcpy( wav_file_path, path );
strcat( wav_file_path, entry->d_name );
mp3_file_path = malloc( sizeof(char) * (strlen(wav_file_path) + 1) );
strcpy( mp3_file_path, wav_file_path );
extension = strrchr( mp3_file_path, '.' );
strcpy( extension, ".mp3" );
/* build parameters structure for encoding-thread */
parameters = malloc( sizeof(struct MP3ConvertorThreadParams) );
parameters->wav_file_path = malloc( strlen(wav_file_path) + 1 );
strcpy( parameters->wav_file_path, wav_file_path );
parameters->mp3_file_path = malloc( strlen(mp3_file_path) + 1 );
strcpy( parameters->mp3_file_path, mp3_file_path );
parameters->number_of_threads = &number_of_threads;
parameters->mutex = &mutex;
/* Encode wave file to mp3 file */
if( pthread_create(&tmpThread, NULL, Encode2Mp3ThreadRoutine, parameters) != 0 ){
pthread_cancel( tmpThread );
}else{
/* lock mutex, increment number of running threads, unlock */
if( pthread_mutex_lock(&mutex) == 0 ){
number_of_threads += 1;
pthread_mutex_unlock( &mutex );
}
/* Disassociate encoder thread from main */
pthread_detach(tmpThread);
}
}
}
/* Wait for running theads to finish */
while( number_of_threads > 0 ){
sleep( 1 );
}
printf( "\nAll threads finished, closing...\n" );
/* free memory */
free( path );
/* destroy mutex */
pthread_mutex_destroy( &mutex );
/* exit with success */
return( EXIT_SUCCESS );
}