openalbridge/loaders.c
changeset 2259 ca42efdce3ce
parent 2257 7eb31efcfb9b
child 2260 31756e21c436
equal deleted inserted replaced
2258:3dd028604cfd 2259:ca42efdce3ce
    19 #include "loaders.h"
    19 #include "loaders.h"
    20 
    20 
    21 #ifdef __CPLUSPLUS
    21 #ifdef __CPLUSPLUS
    22 extern "C" {
    22 extern "C" {
    23 #endif 
    23 #endif 
    24 	
    24     
    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 		
    30         
    31 		wavfile = Fopen(filename, "rb");
    31         wavfile = Fopen(filename, "rb");
    32 		
    32         
    33 		fread(&WAVHeader.ChunkID, sizeof(uint32_t), 1, wavfile);
    33         fread(&WAVHeader.ChunkID, sizeof(uint32_t), 1, wavfile);
    34 		fread(&WAVHeader.ChunkSize, sizeof(uint32_t), 1, wavfile);
    34         fread(&WAVHeader.ChunkSize, sizeof(uint32_t), 1, wavfile);
    35 		fread(&WAVHeader.Format, sizeof(uint32_t), 1, wavfile);
    35         fread(&WAVHeader.Format, sizeof(uint32_t), 1, wavfile);
    36 		
    36         
    37 #ifdef DEBUG
    37 #ifdef DEBUG
    38 		fprintf(stderr, "ChunkID: %X\n", invert_endianness(WAVHeader.ChunkID));
    38         fprintf(stderr, "ChunkID: %X\n", invert_endianness(WAVHeader.ChunkID));
    39 		fprintf(stderr, "ChunkSize: %d\n", WAVHeader.ChunkSize);
    39         fprintf(stderr, "ChunkSize: %d\n", WAVHeader.ChunkSize);
    40 		fprintf(stderr, "Format: %X\n", invert_endianness(WAVHeader.Format));
    40         fprintf(stderr, "Format: %X\n", invert_endianness(WAVHeader.Format));
    41 #endif
    41 #endif
    42 		
    42         
    43 		fread(&WAVHeader.Subchunk1ID, sizeof(uint32_t), 1, wavfile);
    43         fread(&WAVHeader.Subchunk1ID, sizeof(uint32_t), 1, wavfile);
    44 		fread(&WAVHeader.Subchunk1Size, sizeof(uint32_t), 1, wavfile);
    44         fread(&WAVHeader.Subchunk1Size, sizeof(uint32_t), 1, wavfile);
    45 		fread(&WAVHeader.AudioFormat, sizeof(uint16_t), 1, wavfile);
    45         fread(&WAVHeader.AudioFormat, sizeof(uint16_t), 1, wavfile);
    46 		fread(&WAVHeader.NumChannels, sizeof(uint16_t), 1, wavfile);
    46         fread(&WAVHeader.NumChannels, sizeof(uint16_t), 1, wavfile);
    47 		fread(&WAVHeader.SampleRate, sizeof(uint32_t), 1, wavfile);
    47         fread(&WAVHeader.SampleRate, sizeof(uint32_t), 1, wavfile);
    48 		fread(&WAVHeader.ByteRate, sizeof(uint32_t), 1, wavfile);
    48         fread(&WAVHeader.ByteRate, sizeof(uint32_t), 1, wavfile);
    49 		fread(&WAVHeader.BlockAlign, sizeof(uint16_t), 1, wavfile);
    49         fread(&WAVHeader.BlockAlign, sizeof(uint16_t), 1, wavfile);
    50 		fread(&WAVHeader.BitsPerSample, sizeof(uint16_t), 1, wavfile);
    50         fread(&WAVHeader.BitsPerSample, sizeof(uint16_t), 1, wavfile);
    51 		
    51         
    52 #ifdef DEBUG
    52 #ifdef DEBUG
    53 		fprintf(stderr, "Subchunk1ID: %X\n", invert_endianness(WAVHeader.Subchunk1ID));
    53         fprintf(stderr, "Subchunk1ID: %X\n", invert_endianness(WAVHeader.Subchunk1ID));
    54 		fprintf(stderr, "Subchunk1Size: %d\n", WAVHeader.Subchunk1Size);
    54         fprintf(stderr, "Subchunk1Size: %d\n", WAVHeader.Subchunk1Size);
    55 		fprintf(stderr, "AudioFormat: %d\n", WAVHeader.AudioFormat);
    55         fprintf(stderr, "AudioFormat: %d\n", WAVHeader.AudioFormat);
    56 		fprintf(stderr, "NumChannels: %d\n", WAVHeader.NumChannels);
    56         fprintf(stderr, "NumChannels: %d\n", WAVHeader.NumChannels);
    57 		fprintf(stderr, "SampleRate: %d\n", WAVHeader.SampleRate);
    57         fprintf(stderr, "SampleRate: %d\n", WAVHeader.SampleRate);
    58 		fprintf(stderr, "ByteRate: %d\n", WAVHeader.ByteRate);
    58         fprintf(stderr, "ByteRate: %d\n", WAVHeader.ByteRate);
    59 		fprintf(stderr, "BlockAlign: %d\n", WAVHeader.BlockAlign);
    59         fprintf(stderr, "BlockAlign: %d\n", WAVHeader.BlockAlign);
    60 		fprintf(stderr, "BitsPerSample: %d\n", WAVHeader.BitsPerSample);
    60         fprintf(stderr, "BitsPerSample: %d\n", WAVHeader.BitsPerSample);
    61 #endif
    61 #endif
    62 		
    62         
    63 		do { /*remove useless header chunks (plenty room for improvements)*/
    63         do { /*remove useless header chunks (plenty room for improvements)*/
    64 			t = fread(&WAVHeader.Subchunk2ID, sizeof(uint32_t), 1, wavfile);
    64             t = fread(&WAVHeader.Subchunk2ID, sizeof(uint32_t), 1, wavfile);
    65 			if (invert_endianness(WAVHeader.Subchunk2ID) == 0x64617461)
    65             if (invert_endianness(WAVHeader.Subchunk2ID) == 0x64617461)
    66 				break;
    66                 break;
    67 			if (t <= 0) { /*eof*/
    67             if (t <= 0) { /*eof*/
    68 				fprintf(stderr, "ERROR: wrong WAV header\n");
    68                 fprintf(stderr, "ERROR: wrong WAV header\n");
    69 				return AL_FALSE;
    69                 return AL_FALSE;
    70 			}
    70             }
    71 		} while (1);
    71         } while (1);
    72 		fread(&WAVHeader.Subchunk2Size, sizeof(uint32_t), 1, wavfile);
    72         fread(&WAVHeader.Subchunk2Size, sizeof(uint32_t), 1, wavfile);
    73 		
    73         
    74 #ifdef DEBUG
    74 #ifdef DEBUG
    75 		fprintf(stderr, "Subchunk2ID: %X\n", invert_endianness(WAVHeader.Subchunk2ID));
    75         fprintf(stderr, "Subchunk2ID: %X\n", invert_endianness(WAVHeader.Subchunk2ID));
    76 		fprintf(stderr, "Subchunk2Size: %d\n", WAVHeader.Subchunk2Size);
    76         fprintf(stderr, "Subchunk2Size: %d\n", WAVHeader.Subchunk2Size);
    77 #endif
    77 #endif
    78 		
    78         
    79 		*data = (char*) Malloc (sizeof(char) * WAVHeader.Subchunk2Size);
    79         *data = (char*) Malloc (sizeof(char) * WAVHeader.Subchunk2Size);
    80 		
    80         
    81 		/*this could be improved*/
    81         /*this could be improved*/
    82 		do {
    82         do {
    83 			n += fread(&((*data)[n]), sizeof(uint8_t), 1, wavfile);
    83             n += fread(&((*data)[n]), sizeof(uint8_t), 1, wavfile);
    84 		} while (n < WAVHeader.Subchunk2Size);
    84         } while (n < WAVHeader.Subchunk2Size);
    85 		
    85         
    86 		fclose(wavfile);	
    86         fclose(wavfile);	
    87 		
    87         
    88 #ifdef DEBUG
    88 #ifdef DEBUG
    89 		fprintf(stderr, "Last two bytes of data: %X%X\n", (*data)[n-2], (*data)[n-1]);
    89         fprintf(stderr, "Last two bytes of data: %X%X\n", (*data)[n-2], (*data)[n-1]);
    90 #endif
    90 #endif
    91 		
    91         
    92 		/*remaining parameters*/
    92         /*remaining parameters*/
    93 		/*Valid formats are AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8, and AL_FORMAT_STEREO16*/
    93         /*Valid formats are AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8, and AL_FORMAT_STEREO16*/
    94 		if (WAVHeader.NumChannels == 1) {
    94         if (WAVHeader.NumChannels == 1) {
    95 			if (WAVHeader.BitsPerSample == 8)
    95             if (WAVHeader.BitsPerSample == 8)
    96 				*format = AL_FORMAT_MONO8;
    96                 *format = AL_FORMAT_MONO8;
    97 			else {
    97             else {
    98 				if (WAVHeader.BitsPerSample == 16)
    98                 if (WAVHeader.BitsPerSample == 16)
    99 					*format = AL_FORMAT_MONO16;
    99                     *format = AL_FORMAT_MONO16;
   100 				else {
   100                 else {
   101 					fprintf(stderr, "ERROR: wrong WAV header - bitsample value\n");
   101                     fprintf(stderr, "ERROR: wrong WAV header - bitsample value\n");
   102 					return AL_FALSE;
   102                     return AL_FALSE;
   103 				}
   103                 }
   104 			} 
   104             } 
   105 		} else {
   105         } else {
   106 			if (WAVHeader.NumChannels == 2) {
   106             if (WAVHeader.NumChannels == 2) {
   107 				if (WAVHeader.BitsPerSample == 8)
   107                 if (WAVHeader.BitsPerSample == 8)
   108 					*format = AL_FORMAT_STEREO8;
   108                     *format = AL_FORMAT_STEREO8;
   109 				else {
   109                 else {
   110 					if (WAVHeader.BitsPerSample == 16)
   110                     if (WAVHeader.BitsPerSample == 16)
   111 						*format = AL_FORMAT_STEREO16;
   111                         *format = AL_FORMAT_STEREO16;
   112 					else {
   112                     else {
   113 						fprintf(stderr, "ERROR: wrong WAV header - bitsample value\n");
   113                         fprintf(stderr, "ERROR: wrong WAV header - bitsample value\n");
   114 						return AL_FALSE;
   114                         return AL_FALSE;
   115 					}				
   115                     }				
   116 				}
   116                 }
   117 			} else {
   117             } else {
   118 				fprintf(stderr, "ERROR: wrong WAV header - format value\n");
   118                 fprintf(stderr, "ERROR: wrong WAV header - format value\n");
   119 				return AL_FALSE;
   119                 return AL_FALSE;
   120 			}
   120             }
   121 		}
   121         }
   122 		
   122         
   123 		*bitsize = WAVHeader.Subchunk2Size;
   123         *bitsize = WAVHeader.Subchunk2Size;
   124 		*freq = WAVHeader.SampleRate;
   124         *freq = WAVHeader.SampleRate;
   125 		return AL_TRUE;
   125         return AL_TRUE;
   126 	}
   126     }
   127 	
   127     
   128     
   128     
   129 	int load_oggvorbis (const char *filename, ALenum *format, char **data, ALsizei *bitsize, ALsizei *freq) {
   129     int load_oggvorbis (const char *filename, ALenum *format, char **data, ALsizei *bitsize, ALsizei *freq) {
   130 		/*implementation inspired from http://www.devmaster.net/forums/showthread.php?t=1153 */
   130         /*implementation inspired from http://www.devmaster.net/forums/showthread.php?t=1153 */
   131 		FILE			*oggFile;		/*ogg handle*/
   131         FILE		*oggFile;		/*ogg handle*/
   132 		OggVorbis_File  oggStream;		/*stream handle*/
   132         OggVorbis_File  oggStream;		/*stream handle*/
   133 		vorbis_info		*vorbisInfo;	/*some formatting data*/
   133         vorbis_info	*vorbisInfo;	/*some formatting data*/
   134 		int64_t			pcm_length;		/*length of the decoded data*/
   134         int64_t		pcm_length;		/*length of the decoded data*/
   135 		int size = 0;
   135         int size = 0;
   136 		int section, result;
   136         int section, result;
   137 #ifdef DEBUG
   137 #ifdef DEBUG
   138 		int i;
   138         int i;
   139 		vorbis_comment	*vorbisComment;	/*other less useful data*/
   139         vorbis_comment	*vorbisComment;	/*other less useful data*/
   140 #endif
   140 #endif
   141 		
   141         
   142 		oggFile = Fopen(filename, "rb");
   142         oggFile = Fopen(filename, "rb");
   143 		result = ov_open(oggFile, &oggStream, NULL, 0);	/*TODO: check returning value of result*/
   143         result = ov_open(oggFile, &oggStream, NULL, 0);	/*TODO: check returning value of result*/
   144                 fclose(oggFile);
   144         fclose(oggFile);
   145             
   145         
   146 		vorbisInfo = ov_info(&oggStream, -1);
   146         vorbisInfo = ov_info(&oggStream, -1);
   147 		pcm_length = ov_pcm_total(&oggStream, -1) << vorbisInfo->channels;	
   147         pcm_length = ov_pcm_total(&oggStream, -1) << vorbisInfo->channels;	
   148 		
   148         
   149 #ifdef DEBUG
   149 #ifdef DEBUG
   150 		vorbisComment = ov_comment(&oggStream, -1);
   150         vorbisComment = ov_comment(&oggStream, -1);
   151 		fprintf(stderr, "Version: %d\n", vorbisInfo->version);
   151         fprintf(stderr, "Version: %d\n", vorbisInfo->version);
   152 		fprintf(stderr, "Channels: %d\n", vorbisInfo->channels);
   152         fprintf(stderr, "Channels: %d\n", vorbisInfo->channels);
   153 		fprintf(stderr, "Rate (Hz): %ld\n", vorbisInfo->rate);
   153         fprintf(stderr, "Rate (Hz): %ld\n", vorbisInfo->rate);
   154 		fprintf(stderr, "Bitrate Upper: %ld\n", vorbisInfo->bitrate_upper);
   154         fprintf(stderr, "Bitrate Upper: %ld\n", vorbisInfo->bitrate_upper);
   155 		fprintf(stderr, "Bitrate Nominal: %ld\n", vorbisInfo->bitrate_nominal);
   155         fprintf(stderr, "Bitrate Nominal: %ld\n", vorbisInfo->bitrate_nominal);
   156 		fprintf(stderr, "Bitrate Lower: %ld\n", vorbisInfo->bitrate_lower);
   156         fprintf(stderr, "Bitrate Lower: %ld\n", vorbisInfo->bitrate_lower);
   157 		fprintf(stderr, "Bitrate Windows: %ld\n", vorbisInfo->bitrate_window);
   157         fprintf(stderr, "Bitrate Windows: %ld\n", vorbisInfo->bitrate_window);
   158 		fprintf(stderr, "Vendor: %s\n", vorbisComment->vendor);
   158         fprintf(stderr, "Vendor: %s\n", vorbisComment->vendor);
   159 		fprintf(stderr, "PCM data size: %lld\n", pcm_length);
   159         fprintf(stderr, "PCM data size: %lld\n", pcm_length);
   160 		fprintf(stderr, "# comment: %d\n", vorbisComment->comments);
   160         fprintf(stderr, "# comment: %d\n", vorbisComment->comments);
   161 		for (i = 0; i < vorbisComment->comments; i++)
   161         for (i = 0; i < vorbisComment->comments; i++)
   162 			fprintf(stderr, "\tComment %d: %s\n", i, vorbisComment->user_comments[i]);
   162             fprintf(stderr, "\tComment %d: %s\n", i, vorbisComment->user_comments[i]);
   163 #endif
   163 #endif
   164 		
   164         
   165 		/*allocates enough room for the decoded data*/
   165         /*allocates enough room for the decoded data*/
   166 		*data = (char*) Malloc (sizeof(char) * pcm_length);
   166         *data = (char*) Malloc (sizeof(char) * pcm_length);
   167 		
   167         
   168 		/*there *should* not be ogg at 8 bits*/
   168         /*there *should* not be ogg at 8 bits*/
   169 		if (vorbisInfo->channels == 1)
   169         if (vorbisInfo->channels == 1)
   170 			*format = AL_FORMAT_MONO16;
   170             *format = AL_FORMAT_MONO16;
   171 		else {
   171         else {
   172 			if (vorbisInfo->channels == 2)
   172             if (vorbisInfo->channels == 2)
   173 				*format = AL_FORMAT_STEREO16;
   173                 *format = AL_FORMAT_STEREO16;
   174 			else {
   174             else {
   175 				fprintf(stderr, "ERROR: wrong OGG header - channel value (%d)\n", vorbisInfo->channels);
   175                 fprintf(stderr, "ERROR: wrong OGG header - channel value (%d)\n", vorbisInfo->channels);
   176 				return AL_FALSE;
   176                 return AL_FALSE;
   177 			}
   177             }
   178 		}
   178         }
   179 		
   179         
   180 		while(size < pcm_length) {
   180         while(size < pcm_length) {
   181 			/*ov_read decodes the ogg stream and storse the pcm in data*/
   181             /*ov_read decodes the ogg stream and storse the pcm in data*/
   182 			result = ov_read (&oggStream, *data + size, pcm_length - size, 0, 2, 1, &section);
   182             result = ov_read (&oggStream, *data + size, pcm_length - size, 0, 2, 1, &section);
   183 			if(result > 0) {
   183             if(result > 0) {
   184 				size += result;
   184                 size += result;
   185 			} else {
   185             } else {
   186 				if (result == 0)
   186                 if (result == 0)
   187 					break;
   187                     break;
   188 				else { 
   188                 else { 
   189 					fprintf(stderr, "ERROR: end of file from OGG stream\n");
   189                     fprintf(stderr, "ERROR: end of file from OGG stream\n");
   190 					return AL_FALSE;
   190                     return AL_FALSE;
   191 				}
   191                 }
   192 			}
   192             }
   193 		}
   193         }
   194 		
   194         
   195 		/*records the last fields*/
   195         /*records the last fields*/
   196 		*bitsize = size;
   196         *bitsize = size;
   197 		*freq    = vorbisInfo->rate;
   197         *freq    = vorbisInfo->rate;
   198             
   198         
   199                 ov_clear (&oggStream);
   199         ov_clear (&oggStream);
   200 		return AL_TRUE;
   200         return AL_TRUE;
   201 	}
   201     }
   202 	
   202     
   203 #ifdef __CPLUSPLUS
   203 #ifdef __CPLUSPLUS
   204 }
   204 }
   205 #endif	
   205 #endif