summaryrefslogtreecommitdiff
path: root/apps/metadata/wave.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/metadata/wave.c')
-rw-r--r--apps/metadata/wave.c138
1 files changed, 113 insertions, 25 deletions
diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c
index acef32dd38..79bb8178bd 100644
--- a/apps/metadata/wave.c
+++ b/apps/metadata/wave.c
@@ -28,6 +28,7 @@
28#include "metadata.h" 28#include "metadata.h"
29#include "metadata_common.h" 29#include "metadata_common.h"
30#include "metadata_parsers.h" 30#include "metadata_parsers.h"
31#include "logf.h"
31 32
32# define AV_WL32(p, d) do { \ 33# define AV_WL32(p, d) do { \
33 ((uint8_t*)(p))[0] = (d); \ 34 ((uint8_t*)(p))[0] = (d); \
@@ -40,29 +41,101 @@
40 ((uint8_t*)(p))[1] = (d)>>8; \ 41 ((uint8_t*)(p))[1] = (d)>>8; \
41 } while(0) 42 } while(0)
42 43
44enum
45{
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 */
59};
60
61struct 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;
68};
69
70static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3)
71{
72 unsigned long totalsamples = 0;
73
74 switch (fmt->formattag)
75 {
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)
92 {
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;
97 }
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;
107
108 totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
109 break;
110 default:
111 totalsamples = 0;
112 break;
113 }
114 return totalsamples;
115}
116
43bool get_wave_metadata(int fd, struct mp3entry* id3) 117bool get_wave_metadata(int fd, struct mp3entry* id3)
44{ 118{
45 /* Use the trackname part of the id3 structure as a temporary buffer */ 119 /* Use the trackname part of the id3 structure as a temporary buffer */
46 unsigned char* buf = (unsigned char *)id3->path; 120 unsigned char* buf = (unsigned char *)id3->path;
121 struct wave_fmt fmt;
47 unsigned long totalsamples = 0; 122 unsigned long totalsamples = 0;
48 unsigned long channels = 0;
49 unsigned long bitspersample = 0;
50 unsigned long numbytes = 0;
51 unsigned long offset = 0; 123 unsigned long offset = 0;
52 int read_bytes; 124 int read_bytes;
53 int i; 125 int i;
54 126
127 memset(&fmt, 0, sizeof(struct wave_fmt));
128
55 /* get RIFF chunk header */ 129 /* get RIFF chunk header */
56 if ((lseek(fd, 0, SEEK_SET) < 0) 130 if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 12) < 12))
57 || ((read_bytes = read(fd, buf, 12)) < 12))
58 { 131 {
59 return false; 132 return false;
60 } 133 }
61 offset += 12; 134 offset += 12;
62 135
63 if ((memcmp(buf, "RIFF",4) != 0) 136 if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0))
64 || (memcmp(&buf[8], "WAVE", 4) !=0 ))
65 { 137 {
138 DEBUGF("metadata error: missing riff header.\n");
66 return false; 139 return false;
67 } 140 }
68 141
@@ -70,7 +143,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
70 while (true) 143 while (true)
71 { 144 {
72 /* get chunk header */ 145 /* get chunk header */
73 if ((read_bytes = read(fd, buf, 8)) < 8) 146 if (read(fd, buf, 8) < 8)
74 return false; 147 return false;
75 offset += 8; 148 offset += 8;
76 149
@@ -80,26 +153,41 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
80 if (memcmp(buf, "fmt ", 4) == 0) 153 if (memcmp(buf, "fmt ", 4) == 0)
81 { 154 {
82 /* get rest of chunk */ 155 /* get rest of chunk */
83 if ((read_bytes = read(fd, buf, 16)) < 16) 156 if (i < 16)
84 return false; 157 return false;
85 offset += 16;
86 i -= 16;
87 158
159 read_bytes = 16;
160 if (i > 19)
161 read_bytes = 20;
88 162
89 /* skipping wFormatTag */ 163 if (read(fd, buf, read_bytes) != read_bytes)
164 return false;
165
166 offset += read_bytes;
167 i -= read_bytes;
168
169 /* wFormatTag */
170 fmt.formattag = buf[0] | (buf[1] << 8);
90 /* wChannels */ 171 /* wChannels */
91 channels = buf[2] | (buf[3] << 8); 172 fmt.channels = buf[2] | (buf[3] << 8);
92 /* dwSamplesPerSec */ 173 /* dwSamplesPerSec */
93 id3->frequency = get_long_le(&buf[4]); 174 id3->frequency = get_long_le(&buf[4]);
94 /* dwAvgBytesPerSec */ 175 /* dwAvgBytesPerSec */
95 id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000; 176 id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000;
96 /* wBlockAlign */ 177 /* wBlockAlign */
97 id3->bytesperframe = buf[12] | (buf[13] << 8); 178 fmt.blockalign = buf[12] | (buf[13] << 8);
179 id3->bytesperframe = fmt.blockalign;
98 /* wBitsPerSample */ 180 /* wBitsPerSample */
99 bitspersample = buf[14] | (buf[15] << 8); 181 fmt.bitspersample = buf[14] | (buf[15] << 8);
182 if (read_bytes > 19)
183 {
184 /* wSamplesPerBlock */
185 fmt.samplesperblock = buf[18] | (buf[19] << 8);
186 }
187
100 /* Check for ATRAC3 stream */ 188 /* Check for ATRAC3 stream */
101 if((buf[0] | (buf[1] << 8)) == 0x0270) 189 if (fmt.formattag == WAVE_FORMAT_ATRAC3)
102 { 190 {
103 int jsflag = 0; 191 int jsflag = 0;
104 if(id3->bitrate == 66 || id3->bitrate == 94) 192 if(id3->bitrate == 66 || id3->bitrate == 94)
105 jsflag = 1; 193 jsflag = 1;
@@ -107,7 +195,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
107 id3->extradata_size = 14; 195 id3->extradata_size = 14;
108 id3->channels = 2; 196 id3->channels = 2;
109 id3->codectype = AFMT_OMA_ATRAC3; 197 id3->codectype = AFMT_OMA_ATRAC3;
110 /* Store the extradata for the codec */ 198 /* Store the extradata for the codec */
111 AV_WL16(&id3->id3v2buf[0], 1); // always 1 199 AV_WL16(&id3->id3v2buf[0], 1); // always 1
112 AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate 200 AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate
113 AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode 201 AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode
@@ -118,8 +206,9 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
118 } 206 }
119 else if (memcmp(buf, "data", 4) == 0) 207 else if (memcmp(buf, "data", 4) == 0)
120 { 208 {
121 numbytes = i; 209 fmt.numbytes = i;
122 id3->first_frame_offset = offset; 210 if (fmt.formattag == WAVE_FORMAT_ATRAC3)
211 id3->first_frame_offset = offset;
123 break; 212 break;
124 } 213 }
125 else if (memcmp(buf, "fact", 4) == 0) 214 else if (memcmp(buf, "fact", 4) == 0)
@@ -128,7 +217,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
128 if (i >= 4) 217 if (i >= 4)
129 { 218 {
130 /* get rest of chunk */ 219 /* get rest of chunk */
131 if ((read_bytes = read(fd, buf, 4)) < 4) 220 if (read(fd, buf, 4) < 4)
132 return false; 221 return false;
133 offset += 4; 222 offset += 4;
134 i -= 4; 223 i -= 4;
@@ -145,16 +234,15 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
145 offset += i; 234 offset += i;
146 } 235 }
147 236
148 if ((numbytes == 0) || (channels == 0)) 237 if ((fmt.numbytes == 0) || (fmt.channels == 0) || (fmt.blockalign == 0))
149 { 238 {
239 DEBUGF("metadata error: numbytes, channels, or blockalign is 0.\n");
150 return false; 240 return false;
151 } 241 }
152 242
153 if (totalsamples == 0) 243 if (totalsamples == 0)
154 { 244 {
155 /* for PCM only */ 245 totalsamples = get_totalsamples(&fmt, id3);
156 totalsamples = numbytes
157 / ((((bitspersample - 1) / 8) + 1) * channels);
158 } 246 }
159 247
160 id3->vbr = false; /* All WAV files are CBR */ 248 id3->vbr = false; /* All WAV files are CBR */