A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
2

Configure Feed

Select the types of activity you want to include in your feed.

rockboxd / lib / rbcodec / metadata / aiff.c
4.7 kB 156 lines
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * 9 * Copyright (C) 2005 Dave Chapman 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 2 14 * of the License, or (at your option) any later version. 15 * 16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 17 * KIND, either express or implied. 18 * 19 ****************************************************************************/ 20#include <stdio.h> 21#include <string.h> 22#include <stdlib.h> 23#include <ctype.h> 24#include <inttypes.h> 25#include "platform.h" 26 27#include "metadata.h" 28#include "metadata_common.h" 29#include "metadata_parsers.h" 30 31#include "debug.h" 32 33/* compressionType: AIFC QuickTime IMA ADPCM */ 34#define AIFC_FORMAT_QT_IMA_ADPCM "ima4" 35 36static void read_id3_tags(int fd, struct mp3entry* id3) 37{ 38 setid3v2title(fd, id3); 39} 40 41bool get_aiff_metadata(int fd, struct mp3entry* id3) 42{ 43 unsigned char buf[512]; 44 unsigned long numChannels = 0; 45 unsigned long numSampleFrames = 0; 46 unsigned long numbytes = 0; 47 unsigned long offset = 0; 48 bool is_aifc = false; 49 char *p=id3->id3v2buf; 50 51 52 if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, &buf[0], 12) < 12) || 53 (memcmp(&buf[0], "FORM", 4) != 0) || (memcmp(&buf[8], "AIF", 3) != 0) || 54 (!(is_aifc = (buf[11] == 'C')) && buf[11] != 'F')) 55 { 56 return false; 57 } 58 59 60 while (read(fd, &buf[0], 8) == 8) 61 { 62 size_t size = get_long_be(&buf[4]); /* chunkSize */ 63 64 if (memcmp(&buf[0], "SSND", 4) == 0) 65 { 66 numbytes = size - 8; 67 68 /* check for ID3 tag */ 69 offset=lseek(fd, 0, SEEK_CUR); 70 lseek(fd, size, SEEK_CUR); 71 if ((read(fd, &buf[0], 8) == 8) && (memcmp(&buf[0], "ID3", 3) == 0)) 72 { 73 id3->id3v2len = get_long_be(&buf[4]); 74 read_id3_tags(fd, id3); 75 } 76 else 77 DEBUGF("ID3 tag not present immediately after sound data"); 78 lseek(fd, offset, SEEK_SET); 79 break; /* assume COMM was already read */ 80 } 81 82 /* odd chunk sizes must be padded */ 83 size += size & 1; 84 85 if (size > sizeof(buf)) 86 { 87 DEBUGF("AIFF \"%4.4s\" chunk too large (%zd > %zd)", 88 (char*) &buf[0], size, sizeof(buf)); 89 } 90 91 92 if (memcmp(&buf[0], "NAME", 4) == 0) 93 { 94 read_string(fd, p, 512, 0, size); 95 id3->title=p; 96 p+=size; 97 } 98 99 else if (memcmp(&buf[0], "AUTH", 4) == 0) 100 { 101 read_string(fd, p, 512, 0, size); 102 id3->artist=p; 103 p+=size; 104 } 105 106 else if (memcmp(&buf[0], "ANNO", 4) == 0) 107 { 108 read_string(fd, p, 512, 0, size); 109 id3->comment=p; 110 p+=size; 111 } 112 113 else if (memcmp(&buf[0], "ID3", 3) == 0) 114 { 115 read_id3_tags(fd, id3); 116 } 117 118 119 else if (memcmp(&buf[0], "COMM", 4) == 0) 120 { 121 if (size > sizeof(buf) || read(fd, &buf[0], size) != (ssize_t)size) 122 return false; 123 124 numChannels = ((buf[0]<<8)|buf[1]); 125 126 numSampleFrames = get_long_be(&buf[2]); 127 128 /* sampleRate */ 129 id3->frequency = get_long_be(&buf[10]); 130 id3->frequency >>= (16+14-buf[9]); 131 132 /* save format infos */ 133 id3->bitrate = ((buf[6]<<8)|buf[7]) * numChannels * id3->frequency; 134 id3->bitrate /= 1000; 135 136 if (!is_aifc || memcmp(&buf[18], AIFC_FORMAT_QT_IMA_ADPCM, 4) != 0) 137 id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency; 138 else 139 { 140 /* QuickTime IMA ADPCM is 1block = 64 data for each channel */ 141 id3->length = ((int64_t) numSampleFrames * 64000LL) / id3->frequency; 142 } 143 144 id3->vbr = false; /* AIFF files are CBR */ 145 id3->FS_PREFIX(filesize) = filesize(fd); 146 } 147 else 148 { 149 /* skip chunk */ 150 if (lseek(fd, size, SEEK_CUR) < 0) 151 return false; 152 } 153 } 154 155 return numbytes && numChannels; 156}