aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/libapetag/info_mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libapetag/info_mac.c')
-rwxr-xr-xsrc/libapetag/info_mac.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/libapetag/info_mac.c b/src/libapetag/info_mac.c
new file mode 100755
index 0000000..1b8b5e2
--- /dev/null
+++ b/src/libapetag/info_mac.c
@@ -0,0 +1,151 @@
+/********************************************************************
+*
+* Copyright (c) 2002 Artur Polaczynski (Ar't) All rights reserved.
+* <artii@o2.pl> LGPL-2.1
+* $ArtId: info_mac.c,v 1.15 2003/04/13 11:24:10 art Exp $
+********************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "info_mac.h"
+#include "is_tag.h"
+
+#define MAC_FORMAT_FLAG_8_BIT 1 // 8-bit wave
+#define MAC_FORMAT_FLAG_CRC 2 // new CRC32 error detection
+#define MAC_FORMAT_FLAG_HAS_PEAK_LEVEL 4 // u-long Peak_Level after the header
+#define MAC_FORMAT_FLAG_24_BIT 8 // 24-bit wave
+#define MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS 16 // number of seek elements after the peak level
+#define MAC_FORMAT_FLAG_CREATE_WAV_HEADER 32 // wave header not stored
+
+struct macHeader {
+ char id[4]; // should equal 'MAC '
+ unsigned short ver; // version number * 1000 (3.81 = 3810)
+ unsigned short compLevel; // the compression level
+ unsigned short formatFlags; // any format flags (for future use)
+ unsigned short channels; // the number of channels (1 or 2)
+ unsigned long sampleRate; // the sample rate (typically 44100)
+ unsigned long headerBytesWAV; // the bytes after the MAC header that compose the WAV header
+ unsigned long terminatingBytesWAV; // the bytes after that raw data (for extended info)
+ unsigned long totalFrames; // the number of frames in the file
+ unsigned long finalFrameBlocks; // the number of samples in the final frame
+ unsigned long peakLevel;
+ unsigned short seekElements;
+};
+
+
+// local prototypes
+static int
+monkey_samples_per_frame(unsigned int versionid, unsigned int compressionlevel);
+static const char *
+monkey_stringify(unsigned int profile);
+
+static const char *
+monkey_stringify(unsigned int profile)
+{
+ static const char na[] = "unknown";
+ static const char *Names[] = {
+ na, "Fast", "Normal", "High", "Extra-High", "Insane"
+ };
+ unsigned int profile2 = profile/1000;
+
+ return (profile2 >= sizeof (Names) / sizeof (*Names)) ? na : Names[(profile2)];
+}
+
+
+static int
+monkey_samples_per_frame(unsigned int versionid, unsigned int compressionlevel)
+{
+ if (versionid >= 3950) {
+ return 294912; // 73728 * 4
+ } else if (versionid >= 3900) {
+ return 73728;
+ } else if ((versionid >= 3800) && (compressionlevel == COMPRESSION_LEVEL_EXTRA_HIGH)) {
+ return 73728;
+ } else {
+ return 9216;
+ }
+}
+
+/*
+ return 0; Info has all info
+ return 1; File not found
+ return 2; no MAC file
+*/
+int
+info_mac_read(const char *fn, StreamInfoMac * Info)
+{
+ unsigned int HeaderData[32];
+ FILE *tmpFile = NULL;
+ long SkipSizeID3;
+ struct macHeader * header;
+
+ // load file
+ tmpFile = fopen(fn, "rb");
+
+ if (tmpFile == NULL)
+ return 1; // file not found or read-protected
+
+ // skip id3v2
+ SkipSizeID3 = is_id3v2(tmpFile);
+ fseek(tmpFile, SkipSizeID3, SEEK_SET);
+ fread((void *) HeaderData, sizeof (int), 16, tmpFile);
+ fseek(tmpFile, 0, SEEK_END);
+ Info->FileSize = ftell(tmpFile);
+ fclose(tmpFile);
+
+ if (0 != memcmp(HeaderData, "MAC", 3))
+ return 2; // no monkeyAudio file
+
+ header= (struct macHeader *) HeaderData;
+
+ Info->Version = Info->EncoderVersion = header->ver;
+ Info->Channels = header->channels;
+ Info->SampleFreq = header->sampleRate;
+ Info->Flags = header->formatFlags;
+ Info->SamplesPerFrame = monkey_samples_per_frame(header->ver, header->compLevel);
+ Info->BitsPerSample = (header->formatFlags & MAC_FORMAT_FLAG_8_BIT)
+ ? 8 : ((header->formatFlags & MAC_FORMAT_FLAG_24_BIT) ? 24 : 16);
+
+ Info->PeakLevel = header->peakLevel;
+// Info->PeakRatio = Info->PakLevel / pow(2, Info->bitsPerSample - 1);
+ Info->Frames = header->totalFrames;
+ Info->Samples = (Info->Frames - 1) * Info->SamplesPerFrame +
+ header->finalFrameBlocks;
+
+ Info->Duration = Info->SampleFreq > 0 ?
+ ((float)Info->Samples / Info->SampleFreq)*1000 : 0;
+
+ Info->Compresion = header->compLevel;
+ Info->CompresionName = monkey_stringify(Info->Compresion);
+
+ Info->UncompresedSize = Info->Samples * Info->Channels *
+ (Info->BitsPerSample / 8);
+
+ Info->CompresionRatio =
+ (Info->UncompresedSize + header->headerBytesWAV) > 0 ?
+ Info->FileSize / (float) (Info->UncompresedSize +
+ header->headerBytesWAV) : 0. ;
+
+ Info->Bitrate = Info->Duration > 0 ? (((Info->Samples *
+ Info->Channels * Info->BitsPerSample) / (float) Info->Duration) *
+ Info->CompresionRatio) * 1000 : 0;
+
+ Info->PeakRatio=Info->ByteLength=0;
+ return 0;
+}