-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathlibwav.c
More file actions
160 lines (128 loc) · 4.2 KB
/
Copy pathlibwav.c
File metadata and controls
160 lines (128 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "libwav.h"
#include <string.h>
#include <stdio.h>
typedef struct __attribute__((__packed__)) {
uint8_t riff[4];
int32_t totalsize;
uint8_t riff_format[4];
} wavmagic_t;
typedef struct __attribute__((__packed__)) {
uint8_t id[4];
size_t size;
} chunkhdr_t;
typedef struct __attribute__((__packed__)) {
int16_t format;
int16_t channels;
int32_t sample_rate;
int32_t byte_per_sec;
int16_t blocksize;
int16_t sample_size;
} fmthdr_t;
int wav_get_info_file(file_t file, WavFileInfo *result) {
wavmagic_t wavmagic;
chunkhdr_t chunkhdr;
fmthdr_t fmthdr;
memset(result, 0, sizeof(WavFileInfo));
fs_seek(file, 0, SEEK_SET);
if(fs_read(file, &wavmagic, sizeof(wavmagic)) != sizeof(wavmagic)) {
fs_close(file);
return 0;
}
if(strncmp((const char*)wavmagic.riff, "RIFF", 4)) {
fs_close(file);
return 0;
}
if(strncmp((const char*)wavmagic.riff_format, "WAVE", 4)) {
fs_close(file);
return 0;
}
do {
/* Read the chunk header */
if(fs_read(file, &(chunkhdr), sizeof(chunkhdr)) != sizeof(chunkhdr)) {
fs_close(file);
return 0;
}
/* If it is the fmt chunk, grab the fields we care about and skip the
rest of the section if there is more */
if(strncmp((const char *)chunkhdr.id, "fmt ", 4) == 0) {
if(fs_read(file, &(fmthdr), sizeof(fmthdr)) != sizeof(fmthdr)) {
fs_close(file);
return 0;
}
/* Skip the rest of the fmt chunk */
fs_seek(file, chunkhdr.size - sizeof(fmthdr), SEEK_CUR);
}
/* If we found the data chunk, we are done */
else if(strncmp((const char *)chunkhdr.id, "data", 4) == 0) {
break;
}
/* Skip meta data */
else {
fs_seek(file, chunkhdr.size, SEEK_CUR);
}
} while(1);
result->format = fmthdr.format;
result->channels = fmthdr.channels;
result->sample_rate = fmthdr.sample_rate;
result->sample_size = fmthdr.sample_size;
result->data_length = chunkhdr.size;
result->data_offset = fs_tell(file);
return 1;
}
int wav_get_info_cdda(file_t file, WavFileInfo *result) {
result->format = WAVE_FORMAT_PCM;
result->channels = 2;
result->sample_rate = 44100;
result->sample_size = 16;
result->data_length = fs_total(file);
result->data_offset = 0;
return 1;
}
int wav_get_info_adpcm(file_t file, WavFileInfo *result) {
result->format = WAVE_FORMAT_YAMAHA_ADPCM;
result->channels = 2;
result->sample_rate = 44100;
result->sample_size = 4;
result->data_length = fs_total(file);
result->data_offset = 0;
return 1;
}
int wav_get_info_buffer(const uint8_t *buffer, WavFileInfo *result) {
wavmagic_t wavmagic;
chunkhdr_t chunkhdr;
fmthdr_t fmthdr;
size_t data_offset = sizeof(wavmagic_t);
memset(result, 0, sizeof(WavFileInfo));
memcpy(&wavmagic, buffer, sizeof(wavmagic_t));
if(strncmp((const char*)wavmagic.riff, "RIFF", 4))
return 0;
if(strncmp((const char*)wavmagic.riff_format, "WAVE", 4))
return 0;
do {
/* Read the next chunk header */
memcpy(&(chunkhdr), buffer + data_offset, sizeof(chunkhdr));
data_offset += sizeof(chunkhdr);
/* If it is the fmt chunk, grab the fields we care about and skip the
rest of the section if there is more */
if(strncmp((const char *)chunkhdr.id, "fmt ", 4) == 0) {
memcpy(&(fmthdr), buffer + data_offset, sizeof(fmthdr));
/* Skip the rest of the fmt chunk */
data_offset += chunkhdr.size;
}
/* If we found the data chunk, we are done */
else if(strncmp((const char *)chunkhdr.id, "data", 4) == 0) {
break;
}
/* Skip meta data */
else {
data_offset += chunkhdr.size;
}
} while(1);
result->format = fmthdr.format;
result->channels = fmthdr.channels;
result->sample_rate = fmthdr.sample_rate;
result->sample_size = fmthdr.sample_size;
result->data_length = chunkhdr.size;
result->data_offset = data_offset;
return 1;
}