Mercurial > audlegacy
comparison src/audacious/output.c @ 2538:719e0898ff3c trunk
[svn] - Patch to use libsamplerate for high-quality interpolated upsampling,
similar to what foobar2000 can do. Patch by Teru KAMOGASHIRA.
author | nenolod |
---|---|
date | Sat, 17 Feb 2007 02:19:35 -0800 |
parents | ad1d7687814c |
children | ef01234ae265 |
comparison
equal
deleted
inserted
replaced
2537:7aac1b5ef85d | 2538:719e0898ff3c |
---|---|
30 #include "main.h" | 30 #include "main.h" |
31 #include "input.h" | 31 #include "input.h" |
32 #include "playback.h" | 32 #include "playback.h" |
33 | 33 |
34 #include "playlist.h" | 34 #include "playlist.h" |
35 #include "libaudacious/configdb.h" | |
36 #ifdef USE_SRC | |
37 #include <samplerate.h> | |
38 #endif | |
35 | 39 |
36 OutputPluginData op_data = { | 40 OutputPluginData op_data = { |
37 NULL, | 41 NULL, |
38 NULL | 42 NULL |
39 }; | 43 }; |
215 OutputPlugin *op = get_current_output_plugin(); | 219 OutputPlugin *op = get_current_output_plugin(); |
216 | 220 |
217 return op->output_time(); | 221 return op->output_time(); |
218 } | 222 } |
219 | 223 |
224 #ifdef USE_SRC | |
225 static SRC_STATE *src_state; | |
226 static SRC_DATA src_data; | |
227 static int overSamplingFs = 96000; | |
228 static int converter_type = SRC_SINC_BEST_QUALITY; | |
229 static int srcError = 0; | |
230 static void freeSRC() | |
231 { | |
232 if(src_state != NULL) | |
233 src_state = src_delete(src_state); | |
234 } | |
235 #endif | |
236 | |
220 gint | 237 gint |
221 output_open_audio(AFormat fmt, gint rate, gint nch) | 238 output_open_audio(AFormat fmt, gint rate, gint nch) |
222 { | 239 { |
223 gint ret; | 240 gint ret; |
224 OutputPlugin *op; | 241 OutputPlugin *op; |
242 | |
243 #ifdef USE_SRC | |
244 ConfigDb *db; | |
245 gboolean src_enabled; | |
246 gint src_rate, src_type; | |
247 db = bmp_cfg_db_open(); | |
248 | |
249 if (bmp_cfg_db_get_bool(db, NULL, "enable_src", &src_enabled) == FALSE) | |
250 src_enabled = FALSE; | |
251 | |
252 if (bmp_cfg_db_get_int(db, NULL, "src_rate", &src_rate) == FALSE) | |
253 overSamplingFs = 48000; | |
254 else | |
255 overSamplingFs = src_rate; | |
256 | |
257 if (bmp_cfg_db_get_int(db, NULL, "src_type", &src_type) == FALSE) | |
258 converter_type = SRC_SINC_BEST_QUALITY; | |
259 else | |
260 converter_type = src_type; | |
261 | |
262 bmp_cfg_db_close(db); | |
263 | |
264 freeSRC(); | |
265 | |
266 if(src_enabled&& | |
267 (fmt == FMT_S16_NE||(fmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN)|| | |
268 (fmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN))) | |
269 { | |
270 src_state = src_new(converter_type, nch, &srcError); | |
271 if (src_state != NULL) | |
272 { | |
273 src_data.src_ratio = (float)overSamplingFs/(float)rate; | |
274 rate = overSamplingFs; | |
275 } | |
276 else | |
277 fprintf(stderr, "src_new(): %s\n\n", src_strerror(srcError)); | |
278 } | |
279 #endif | |
225 | 280 |
226 op = get_current_output_plugin(); | 281 op = get_current_output_plugin(); |
227 | 282 |
228 if (op == NULL) | 283 if (op == NULL) |
229 return -1; | 284 return -1; |
266 void | 321 void |
267 output_close_audio(void) | 322 output_close_audio(void) |
268 { | 323 { |
269 OutputPlugin *op = get_current_output_plugin(); | 324 OutputPlugin *op = get_current_output_plugin(); |
270 | 325 |
326 #ifdef USE_SRC | |
327 freeSRC(); | |
328 #endif | |
329 | |
271 /* Do not close if there are still songs to play and the user has | 330 /* Do not close if there are still songs to play and the user has |
272 * not requested a stop. --nenolod | 331 * not requested a stop. --nenolod |
273 */ | 332 */ |
274 if (ip_data.stop == FALSE && | 333 if (ip_data.stop == FALSE && |
275 (playlist_get_position_nolock(playlist_get_active()) < playlist_get_length_nolock(playlist_get_active()) - 1)) | 334 (playlist_get_position_nolock(playlist_get_active()) < playlist_get_length_nolock(playlist_get_active()) - 1)) |
326 if (op == NULL) | 385 if (op == NULL) |
327 return 0; | 386 return 0; |
328 | 387 |
329 return op->buffer_playing(); | 388 return op->buffer_playing(); |
330 } | 389 } |
390 | |
391 #ifdef USE_SRC | |
392 static float *srcIn = NULL, *srcOut = NULL; | |
393 static short int *wOut = NULL; | |
394 static gboolean isSrcAlloc = FALSE; | |
395 #endif | |
331 | 396 |
332 /* called by input plugin when data is ready */ | 397 /* called by input plugin when data is ready */ |
333 void | 398 void |
334 produce_audio(gint time, /* position */ | 399 produce_audio(gint time, /* position */ |
335 AFormat fmt, /* output format */ | 400 AFormat fmt, /* output format */ |
344 guint myorder = G_BYTE_ORDER == G_LITTLE_ENDIAN ? FMT_S16_LE : FMT_S16_BE; | 409 guint myorder = G_BYTE_ORDER == G_LITTLE_ENDIAN ? FMT_S16_LE : FMT_S16_BE; |
345 int caneq = (fmt == FMT_S16_NE || fmt == myorder); | 410 int caneq = (fmt == FMT_S16_NE || fmt == myorder); |
346 OutputPlugin *op = get_current_output_plugin(); | 411 OutputPlugin *op = get_current_output_plugin(); |
347 int writeoffs; | 412 int writeoffs; |
348 | 413 |
414 #ifdef USE_SRC | |
415 if(isSrcAlloc == TRUE) | |
416 { | |
417 free(srcIn); | |
418 free(srcOut); | |
419 free(wOut); | |
420 isSrcAlloc = FALSE; | |
421 } | |
422 | |
423 if(src_state != NULL&&length > 0) | |
424 { | |
425 int lrLength = length/2; | |
426 int overLrLength = (int)floor(lrLength*(src_data.src_ratio+1)); | |
427 srcIn = (float*)malloc(sizeof(float)*lrLength); | |
428 srcOut = (float*)malloc(sizeof(float)*overLrLength); | |
429 wOut = (short int*)malloc(sizeof(short int)*overLrLength); | |
430 src_short_to_float_array((short int*)ptr, srcIn, lrLength); | |
431 isSrcAlloc = TRUE; | |
432 src_data.data_in = srcIn; | |
433 src_data.data_out = srcOut; | |
434 src_data.end_of_input = 0; | |
435 src_data.input_frames = lrLength/2; | |
436 src_data.output_frames = overLrLength/2; | |
437 if (srcError = src_process(src_state, &src_data)) | |
438 { | |
439 fprintf(stderr, "src_process(): %s\n", src_strerror(srcError)); | |
440 } | |
441 else | |
442 { | |
443 src_float_to_short_array(srcOut, wOut, src_data.output_frames_gen*2); | |
444 ptr = wOut; | |
445 length = src_data.output_frames_gen*4; | |
446 } | |
447 } | |
448 #endif | |
449 | |
349 if (!caneq && cfg.equalizer_active) { /* wrong byte order */ | 450 if (!caneq && cfg.equalizer_active) { /* wrong byte order */ |
350 byteswap(length, ptr); /* so convert */ | 451 byteswap(length, ptr); /* so convert */ |
351 ++swapped; | 452 ++swapped; |
352 ++caneq; | 453 ++caneq; |
353 } /* can eq now, mark swapd */ | 454 } /* can eq now, mark swapd */ |