25 int load_wavpcm (const char *filename, ALenum *format, char ** data, ALsizei *bitsize, ALsizei *freq) { |
25 int load_wavpcm (const char *filename, ALenum *format, char ** data, ALsizei *bitsize, ALsizei *freq) { |
26 WAV_header_t WAVHeader; |
26 WAV_header_t WAVHeader; |
27 FILE *wavfile; |
27 FILE *wavfile; |
28 int32_t t; |
28 int32_t t; |
29 uint32_t n = 0; |
29 uint32_t n = 0; |
|
30 uint8_t sub0, sub1, sub2, sub3; |
30 |
31 |
31 wavfile = Fopen(filename, "rb"); |
32 wavfile = Fopen(filename, "rb"); |
32 |
33 |
33 fread(&WAVHeader.ChunkID, sizeof(uint32_t), 1, wavfile); |
34 fread(&WAVHeader.ChunkID, sizeof(uint32_t), 1, wavfile); /*RIFF*/ |
34 fread(&WAVHeader.ChunkSize, sizeof(uint32_t), 1, wavfile); |
35 fread(&WAVHeader.ChunkSize, sizeof(uint32_t), 1, wavfile); |
35 fread(&WAVHeader.Format, sizeof(uint32_t), 1, wavfile); |
36 fread(&WAVHeader.Format, sizeof(uint32_t), 1, wavfile); /*WAVE*/ |
36 |
37 |
37 #ifdef DEBUG |
38 #ifdef DEBUG |
38 fprintf(stderr, "ChunkID: %X\n", invert_endianness(WAVHeader.ChunkID)); |
39 fprintf(stderr, "ChunkID: %X\n", ENDIAN_BIG_32(WAVHeader.ChunkID)); |
39 fprintf(stderr, "ChunkSize: %d\n", WAVHeader.ChunkSize); |
40 fprintf(stderr, "ChunkSize: %d\n", ENDIAN_LITTLE_32(WAVHeader.ChunkSize)); |
40 fprintf(stderr, "Format: %X\n", invert_endianness(WAVHeader.Format)); |
41 fprintf(stderr, "Format: %X\n", ENDIAN_BIG_32(WAVHeader.Format)); |
41 #endif |
42 #endif |
42 |
43 |
43 fread(&WAVHeader.Subchunk1ID, sizeof(uint32_t), 1, wavfile); |
44 fread(&WAVHeader.Subchunk1ID, sizeof(uint32_t), 1, wavfile); /*fmt */ |
44 fread(&WAVHeader.Subchunk1Size, sizeof(uint32_t), 1, wavfile); |
45 fread(&WAVHeader.Subchunk1Size, sizeof(uint32_t), 1, wavfile); |
45 fread(&WAVHeader.AudioFormat, sizeof(uint16_t), 1, wavfile); |
46 fread(&WAVHeader.AudioFormat, sizeof(uint16_t), 1, wavfile); |
46 fread(&WAVHeader.NumChannels, sizeof(uint16_t), 1, wavfile); |
47 fread(&WAVHeader.NumChannels, sizeof(uint16_t), 1, wavfile); |
47 fread(&WAVHeader.SampleRate, sizeof(uint32_t), 1, wavfile); |
48 fread(&WAVHeader.SampleRate, sizeof(uint32_t), 1, wavfile); |
48 fread(&WAVHeader.ByteRate, sizeof(uint32_t), 1, wavfile); |
49 fread(&WAVHeader.ByteRate, sizeof(uint32_t), 1, wavfile); |
49 fread(&WAVHeader.BlockAlign, sizeof(uint16_t), 1, wavfile); |
50 fread(&WAVHeader.BlockAlign, sizeof(uint16_t), 1, wavfile); |
50 fread(&WAVHeader.BitsPerSample, sizeof(uint16_t), 1, wavfile); |
51 fread(&WAVHeader.BitsPerSample, sizeof(uint16_t), 1, wavfile); |
51 |
52 |
52 #ifdef DEBUG |
53 #ifdef DEBUG |
53 fprintf(stderr, "Subchunk1ID: %X\n", invert_endianness(WAVHeader.Subchunk1ID)); |
54 fprintf(stderr, "Subchunk1ID: %X\n", ENDIAN_BIG_32(WAVHeader.Subchunk1ID)); |
54 fprintf(stderr, "Subchunk1Size: %d\n", WAVHeader.Subchunk1Size); |
55 fprintf(stderr, "Subchunk1Size: %d\n", ENDIAN_LITTLE_32(WAVHeader.Subchunk1Size)); |
55 fprintf(stderr, "AudioFormat: %d\n", WAVHeader.AudioFormat); |
56 fprintf(stderr, "AudioFormat: %d\n", ENDIAN_LITTLE_16(WAVHeader.AudioFormat)); |
56 fprintf(stderr, "NumChannels: %d\n", WAVHeader.NumChannels); |
57 fprintf(stderr, "NumChannels: %d\n", ENDIAN_LITTLE_16(WAVHeader.NumChannels)); |
57 fprintf(stderr, "SampleRate: %d\n", WAVHeader.SampleRate); |
58 fprintf(stderr, "SampleRate: %d\n", ENDIAN_LITTLE_32(WAVHeader.SampleRate)); |
58 fprintf(stderr, "ByteRate: %d\n", WAVHeader.ByteRate); |
59 fprintf(stderr, "ByteRate: %d\n", ENDIAN_LITTLE_32(WAVHeader.ByteRate)); |
59 fprintf(stderr, "BlockAlign: %d\n", WAVHeader.BlockAlign); |
60 fprintf(stderr, "BlockAlign: %d\n", ENDIAN_LITTLE_16(WAVHeader.BlockAlign)); |
60 fprintf(stderr, "BitsPerSample: %d\n", WAVHeader.BitsPerSample); |
61 fprintf(stderr, "BitsPerSample: %d\n", ENDIAN_LITTLE_16(WAVHeader.BitsPerSample)); |
61 #endif |
62 #endif |
62 |
63 |
63 do { /*remove useless header chunks (plenty room for improvements)*/ |
64 /*remove useless header chunks by looking for the WAV_HEADER_SUBCHUNK2ID integer */ |
64 t = fread(&WAVHeader.Subchunk2ID, sizeof(uint32_t), 1, wavfile); |
65 do { |
65 if (invert_endianness(WAVHeader.Subchunk2ID) == 0x64617461) |
66 t = fread(&sub0, sizeof(uint8_t), 1, wavfile); |
66 break; |
67 if(sub0 == 0x64) { |
67 if (t <= 0) { /*eof*/ |
68 t = fread(&sub1, sizeof(uint8_t), 1, wavfile); |
68 fprintf(stderr, "ERROR: wrong WAV header\n"); |
69 if(sub1 == 0x61) { |
69 return AL_FALSE; |
70 t = fread(&sub2, sizeof(uint8_t), 1, wavfile); |
70 } |
71 if(sub2 == 0x74) { |
|
72 t = fread(&sub3, sizeof(uint8_t), 1, wavfile); |
|
73 if(sub3 == 0x61) { |
|
74 WAVHeader.Subchunk2ID = WAV_HEADER_SUBCHUNK2ID; |
|
75 break; |
|
76 } |
|
77 } |
|
78 } |
|
79 } |
|
80 |
|
81 if (t <= 0) { |
|
82 /*eof*/ |
|
83 fprintf(stderr, "ERROR 'load_wavpcm()': wrong WAV header\n"); |
|
84 return AL_FALSE; |
|
85 } |
71 } while (1); |
86 } while (1); |
|
87 |
72 fread(&WAVHeader.Subchunk2Size, sizeof(uint32_t), 1, wavfile); |
88 fread(&WAVHeader.Subchunk2Size, sizeof(uint32_t), 1, wavfile); |
73 |
89 |
74 #ifdef DEBUG |
90 #ifdef DEBUG |
75 fprintf(stderr, "Subchunk2ID: %X\n", invert_endianness(WAVHeader.Subchunk2ID)); |
91 fprintf(stderr, "Subchunk2ID: %X\n", ENDIAN_LITTLE_32(WAVHeader.Subchunk2ID)); |
76 fprintf(stderr, "Subchunk2Size: %d\n", WAVHeader.Subchunk2Size); |
92 fprintf(stderr, "Subchunk2Size: %d\n", ENDIAN_LITTLE_32(WAVHeader.Subchunk2Size)); |
77 #endif |
93 #endif |
78 |
94 |
79 *data = (char*) Malloc (sizeof(char) * WAVHeader.Subchunk2Size); |
95 *data = (char*) Malloc (sizeof(char) * ENDIAN_LITTLE_32(WAVHeader.Subchunk2Size)); |
80 |
96 |
81 /*this could be improved*/ |
97 /*read the actual sound data*/ |
82 do { |
98 do { |
83 n += fread(&((*data)[n]), sizeof(uint8_t), 1, wavfile); |
99 n += fread(&((*data)[n]), sizeof(uint8_t), 4, wavfile); |
84 } while (n < WAVHeader.Subchunk2Size); |
100 } while (n < ENDIAN_LITTLE_32(WAVHeader.Subchunk2Size)); |
85 |
101 |
86 fclose(wavfile); |
102 fclose(wavfile); |
87 |
103 |
88 #ifdef DEBUG |
104 #ifdef DEBUG |
89 fprintf(stderr, "Last two bytes of data: %X%X\n", (*data)[n-2], (*data)[n-1]); |
105 fprintf(stderr, "WAV data loaded\n"); |
90 #endif |
106 #endif |
91 |
107 |
92 /*remaining parameters*/ |
108 /*set parameters for OpenAL*/ |
93 /*Valid formats are AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8, and AL_FORMAT_STEREO16*/ |
109 /*Valid formats are AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8, and AL_FORMAT_STEREO16*/ |
94 if (WAVHeader.NumChannels == 1) { |
110 if (ENDIAN_LITTLE_16(WAVHeader.NumChannels) == 1) { |
95 if (WAVHeader.BitsPerSample == 8) |
111 if (ENDIAN_LITTLE_16(WAVHeader.BitsPerSample) == 8) |
96 *format = AL_FORMAT_MONO8; |
112 *format = AL_FORMAT_MONO8; |
97 else { |
113 else { |
98 if (WAVHeader.BitsPerSample == 16) |
114 if (ENDIAN_LITTLE_16(WAVHeader.BitsPerSample) == 16) |
99 *format = AL_FORMAT_MONO16; |
115 *format = AL_FORMAT_MONO16; |
100 else { |
116 else { |
101 fprintf(stderr, "ERROR: wrong WAV header - bitsample value\n"); |
117 fprintf(stderr, "ERROR 'load_wavpcm()': wrong WAV header - bitsample value\n"); |
102 return AL_FALSE; |
118 return AL_FALSE; |
103 } |
119 } |
104 } |
120 } |
105 } else { |
121 } else { |
106 if (WAVHeader.NumChannels == 2) { |
122 if (ENDIAN_LITTLE_16(WAVHeader.NumChannels) == 2) { |
107 if (WAVHeader.BitsPerSample == 8) |
123 if (ENDIAN_LITTLE_16(WAVHeader.BitsPerSample) == 8) |
108 *format = AL_FORMAT_STEREO8; |
124 *format = AL_FORMAT_STEREO8; |
109 else { |
125 else { |
110 if (WAVHeader.BitsPerSample == 16) |
126 if (ENDIAN_LITTLE_16(WAVHeader.BitsPerSample) == 16) |
111 *format = AL_FORMAT_STEREO16; |
127 *format = AL_FORMAT_STEREO16; |
112 else { |
128 else { |
113 fprintf(stderr, "ERROR: wrong WAV header - bitsample value\n"); |
129 fprintf(stderr, "ERROR 'load_wavpcm()': wrong WAV header - bitsample value\n"); |
114 return AL_FALSE; |
130 return AL_FALSE; |
115 } |
131 } |
116 } |
132 } |
117 } else { |
133 } else { |
118 fprintf(stderr, "ERROR: wrong WAV header - format value\n"); |
134 fprintf(stderr, "ERROR 'load_wavpcm()': wrong WAV header - format value\n"); |
119 return AL_FALSE; |
135 return AL_FALSE; |
120 } |
136 } |
121 } |
137 } |
122 |
138 |
123 *bitsize = WAVHeader.Subchunk2Size; |
139 *bitsize = ENDIAN_LITTLE_32(WAVHeader.Subchunk2Size); |
124 *freq = WAVHeader.SampleRate; |
140 *freq = ENDIAN_LITTLE_32(WAVHeader.SampleRate); |
125 return AL_TRUE; |
141 return AL_TRUE; |
126 } |
142 } |
127 |
143 |
128 |
144 |
129 int load_oggvorbis (const char *filename, ALenum *format, char **data, ALsizei *bitsize, ALsizei *freq) { |
145 int load_oggvorbis (const char *filename, ALenum *format, char **data, ALsizei *bitsize, ALsizei *freq) { |