clix: make code to check whether game is end or not to a separate function to reduce...
[kugel-rb.git] / apps / metadata / wave.c
blob79bb8178bd36f3b617178c384cb9d2dc336d8997
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include <inttypes.h>
27 #include "system.h"
28 #include "metadata.h"
29 #include "metadata_common.h"
30 #include "metadata_parsers.h"
31 #include "logf.h"
33 # define AV_WL32(p, d) do { \
34 ((uint8_t*)(p))[0] = (d); \
35 ((uint8_t*)(p))[1] = (d)>>8; \
36 ((uint8_t*)(p))[2] = (d)>>16; \
37 ((uint8_t*)(p))[3] = (d)>>24; \
38 } while(0)
39 # define AV_WL16(p, d) do { \
40 ((uint8_t*)(p))[0] = (d); \
41 ((uint8_t*)(p))[1] = (d)>>8; \
42 } while(0)
44 enum
46 WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */
47 WAVE_FORMAT_ADPCM = 0x0002, /* Microsoft ADPCM Format */
48 WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* IEEE Float */
49 WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */
50 WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */
51 WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */
52 WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */
53 WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */
54 WAVE_FORMAT_XBOX_ADPCM = 0x0069, /* XBOX ADPCM */
55 IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */
56 IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */
57 WAVE_FORMAT_ATRAC3 = 0x0270, /* Atrac3 stream */
58 WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */
61 struct wave_fmt {
62 unsigned int formattag;
63 unsigned long channels;
64 unsigned int blockalign;
65 unsigned long bitspersample;
66 unsigned int samplesperblock;
67 unsigned long numbytes;
70 static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3)
72 unsigned long totalsamples = 0;
74 switch (fmt->formattag)
76 case WAVE_FORMAT_PCM:
77 case WAVE_FORMAT_IEEE_FLOAT:
78 case WAVE_FORMAT_ALAW:
79 case WAVE_FORMAT_MULAW:
80 case IBM_FORMAT_ALAW:
81 case IBM_FORMAT_MULAW:
82 totalsamples =
83 fmt->numbytes / ((((fmt->bitspersample - 1) / 8) + 1) * fmt->channels);
84 break;
85 case WAVE_FORMAT_ADPCM:
86 case WAVE_FORMAT_DVI_ADPCM:
87 case WAVE_FORMAT_XBOX_ADPCM:
88 totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
89 break;
90 case WAVE_FORMAT_YAMAHA_ADPCM:
91 if (fmt->samplesperblock == 0)
93 if (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels)
94 fmt->samplesperblock = id3->frequency / 30;
95 else
96 fmt->samplesperblock = fmt->blockalign * 2 / fmt->channels;
98 totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
99 break;
100 case WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
101 totalsamples = 2 * fmt->numbytes;
102 break;
103 case WAVE_FORMAT_SWF_ADPCM:
104 if (fmt->samplesperblock == 0)
105 fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22)
106 / fmt->bitspersample;
108 totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
109 break;
110 default:
111 totalsamples = 0;
112 break;
114 return totalsamples;
117 bool get_wave_metadata(int fd, struct mp3entry* id3)
119 /* Use the trackname part of the id3 structure as a temporary buffer */
120 unsigned char* buf = (unsigned char *)id3->path;
121 struct wave_fmt fmt;
122 unsigned long totalsamples = 0;
123 unsigned long offset = 0;
124 int read_bytes;
125 int i;
127 memset(&fmt, 0, sizeof(struct wave_fmt));
129 /* get RIFF chunk header */
130 if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 12) < 12))
132 return false;
134 offset += 12;
136 if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0))
138 DEBUGF("metadata error: missing riff header.\n");
139 return false;
142 /* iterate over WAVE chunks until 'data' chunk */
143 while (true)
145 /* get chunk header */
146 if (read(fd, buf, 8) < 8)
147 return false;
148 offset += 8;
150 /* chunkSize */
151 i = get_long_le(&buf[4]);
153 if (memcmp(buf, "fmt ", 4) == 0)
155 /* get rest of chunk */
156 if (i < 16)
157 return false;
159 read_bytes = 16;
160 if (i > 19)
161 read_bytes = 20;
163 if (read(fd, buf, read_bytes) != read_bytes)
164 return false;
166 offset += read_bytes;
167 i -= read_bytes;
169 /* wFormatTag */
170 fmt.formattag = buf[0] | (buf[1] << 8);
171 /* wChannels */
172 fmt.channels = buf[2] | (buf[3] << 8);
173 /* dwSamplesPerSec */
174 id3->frequency = get_long_le(&buf[4]);
175 /* dwAvgBytesPerSec */
176 id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000;
177 /* wBlockAlign */
178 fmt.blockalign = buf[12] | (buf[13] << 8);
179 id3->bytesperframe = fmt.blockalign;
180 /* wBitsPerSample */
181 fmt.bitspersample = buf[14] | (buf[15] << 8);
182 if (read_bytes > 19)
184 /* wSamplesPerBlock */
185 fmt.samplesperblock = buf[18] | (buf[19] << 8);
188 /* Check for ATRAC3 stream */
189 if (fmt.formattag == WAVE_FORMAT_ATRAC3)
191 int jsflag = 0;
192 if(id3->bitrate == 66 || id3->bitrate == 94)
193 jsflag = 1;
195 id3->extradata_size = 14;
196 id3->channels = 2;
197 id3->codectype = AFMT_OMA_ATRAC3;
198 /* Store the extradata for the codec */
199 AV_WL16(&id3->id3v2buf[0], 1); // always 1
200 AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate
201 AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode
202 AV_WL16(&id3->id3v2buf[8], jsflag); // coding mode
203 AV_WL16(&id3->id3v2buf[10], 1); // always 1
204 AV_WL16(&id3->id3v2buf[12], 0); // always 0
207 else if (memcmp(buf, "data", 4) == 0)
209 fmt.numbytes = i;
210 if (fmt.formattag == WAVE_FORMAT_ATRAC3)
211 id3->first_frame_offset = offset;
212 break;
214 else if (memcmp(buf, "fact", 4) == 0)
216 /* dwSampleLength */
217 if (i >= 4)
219 /* get rest of chunk */
220 if (read(fd, buf, 4) < 4)
221 return false;
222 offset += 4;
223 i -= 4;
224 totalsamples = get_long_le(buf);
228 /* seek to next chunk (even chunk sizes must be padded) */
229 if (i & 0x01)
230 i++;
232 if(lseek(fd, i, SEEK_CUR) < 0)
233 return false;
234 offset += i;
237 if ((fmt.numbytes == 0) || (fmt.channels == 0) || (fmt.blockalign == 0))
239 DEBUGF("metadata error: numbytes, channels, or blockalign is 0.\n");
240 return false;
243 if (totalsamples == 0)
245 totalsamples = get_totalsamples(&fmt, id3);
248 id3->vbr = false; /* All WAV files are CBR */
249 id3->filesize = filesize(fd);
251 /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
252 if(id3->codectype != AFMT_OMA_ATRAC3)
253 id3->length = ((int64_t) totalsamples * 1000) / id3->frequency;
254 else
255 id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate;
257 return true;