Mercurial > audlegacy-plugins
comparison src/madplug/decoder.c @ 2341:59addab003d7
- reworked replaygain to use individual pre-gain for the files with RG info and the rest.
- default pre-gain have been changed to +6dB for with RG, +0dB for the rest.
- new clipping prevention feature using track peak information has been implemented.
- reworked preferences dialog. widgets have been categorized by function and all changes will take effect immediately. and also, cancel button can reverts all changes have been done in the current session.
- some keys in preferences have been changed.
| author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
|---|---|
| date | Thu, 31 Jan 2008 15:22:15 +0900 |
| parents | 47d7a45b26a0 |
| children | f40f4ae3d5eb |
comparison
equal
deleted
inserted
replaced
| 2340:47d7a45b26a0 | 2341:59addab003d7 |
|---|---|
| 17 * You should have received a copy of the GNU General Public License | 17 * You should have received a copy of the GNU General Public License |
| 18 * along with this program; if not, write to the Free Software | 18 * along with this program; if not, write to the Free Software |
| 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 */ | 20 */ |
| 21 | 21 |
| 22 /* #define AUD_DEBUG 1 */ | |
| 23 | |
| 22 #include <math.h> | 24 #include <math.h> |
| 23 #include <assert.h> | 25 #include <assert.h> |
| 24 #include <pthread.h> | 26 #include <pthread.h> |
| 25 #include <signal.h> | 27 #include <signal.h> |
| 26 | 28 |
| 40 * Scale PCM data | 42 * Scale PCM data |
| 41 */ | 43 */ |
| 42 static inline signed int | 44 static inline signed int |
| 43 scale(mad_fixed_t sample, struct mad_info_t *file_info) | 45 scale(mad_fixed_t sample, struct mad_info_t *file_info) |
| 44 { | 46 { |
| 45 /* replayGain by SamKR */ | |
| 46 gdouble scale = -1; | 47 gdouble scale = -1; |
| 47 if (audmad_config.replaygain.enable) { | 48 static int i = 0; |
| 49 | |
| 50 if (audmad_config->replaygain.enable) { | |
| 48 if (file_info->has_replaygain) { | 51 if (file_info->has_replaygain) { |
| 49 scale = file_info->replaygain_track_scale; | 52 // apply track gain if it is available and track mode is specified |
| 50 if (file_info->replaygain_album_scale != -1 | 53 if(file_info->replaygain_track_scale != -1) { |
| 51 && (scale == -1 || !audmad_config.replaygain.track_mode)) | 54 scale = file_info->replaygain_track_scale; |
| 52 { | 55 } |
| 56 // apply album gain if available | |
| 57 if(!audmad_config->replaygain.track_mode && | |
| 58 file_info->replaygain_album_scale != -1) { | |
| 53 scale = file_info->replaygain_album_scale; | 59 scale = file_info->replaygain_album_scale; |
| 54 } | 60 } |
| 55 } | 61 |
| 56 if (scale == -1) | 62 // apply preamp1 |
| 57 scale = audmad_config.replaygain.default_scale; | 63 scale *= audmad_config->replaygain.preamp1_scale; |
| 58 } | 64 |
| 59 if (scale == -1) | 65 if (audmad_config->replaygain.anti_clip) { |
| 66 if(i%100000 == 0) | |
| 67 AUDDBG("track_peak = %f\n", file_info->replaygain_track_peak); | |
| 68 if(scale * file_info->replaygain_track_peak >= 1.0) | |
| 69 scale = 1.0 / file_info->replaygain_track_peak; | |
| 70 } | |
| 71 } | |
| 72 else { | |
| 73 // apply preamp2 for files without RG info | |
| 74 scale = audmad_config->replaygain.preamp2_scale; | |
| 75 } | |
| 76 } | |
| 77 else { | |
| 60 scale = 1.0; | 78 scale = 1.0; |
| 61 if (audmad_config.pregain_scale != 1) | 79 } |
| 62 scale = scale * audmad_config.pregain_scale; | 80 |
| 81 // apply global gain | |
| 82 if (audmad_config->replaygain.preamp0_scale != 1) | |
| 83 scale = scale * audmad_config->replaygain.preamp0_scale; | |
| 84 | |
| 85 if(i%100000 == 0) { | |
| 86 AUDDBG("scale = %f\n", scale); | |
| 87 } | |
| 63 | 88 |
| 64 /* hard-limit (clipping-prevention) */ | 89 /* hard-limit (clipping-prevention) */ |
| 65 if (audmad_config.hard_limit) { | 90 if (audmad_config->replaygain.hard_limit) { |
| 91 | |
| 92 if(i%100000 == 0) { | |
| 93 AUDDBG("hard_limit\n"); | |
| 94 } | |
| 95 | |
| 66 /* convert to double before computation, to avoid mad_fixed_t wrapping */ | 96 /* convert to double before computation, to avoid mad_fixed_t wrapping */ |
| 67 double x = mad_f_todouble(sample) * scale; | 97 double x = mad_f_todouble(sample) * scale; |
| 68 static const double k = 0.5; // -6dBFS | 98 static const double k = 0.5; // -6dBFS |
| 69 if (x > k) { | 99 if (x > k) { |
| 70 x = tanh((x - k) / (1 - k)) * (1 - k) + k; | 100 x = tanh((x - k) / (1 - k)) * (1 - k) + k; |
| 71 } | 101 } |
| 72 else if (x < -k) { | 102 else if (x < -k) { |
| 73 x = tanh((x + k) / (1 - k)) * (1 - k) - k; | 103 x = tanh((x + k) / (1 - k)) * (1 - k) - k; |
| 74 } | 104 } |
| 75 sample = x * (MAD_F_ONE); | 105 sample = x * (MAD_F_ONE); |
| 106 | |
| 107 if(i%100000 == 0) { | |
| 108 AUDDBG("x = %f sample = %d\n", x, sample); | |
| 109 } | |
| 110 | |
| 76 } | 111 } |
| 77 else | 112 else |
| 78 sample *= scale; | 113 sample *= scale; |
| 114 | |
| 115 i++; | |
| 79 | 116 |
| 80 int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16; | 117 int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16; |
| 81 | 118 |
| 82 /* round */ | 119 /* round */ |
| 83 /* add half of the bits_to_loose range to round */ | 120 /* add half of the bits_to_loose range to round */ |
| 86 #ifdef DEBUG_DITHER | 123 #ifdef DEBUG_DITHER |
| 87 mad_fixed_t no_dither = sample; | 124 mad_fixed_t no_dither = sample; |
| 88 #endif | 125 #endif |
| 89 | 126 |
| 90 /* dither one bit of actual output */ | 127 /* dither one bit of actual output */ |
| 91 if (audmad_config.dither) { | 128 if (audmad_config->dither) { |
| 92 int dither = triangular_dither_noise(n_bits_to_loose + 1); | 129 int dither = triangular_dither_noise(n_bits_to_loose + 1); |
| 93 sample += dither; | 130 sample += dither; |
| 94 } | 131 } |
| 95 | 132 |
| 96 /* clip */ | 133 /* clip */ |
| 164 | 201 |
| 165 /** | 202 /** |
| 166 * Decode all headers in the file and fill in stats | 203 * Decode all headers in the file and fill in stats |
| 167 * @return FALSE if scan failed. | 204 * @return FALSE if scan failed. |
| 168 */ | 205 */ |
| 169 gboolean scan_file(struct mad_info_t * info, gboolean fast) | 206 gboolean |
| 207 scan_file(struct mad_info_t * info, gboolean fast) | |
| 170 { | 208 { |
| 171 struct mad_stream stream; | 209 struct mad_stream stream; |
| 172 struct mad_header header; | 210 struct mad_header header; |
| 173 int remainder = 0; | 211 int remainder = 0; |
| 174 int data_used = 0; | 212 int data_used = 0; |
| 275 info->freq = header.samplerate; | 313 info->freq = header.samplerate; |
| 276 info->channels = MAD_NCHANNELS(&header); | 314 info->channels = MAD_NCHANNELS(&header); |
| 277 info->mpeg_layer = header.layer; | 315 info->mpeg_layer = header.layer; |
| 278 info->mode = header.mode; | 316 info->mode = header.mode; |
| 279 | 317 |
| 280 if (audmad_config.use_xing) { | 318 if (audmad_config->use_xing) { |
| 281 frame.header = header; | 319 frame.header = header; |
| 282 if (mad_frame_decode(&frame, &stream) == -1) { | 320 if (mad_frame_decode(&frame, &stream) == -1) { |
| 283 AUDDBG("xing frame decode failed\n"); | 321 AUDDBG("xing frame decode failed\n"); |
| 284 goto no_xing; | 322 goto no_xing; |
| 285 } | 323 } |
| 399 | 437 |
| 400 return (info->frames != 0 || info->remote == TRUE); | 438 return (info->frames != 0 || info->remote == TRUE); |
| 401 } | 439 } |
| 402 | 440 |
| 403 /* sanity check for audio open parameters */ | 441 /* sanity check for audio open parameters */ |
| 404 static gboolean check_audio_param(struct mad_info_t *info) | 442 static gboolean |
| 443 check_audio_param(struct mad_info_t *info) | |
| 405 { | 444 { |
| 406 if(info->fmt < FMT_U8 || info->fmt > FMT_S16_NE) | 445 if(info->fmt < FMT_U8 || info->fmt > FMT_S16_NE) |
| 407 return FALSE; | 446 return FALSE; |
| 408 if(info->freq < 0) // not sure about maximum frequency. --yaz | 447 if(info->freq < 0) // not sure about maximum frequency. --yaz |
| 409 return FALSE; | 448 return FALSE; |
| 411 return FALSE; | 450 return FALSE; |
| 412 | 451 |
| 413 return TRUE; | 452 return TRUE; |
| 414 } | 453 } |
| 415 | 454 |
| 416 gpointer decode_loop(gpointer arg) | 455 gpointer |
| 456 decode_loop(gpointer arg) | |
| 417 { | 457 { |
| 418 unsigned char buffer[BUFFER_SIZE]; | 458 unsigned char buffer[BUFFER_SIZE]; |
| 419 int len; | 459 int len; |
| 420 gboolean seek_skip = FALSE; | 460 gboolean seek_skip = FALSE; |
| 421 int remainder = 0; | 461 int remainder = 0; |
| 459 } | 499 } |
| 460 | 500 |
| 461 /* set mainwin title */ | 501 /* set mainwin title */ |
| 462 if (info->title) | 502 if (info->title) |
| 463 g_free(info->title); | 503 g_free(info->title); |
| 464 info->title = aud_tuple_formatter_make_title_string(info->tuple, audmad_config.title_override == TRUE ? | 504 info->title = aud_tuple_formatter_make_title_string(info->tuple, audmad_config->title_override == TRUE ? |
| 465 audmad_config.id3_format : aud_get_gentitle_format()); | 505 audmad_config->id3_format : aud_get_gentitle_format()); |
| 466 | 506 |
| 467 tlen = (gint) mad_timer_count(info->duration, MAD_UNITS_MILLISECONDS), | 507 tlen = (gint) mad_timer_count(info->duration, MAD_UNITS_MILLISECONDS), |
| 468 info->playback->set_params(info->playback, info->title, | 508 info->playback->set_params(info->playback, info->title, |
| 469 (tlen == 0 || info->size <= 0) ? -1 : tlen, | 509 (tlen == 0 || info->size <= 0) ? -1 : tlen, |
| 470 info->bitrate, info->freq, info->channels); | 510 info->bitrate, info->freq, info->channels); |
| 579 continue; | 619 continue; |
| 580 } | 620 } |
| 581 | 621 |
| 582 info->bitrate = frame.header.bitrate; | 622 info->bitrate = frame.header.bitrate; |
| 583 | 623 |
| 584 if (!audmad_config.show_avg_vbr_bitrate && info->vbr && (iteration % 40 == 0)) { | 624 if (!audmad_config->show_avg_vbr_bitrate && info->vbr && (iteration % 40 == 0)) { |
| 585 | 625 |
| 586 #ifdef DEBUG_INTENSIVELY | 626 #ifdef DEBUG_INTENSIVELY |
| 587 AUDDBG("decode vbr tlen = %d\n", tlen); | 627 AUDDBG("decode vbr tlen = %d\n", tlen); |
| 588 #endif | 628 #endif |
| 589 info->playback->set_params(info->playback, info->title, | 629 info->playback->set_params(info->playback, info->title, |
| 616 (guint) MAD_NCHANNELS(&frame.header)); | 656 (guint) MAD_NCHANNELS(&frame.header)); |
| 617 | 657 |
| 618 info->freq = frame.header.samplerate; | 658 info->freq = frame.header.samplerate; |
| 619 info->channels = MAD_NCHANNELS(&frame.header); | 659 info->channels = MAD_NCHANNELS(&frame.header); |
| 620 | 660 |
| 621 if(audmad_config.force_reopen_audio && check_audio_param(info)) { | 661 if(audmad_config->force_reopen_audio && check_audio_param(info)) { |
| 622 gint current_time = info->playback->output->output_time(); | 662 gint current_time = info->playback->output->output_time(); |
| 623 | 663 |
| 624 AUDDBG("re-opening audio due to change in audio type\n"); | 664 AUDDBG("re-opening audio due to change in audio type\n"); |
| 625 | 665 |
| 626 info->playback->output->close_audio(); | 666 info->playback->output->close_audio(); |
