summaryrefslogtreecommitdiff
path: root/apps/metadata/mpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/metadata/mpc.c')
-rw-r--r--apps/metadata/mpc.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/apps/metadata/mpc.c b/apps/metadata/mpc.c
new file mode 100644
index 0000000000..60e8202ff5
--- /dev/null
+++ b/apps/metadata/mpc.c
@@ -0,0 +1,118 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Dave Chapman
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <ctype.h>
23#include <inttypes.h>
24
25#include "system.h"
26#include "id3.h"
27#include "metadata_common.h"
28#include "logf.h"
29#include "replaygain.h"
30
31bool get_musepack_metadata(int fd, struct mp3entry *id3)
32{
33 const int32_t sfreqs_sv7[4] = { 44100, 48000, 37800, 32000 };
34 uint32_t header[8];
35 uint64_t samples = 0;
36 int i;
37
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;
46
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;
56
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 */
63
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;
68
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;
72
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);
82 }
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;
93
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
98
99 samples -= 576;
100 if (streamversion < 6)
101 samples -= 1152;
102 }
103
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;
108
109 if (id3->length <= 0)
110 {
111 logf("mpc length invalid!");
112 return false;
113 }
114
115 id3->filesize = filesize(fd);
116 id3->bitrate = id3->filesize * 8 / id3->length;
117 return true;
118}