Prevent an unwanted action which increases volume to be triggered at the same time...
[Rockbox.git] / apps / metadata / mpc.c
blob0c50ddf630b6097f19cab148555a4164846b3648
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Thom Johansen
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <inttypes.h>
25 #include "system.h"
26 #include "id3.h"
27 #include "metadata_common.h"
28 #include "logf.h"
29 #include "replaygain.h"
31 bool get_musepack_metadata(int fd, struct mp3entry *id3)
33 const int32_t sfreqs_sv7[4] = { 44100, 48000, 37800, 32000 };
34 uint32_t header[8];
35 uint64_t samples = 0;
36 int i;
38 if (!skip_id3v2(fd, id3))
39 return false;
40 if (read(fd, header, 4*8) != 4*8) return false;
41 /* Musepack files are little endian, might need swapping */
42 for (i = 1; i < 8; i++)
43 header[i] = letoh32(header[i]);
44 if (!memcmp(header, "MP+", 3)) { /* Compare to sig "MP+" */
45 unsigned int streamversion;
47 header[0] = letoh32(header[0]);
48 streamversion = (header[0] >> 24) & 15;
49 if (streamversion >= 8) {
50 return false; /* SV8 or higher don't exist yet, so no support */
51 } else if (streamversion == 7) {
52 unsigned int gapless = (header[5] >> 31) & 0x0001;
53 unsigned int last_frame_samples = (header[5] >> 20) & 0x07ff;
54 int track_gain, album_gain;
55 unsigned int bufused;
57 id3->frequency = sfreqs_sv7[(header[2] >> 16) & 0x0003];
58 samples = (uint64_t)header[1]*1152; /* 1152 is mpc frame size */
59 if (gapless)
60 samples -= 1152 - last_frame_samples;
61 else
62 samples -= 481; /* Musepack subband synth filter delay */
64 /* Extract ReplayGain data from header */
65 track_gain = (int16_t)((header[3] >> 16) & 0xffff);
66 id3->track_gain = get_replaygain_int(track_gain);
67 id3->track_peak = ((uint16_t)(header[3] & 0xffff)) << 9;
69 album_gain = (int16_t)((header[4] >> 16) & 0xffff);
70 id3->album_gain = get_replaygain_int(album_gain);
71 id3->album_peak = ((uint16_t)(header[4] & 0xffff)) << 9;
73 /* Write replaygain values to strings for use in id3 screen. We use
74 the XING header as buffer space since Musepack files shouldn't
75 need to use it in any other way */
76 id3->track_gain_string = (char *)id3->toc;
77 bufused = snprintf(id3->track_gain_string, 45,
78 "%d.%d dB", track_gain/100, abs(track_gain)%100);
79 id3->album_gain_string = (char *)id3->toc + bufused + 1;
80 bufused = snprintf(id3->album_gain_string, 45,
81 "%d.%d dB", album_gain/100, abs(album_gain)%100);
83 } else {
84 header[0] = letoh32(header[0]);
85 unsigned int streamversion = (header[0] >> 11) & 0x03FF;
86 if (streamversion != 4 && streamversion != 5 && streamversion != 6)
87 return false;
88 id3->frequency = 44100;
89 id3->track_gain = 0;
90 id3->track_peak = 0;
91 id3->album_gain = 0;
92 id3->album_peak = 0;
94 if (streamversion >= 5)
95 samples = (uint64_t)header[1]*1152; // 32 bit
96 else
97 samples = (uint64_t)(header[1] >> 16)*1152; // 16 bit
99 samples -= 576;
100 if (streamversion < 6)
101 samples -= 1152;
104 id3->vbr = true;
105 /* Estimate bitrate, we should probably subtract the various header sizes
106 here for super-accurate results */
107 id3->length = ((int64_t) samples * 1000) / id3->frequency;
109 if (id3->length <= 0)
111 logf("mpc length invalid!");
112 return false;
115 id3->filesize = filesize(fd);
116 id3->bitrate = id3->filesize * 8 / id3->length;
117 return true;