7 wavefile_t *waveopen(char *filename, char **errorstring)
9 int validfmt, position, length, l;
13 unsigned char buffer[1024];
15 file = fopen(filename, "rb");
18 w = malloc(sizeof(*w));
19 memset(w, 0, sizeof(*w));
23 if (fread(buffer, 12, 1, w->file))
25 if (!memcmp(buffer, "RIFF", 4))
27 if (!memcmp(buffer + 8, "WAVE", 4))
32 if (!fread(buffer, 8, 1, w->file))
34 //error = "error reading chunk\n");
37 position = ftell(w->file);
38 length = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | (buffer[7] << 24);
39 if (!memcmp(buffer, "fmt ", 4))
45 if (!fread(buffer, l, 1, w->file))
47 error = "error reading \"fmt \" chunk\n";
50 w->info_format = buffer[0] | (buffer[1] << 8);
51 if (w->info_format != 1)
53 error = "only PCM format supported\n";
56 w->info_channels = buffer[2] | (buffer[3] << 8);
57 if (w->info_channels != 1 && w->info_channels != 2)
59 error = "only mono and stereo supported\n";
62 w->info_rate = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | (buffer[7] << 24);
65 error = "only rates 1hz-100khz supported\n";
68 w->info_bits = buffer[14] | (buffer[15] << 8);
69 if (w->info_bits != 8 && w->info_bits != 16)
71 error = "only 8bit and 16bit supported\n";
76 else if (!memcmp(buffer, "data", 4))
80 w->datalength = length;
81 w->dataposition = position;
84 // other chunks that might be of interest:
85 // "cue " (for looping)
86 if (fseek(w->file, position + length, SEEK_SET))
88 error = "error seeking to next chunk\n";
92 if (w->datalength && validfmt)
94 w->info_bytesperchannel = w->info_bits / 8;
95 w->info_bytespersample = w->info_channels * w->info_bytesperchannel;
96 w->length = w->datalength / w->info_bytespersample;
98 fseek(w->file, w->dataposition, SEEK_SET);
103 error = "not a RIFF WAVE file\n";
106 error = "not a RIFF file\n";
109 error = "error reading file\n";
113 error = "unable to allocate memory\n";
117 error = "unable to open file\n";
119 *errorstring = error;
123 void waveclose(wavefile_t *f)
132 unsigned int waveread16stereo(wavefile_t *w, short *soundbuffer, unsigned int samples)
139 if (length > w->length - w->position)
140 length = w->length - w->position;
141 if (w->bufferlength < length)
145 w->bufferlength = length + 100;
146 w->buffer = malloc(w->bufferlength * w->info_bytespersample);
148 length = fread(w->buffer, w->info_bytespersample, length, w->file);
149 w->position += length;
152 if (w->info_bytesperchannel == 2)
154 if (w->info_channels == 2)
156 for (i = 0, in = w->buffer, out = soundbuffer;i < length;i++, in += 4, out += 2)
158 out[0] = in[0] | (in[1] << 8);
159 out[1] = in[2] | (in[3] << 8);
163 for (i = 0, in = w->buffer, out = soundbuffer;i < length;i++, in += 2, out += 2)
164 out[0] = out[1] = in[0] | (in[1] << 8);
168 if (w->info_channels == 2)
170 for (i = 0, in = w->buffer, out = soundbuffer;i < length;i++, in += 2, out += 2)
172 out[0] = (in[0] - 128) << 8;
173 out[1] = (in[1] - 128) << 8;
177 for (i = 0, in = w->buffer, out = soundbuffer;i < length;i++, in += 1, out += 2)
178 out[0] = out[1] = (in[0] - 128) << 8;
184 unsigned int waveseek(wavefile_t *w, unsigned int samples)
186 if (samples > w->datalength)
190 w->position = samples;
191 fseek(w->file, w->dataposition + w->position * w->info_bytespersample, SEEK_SET);