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 */