openalbridge/loaders.c
changeset 2415 35d09cbf819a
parent 2266 289dc8e51210
child 2416 3278cf087339
equal deleted inserted replaced
2414:fd9ca82077d8 2415:35d09cbf819a
    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) {
   137         vorbis_comment	*vorbisComment;	/*other less useful data*/
   153         vorbis_comment	*vorbisComment;	/*other less useful data*/
   138 #endif
   154 #endif
   139 
   155 
   140 	result = ov_fopen((char*) filename, &oggStream);
   156 	result = ov_fopen((char*) filename, &oggStream);
   141 	if (result < 0) {
   157 	if (result < 0) {
   142 		fprintf (stderr, "ERROR: ov_open_callbacks failed with %X", result);
   158 		fprintf (stderr, "ERROR 'load_oggvorbis()': ov_fopen failed with %X", result);
   143                 ov_clear(&oggStream);
   159                 ov_clear(&oggStream);
   144 		return -1;
   160 		return -1;
   145 	}
   161 	}
   146 
   162 
   147         vorbisInfo = ov_info(&oggStream, -1);
   163         vorbisInfo = ov_info(&oggStream, -1);
   158         fprintf(stderr, "Bitrate Windows: %ld\n", vorbisInfo->bitrate_window);
   174         fprintf(stderr, "Bitrate Windows: %ld\n", vorbisInfo->bitrate_window);
   159         fprintf(stderr, "Vendor: %s\n", vorbisComment->vendor);
   175         fprintf(stderr, "Vendor: %s\n", vorbisComment->vendor);
   160         fprintf(stderr, "PCM data size: %lld\n", pcm_length);
   176         fprintf(stderr, "PCM data size: %lld\n", pcm_length);
   161         fprintf(stderr, "# comment: %d\n", vorbisComment->comments);
   177         fprintf(stderr, "# comment: %d\n", vorbisComment->comments);
   162         for (i = 0; i < vorbisComment->comments; i++)
   178         for (i = 0; i < vorbisComment->comments; i++)
   163             fprintf(stderr, "\tComment %d: %s\n", i, vorbisComment->user_comments[i]);
   179                 fprintf(stderr, "\tComment %d: %s\n", i, vorbisComment->user_comments[i]);
   164 #endif
   180 #endif
   165         
   181         
   166         /*allocates enough room for the decoded data*/
   182         /*allocates enough room for the decoded data*/
   167         *data = (char*) Malloc (sizeof(char) * pcm_length);
   183         *data = (char*) Malloc (sizeof(char) * pcm_length);
   168         
   184         
   171             *format = AL_FORMAT_MONO16;
   187             *format = AL_FORMAT_MONO16;
   172         else {
   188         else {
   173             if (vorbisInfo->channels == 2)
   189             if (vorbisInfo->channels == 2)
   174                 *format = AL_FORMAT_STEREO16;
   190                 *format = AL_FORMAT_STEREO16;
   175             else {
   191             else {
   176                 fprintf(stderr, "ERROR: wrong OGG header - channel value (%d)\n", vorbisInfo->channels);
   192                 fprintf(stderr, "ERROR 'load_oggvorbis()': wrong OGG header - channel value (%d)\n", vorbisInfo->channels);
   177                 ov_clear(&oggStream);
   193                 ov_clear(&oggStream);
   178                 return AL_FALSE;
   194                 return AL_FALSE;
   179             }
   195             }
   180         }
   196         }
   181         
   197         
   186                 size += result;
   202                 size += result;
   187             } else {
   203             } else {
   188                 if (result == 0)
   204                 if (result == 0)
   189                     break;
   205                     break;
   190                 else { 
   206                 else { 
   191                     fprintf(stderr, "ERROR: end of file from OGG stream\n");
   207                     fprintf(stderr, "ERROR 'load_oggvorbis()': end of file from OGG stream\n");
   192                     ov_clear(&oggStream);
   208                     ov_clear(&oggStream);
   193                     return AL_FALSE;
   209                     return AL_FALSE;
   194                 }
   210                 }
   195             }
   211             }
   196         }
   212         }