Mercurial > audlegacy-plugins
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 2389:46d3e970f0a5 | 2390:bd9673d8b7d5 |
|---|---|
| 34 #include "input.h" | 34 #include "input.h" |
| 35 | 35 |
| 36 #define BUFFER_SIZE 16*1024 | 36 #define BUFFER_SIZE 16*1024 |
| 37 #define N_AVERAGE_FRAMES 10 | 37 #define N_AVERAGE_FRAMES 10 |
| 38 | 38 |
| 39 extern int triangular_dither_noise(int nbits); | |
| 40 | |
| 41 /** | |
| 42 * Scale PCM data | |
| 43 */ | |
| 44 static inline signed int | |
| 45 scale(mad_fixed_t sample, struct mad_info_t *file_info) | |
| 46 { | |
| 47 gdouble scale = -1; | |
| 48 static double a_scale = -1; | |
| 49 static int iter = 0; | |
| 50 | |
| 51 if (audmad_config->replaygain.enable) { | |
| 52 if (file_info->has_replaygain) { | |
| 53 // apply track gain if it is available and track mode is specified | |
| 54 if(file_info->replaygain_track_scale != -1) { | |
| 55 scale = file_info->replaygain_track_scale; | |
| 56 } | |
| 57 // apply album gain if available | |
| 58 if(!audmad_config->replaygain.track_mode && | |
| 59 file_info->replaygain_album_scale != -1) { | |
| 60 scale = file_info->replaygain_album_scale; | |
| 61 } | |
| 62 | |
| 63 // apply preamp1 | |
| 64 scale *= audmad_config->replaygain.preamp1_scale; | |
| 65 | |
| 66 if (audmad_config->replaygain.anti_clip) { | |
| 67 #ifdef AUD_DEBUG | |
| 68 if(iter % 100000 == 0) | |
| 69 AUDDBG("track_peak = %f\n", file_info->replaygain_track_peak); | |
| 70 #endif | |
| 71 if(scale * file_info->replaygain_track_peak >= 1.0) | |
| 72 scale = 1.0 / file_info->replaygain_track_peak; | |
| 73 } | |
| 74 } | |
| 75 else { | |
| 76 // apply preamp2 for files without RG info | |
| 77 scale = audmad_config->replaygain.preamp2_scale; | |
| 78 } | |
| 79 } | |
| 80 else { | |
| 81 scale = 1.0; | |
| 82 } | |
| 83 | |
| 84 // apply global gain | |
| 85 if (audmad_config->replaygain.preamp0_scale != 1) | |
| 86 scale = scale * audmad_config->replaygain.preamp0_scale; | |
| 87 | |
| 88 // adaptive scaler clip prevention | |
| 89 if (audmad_config->replaygain.adaptive_scaler) { | |
| 90 double x; | |
| 91 double a = 0.1; | |
| 92 int interval = 10000; | |
| 93 | |
| 94 if(a_scale == -1.0) | |
| 95 a_scale = scale; | |
| 96 | |
| 97 x = mad_f_todouble(sample) * a_scale; | |
| 98 | |
| 99 // clippling avoidance | |
| 100 if(x > 1.0) { | |
| 101 a_scale = a_scale + a * (1.0 - x); | |
| 102 AUDDBG("down: x = %f a_scale = %f\n", x, a_scale); | |
| 103 } | |
| 104 // slowly go back to defined scale | |
| 105 else if(iter % interval == 0 && a_scale < scale){ | |
| 106 a_scale = a_scale + 1.0e-4; | |
| 107 AUDDBG("up: a_scale = %f\n", a_scale); | |
| 108 } | |
| 109 | |
| 110 x = mad_f_todouble(sample) * a_scale; | |
| 111 sample = x * (MAD_F_ONE); | |
| 112 } | |
| 113 else { | |
| 114 a_scale = scale; | |
| 115 sample *= scale; | |
| 116 } | |
| 117 | |
| 118 iter++; | |
| 119 | |
| 120 int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16; | |
| 121 | |
| 122 /* round */ | |
| 123 /* add half of the bits_to_loose range to round */ | |
| 124 sample += (1L << (n_bits_to_loose - 1)); | |
| 125 | |
| 126 #ifdef DEBUG_DITHER | |
| 127 mad_fixed_t no_dither = sample; | |
| 128 #endif | |
| 129 | |
| 130 /* dither one bit of actual output */ | |
| 131 if (audmad_config->dither) { | |
| 132 int dither = triangular_dither_noise(n_bits_to_loose + 1); | |
| 133 sample += dither; | |
| 134 } | |
| 135 | |
| 136 /* clip */ | |
| 137 /* make sure we are between -1 and 1 */ | |
| 138 if (sample >= MAD_F_ONE) { | |
| 139 sample = MAD_F_ONE - 1; | |
| 140 } | |
| 141 else if (sample < -MAD_F_ONE) { | |
| 142 sample = -MAD_F_ONE; | |
| 143 } | |
| 144 | |
| 145 /* quantize */ | |
| 146 /* | |
| 147 * Turn our mad_fixed_t into an integer. | |
| 148 * Shift all but 16-bits of the fractional part | |
| 149 * off the right hand side and shift an extra place | |
| 150 * to get the sign bit. | |
| 151 */ | |
| 152 sample >>= n_bits_to_loose; | |
| 153 #ifdef DEBUG_DITHER | |
| 154 static int n_zeros = 0; | |
| 155 no_dither >>= n_bits_to_loose; | |
| 156 if (no_dither - sample == 0) | |
| 157 n_zeros++; | |
| 158 else { | |
| 159 g_message("dither: %d %d", n_zeros, no_dither - sample); | |
| 160 n_zeros = 0; | |
| 161 } | |
| 162 #endif | |
| 163 return sample; | |
| 164 } | |
| 165 | |
| 166 void | 39 void |
| 167 write_output(struct mad_info_t *info, struct mad_pcm *pcm, | 40 write_output(struct mad_info_t *info, struct mad_pcm *pcm, |
| 168 struct mad_header *header) | 41 struct mad_header *header) |
| 169 { | 42 { |
| 170 unsigned int nsamples; | 43 unsigned int nsamples; |
| 171 mad_fixed_t const *left_ch, *right_ch; | 44 mad_fixed_t const *left_ch, *right_ch; |
| 172 char *output; | 45 mad_fixed_t *output; |
| 173 int olen = 0; | 46 int outlen = 0; |
| 47 int outbyte = 0; | |
| 174 int pos = 0; | 48 int pos = 0; |
| 175 | 49 |
| 176 nsamples = pcm->length; | 50 nsamples = pcm->length; |
| 177 left_ch = pcm->samples[0]; | 51 left_ch = pcm->samples[0]; |
| 178 right_ch = pcm->samples[1]; | 52 right_ch = pcm->samples[1]; |
| 179 olen = nsamples * MAD_NCHANNELS(header) * 2; | 53 outlen = nsamples * MAD_NCHANNELS(header); |
| 180 output = (char *) g_malloc(olen * sizeof(char)); | 54 outbyte = outlen * sizeof(mad_fixed_t); |
| 55 | |
| 56 output = (mad_fixed_t *) g_malloc(outbyte); | |
| 181 | 57 |
| 182 while (nsamples--) { | 58 while (nsamples--) { |
| 183 signed int sample; | 59 output[pos++] = *left_ch++; |
| 184 /* output sample(s) in 16-bit signed little-endian PCM */ | |
| 185 sample = scale(*left_ch++, info); | |
| 186 output[pos++] = (sample >> 0) & 0xff; | |
| 187 output[pos++] = (sample >> 8) & 0xff; | |
| 188 | 60 |
| 189 if (MAD_NCHANNELS(header) == 2) { | 61 if (MAD_NCHANNELS(header) == 2) { |
| 190 sample = scale(*right_ch++, info); | 62 output[pos++] = *right_ch++; |
| 191 output[pos++] = (sample >> 0) & 0xff; | 63 } |
| 192 output[pos++] = (sample >> 8) & 0xff; | 64 } |
| 193 } | 65 |
| 194 } | 66 assert(pos == outlen); |
| 195 assert(pos == olen); | |
| 196 if (!info->playback->playing) { | 67 if (!info->playback->playing) { |
| 197 g_free(output); | 68 g_free(output); |
| 198 return; | 69 return; |
| 199 } | 70 } |
| 71 | |
| 200 info->playback->pass_audio(info->playback, | 72 info->playback->pass_audio(info->playback, |
| 201 FMT_S16_LE, MAD_NCHANNELS(header), olen, output, &(info->playback->playing)); | 73 info->fmt, MAD_NCHANNELS(header), outbyte, output, |
| 74 &(info->playback->playing)); | |
| 202 g_free(output); | 75 g_free(output); |
| 203 } | 76 } |
| 204 | 77 |
| 205 /** | 78 /** |
| 206 * Decode all headers in the file and fill in stats | 79 * Decode all headers in the file and fill in stats |
| 443 | 316 |
| 444 /* sanity check for audio open parameters */ | 317 /* sanity check for audio open parameters */ |
| 445 static gboolean | 318 static gboolean |
| 446 check_audio_param(struct mad_info_t *info) | 319 check_audio_param(struct mad_info_t *info) |
| 447 { | 320 { |
| 448 if(info->fmt < FMT_U8 || info->fmt > FMT_S16_NE) | 321 if(info->fmt != FMT_FIXED32 && (info->fmt < FMT_U8 || info->fmt > FMT_S16_NE)) |
| 449 return FALSE; | 322 return FALSE; |
| 450 if(info->freq < 0) // not sure about maximum frequency. --yaz | 323 if(info->freq < 0) // not sure about maximum frequency. --yaz |
| 451 return FALSE; | 324 return FALSE; |
| 452 if(info->channels < 1 || info->channels > 2) | 325 if(info->channels < 1 || info->channels > 2) |
| 453 return FALSE; | 326 return FALSE; |
| 686 break; | 559 break; |
| 687 mad_synth_frame(&synth, &frame); | 560 mad_synth_frame(&synth, &frame); |
| 688 mad_stream_sync(&stream); | 561 mad_stream_sync(&stream); |
| 689 | 562 |
| 690 write_output(info, &synth.pcm, &frame.header); | 563 write_output(info, &synth.pcm, &frame.header); |
| 564 | |
| 691 mad_timer_add(&info->pos, frame.header.duration); | 565 mad_timer_add(&info->pos, frame.header.duration); |
| 692 } | 566 } |
| 693 } | 567 } |
| 694 while (stream.error == MAD_ERROR_BUFLEN); | 568 while (stream.error == MAD_ERROR_BUFLEN); |
| 695 | 569 |
