Mercurial > audlegacy-plugins
diff src/madplug/decoder.c @ 2390:bd9673d8b7d5
converted to new sound engine scheme.
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Fri, 15 Feb 2008 19:10:19 +0900 |
parents | fd8271f07747 |
children | 4fb714073ae4 |
line wrap: on
line diff
--- a/src/madplug/decoder.c Thu Feb 14 15:44:10 2008 -0600 +++ b/src/madplug/decoder.c Fri Feb 15 19:10:19 2008 +0900 @@ -36,169 +36,42 @@ #define BUFFER_SIZE 16*1024 #define N_AVERAGE_FRAMES 10 -extern int triangular_dither_noise(int nbits); - -/** - * Scale PCM data - */ -static inline signed int -scale(mad_fixed_t sample, struct mad_info_t *file_info) -{ - gdouble scale = -1; - static double a_scale = -1; - static int iter = 0; - - if (audmad_config->replaygain.enable) { - if (file_info->has_replaygain) { - // apply track gain if it is available and track mode is specified - if(file_info->replaygain_track_scale != -1) { - scale = file_info->replaygain_track_scale; - } - // apply album gain if available - if(!audmad_config->replaygain.track_mode && - file_info->replaygain_album_scale != -1) { - scale = file_info->replaygain_album_scale; - } - - // apply preamp1 - scale *= audmad_config->replaygain.preamp1_scale; - - if (audmad_config->replaygain.anti_clip) { -#ifdef AUD_DEBUG - if(iter % 100000 == 0) - AUDDBG("track_peak = %f\n", file_info->replaygain_track_peak); -#endif - if(scale * file_info->replaygain_track_peak >= 1.0) - scale = 1.0 / file_info->replaygain_track_peak; - } - } - else { - // apply preamp2 for files without RG info - scale = audmad_config->replaygain.preamp2_scale; - } - } - else { - scale = 1.0; - } - - // apply global gain - if (audmad_config->replaygain.preamp0_scale != 1) - scale = scale * audmad_config->replaygain.preamp0_scale; - - // adaptive scaler clip prevention - if (audmad_config->replaygain.adaptive_scaler) { - double x; - double a = 0.1; - int interval = 10000; - - if(a_scale == -1.0) - a_scale = scale; - - x = mad_f_todouble(sample) * a_scale; - - // clippling avoidance - if(x > 1.0) { - a_scale = a_scale + a * (1.0 - x); - AUDDBG("down: x = %f a_scale = %f\n", x, a_scale); - } - // slowly go back to defined scale - else if(iter % interval == 0 && a_scale < scale){ - a_scale = a_scale + 1.0e-4; - AUDDBG("up: a_scale = %f\n", a_scale); - } - - x = mad_f_todouble(sample) * a_scale; - sample = x * (MAD_F_ONE); - } - else { - a_scale = scale; - sample *= scale; - } - - iter++; - - int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16; - - /* round */ - /* add half of the bits_to_loose range to round */ - sample += (1L << (n_bits_to_loose - 1)); - -#ifdef DEBUG_DITHER - mad_fixed_t no_dither = sample; -#endif - - /* dither one bit of actual output */ - if (audmad_config->dither) { - int dither = triangular_dither_noise(n_bits_to_loose + 1); - sample += dither; - } - - /* clip */ - /* make sure we are between -1 and 1 */ - if (sample >= MAD_F_ONE) { - sample = MAD_F_ONE - 1; - } - else if (sample < -MAD_F_ONE) { - sample = -MAD_F_ONE; - } - - /* quantize */ - /* - * Turn our mad_fixed_t into an integer. - * Shift all but 16-bits of the fractional part - * off the right hand side and shift an extra place - * to get the sign bit. - */ - sample >>= n_bits_to_loose; -#ifdef DEBUG_DITHER - static int n_zeros = 0; - no_dither >>= n_bits_to_loose; - if (no_dither - sample == 0) - n_zeros++; - else { - g_message("dither: %d %d", n_zeros, no_dither - sample); - n_zeros = 0; - } -#endif - return sample; -} - void write_output(struct mad_info_t *info, struct mad_pcm *pcm, struct mad_header *header) { unsigned int nsamples; mad_fixed_t const *left_ch, *right_ch; - char *output; - int olen = 0; + mad_fixed_t *output; + int outlen = 0; + int outbyte = 0; int pos = 0; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; - olen = nsamples * MAD_NCHANNELS(header) * 2; - output = (char *) g_malloc(olen * sizeof(char)); + outlen = nsamples * MAD_NCHANNELS(header); + outbyte = outlen * sizeof(mad_fixed_t); + + output = (mad_fixed_t *) g_malloc(outbyte); while (nsamples--) { - signed int sample; - /* output sample(s) in 16-bit signed little-endian PCM */ - sample = scale(*left_ch++, info); - output[pos++] = (sample >> 0) & 0xff; - output[pos++] = (sample >> 8) & 0xff; + output[pos++] = *left_ch++; if (MAD_NCHANNELS(header) == 2) { - sample = scale(*right_ch++, info); - output[pos++] = (sample >> 0) & 0xff; - output[pos++] = (sample >> 8) & 0xff; + output[pos++] = *right_ch++; } } - assert(pos == olen); + + assert(pos == outlen); if (!info->playback->playing) { g_free(output); return; } + info->playback->pass_audio(info->playback, - FMT_S16_LE, MAD_NCHANNELS(header), olen, output, &(info->playback->playing)); + info->fmt, MAD_NCHANNELS(header), outbyte, output, + &(info->playback->playing)); g_free(output); } @@ -445,7 +318,7 @@ static gboolean check_audio_param(struct mad_info_t *info) { - if(info->fmt < FMT_U8 || info->fmt > FMT_S16_NE) + if(info->fmt != FMT_FIXED32 && (info->fmt < FMT_U8 || info->fmt > FMT_S16_NE)) return FALSE; if(info->freq < 0) // not sure about maximum frequency. --yaz return FALSE; @@ -688,6 +561,7 @@ mad_stream_sync(&stream); write_output(info, &synth.pcm, &frame.header); + mad_timer_add(&info->pos, frame.header.duration); } }