load_aiff.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:6k
源码类别:

多媒体编程

开发平台:

DOS

  1. /*
  2.     SDL_mixer:  An audio mixer library based on the SDL library
  3.     Copyright (C) 1997-2009 Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     This is the source needed to decode an AIFF file into a waveform.
  16.     It's pretty straightforward once you get going. The only
  17.     externally-callable function is Mix_LoadAIFF_RW(), which is meant to
  18.     act as identically to SDL_LoadWAV_RW() as possible.
  19.     This file by Torbj鰎n Andersson (torbjorn.andersson@eurotime.se)
  20.     8SVX file support added by Marc Le Douarain (mavati@club-internet.fr)
  21.     in december 2002.
  22. */
  23. /* $Id: load_aiff.c 5214 2009-11-08 17:11:09Z slouken $ */
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include "SDL_endian.h"
  27. #include "SDL_mixer.h"
  28. #include "load_aiff.h"
  29. /*********************************************/
  30. /* Define values for AIFF (IFF audio) format */
  31. /*********************************************/
  32. #define FORM 0x4d524f46 /* "FORM" */
  33. #define AIFF 0x46464941 /* "AIFF" */
  34. #define SSND 0x444e5353 /* "SSND" */
  35. #define COMM 0x4d4d4f43 /* "COMM" */
  36. #define _8SVX 0x58565338 /* "8SVX" */
  37. #define VHDR 0x52444856 /* "VHDR" */
  38. #define BODY 0x59444F42 /* "BODY" */
  39. /* This function was taken from libsndfile. I don't pretend to fully
  40.  * understand it.
  41.  */
  42. static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
  43. {
  44. /* Is the frequency outside of what we can represent with Uint32? */
  45. if ( (sanebuf[0] & 0x80) || (sanebuf[0] <= 0x3F) || (sanebuf[0] > 0x40)
  46. || (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C) )
  47. return 0;
  48. return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
  49. | (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
  50. }
  51. /* This function is based on SDL_LoadWAV_RW(). */
  52. SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, int freesrc,
  53. SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
  54. {
  55. int was_error;
  56. int found_SSND;
  57. int found_COMM;
  58. int found_VHDR;
  59. int found_BODY;
  60. long start = 0;
  61. Uint32 chunk_type;
  62. Uint32 chunk_length;
  63. long next_chunk;
  64. /* AIFF magic header */
  65. Uint32 FORMchunk;
  66. Uint32 AIFFmagic;
  67. /* SSND chunk */
  68. Uint32 offset;
  69. Uint32 blocksize;
  70. /* COMM format chunk */
  71. Uint16 channels = 0;
  72. Uint32 numsamples = 0;
  73. Uint16 samplesize = 0;
  74. Uint8 sane_freq[10];
  75. Uint32 frequency = 0;
  76. /* Make sure we are passed a valid data source */
  77. was_error = 0;
  78. if ( src == NULL ) {
  79. was_error = 1;
  80. goto done;
  81. }
  82. FORMchunk = SDL_ReadLE32(src);
  83. chunk_length = SDL_ReadBE32(src);
  84. if ( chunk_length == AIFF ) { /* The FORMchunk has already been read */
  85. AIFFmagic    = chunk_length;
  86. chunk_length = FORMchunk;
  87. FORMchunk    = FORM;
  88. } else {
  89. AIFFmagic    = SDL_ReadLE32(src);
  90. }
  91. if ( (FORMchunk != FORM) || ( (AIFFmagic != AIFF) && (AIFFmagic != _8SVX) ) ) {
  92. SDL_SetError("Unrecognized file type (not AIFF nor 8SVX)");
  93. was_error = 1;
  94. goto done;
  95. }
  96. /* TODO: Better santity-checking. */
  97. found_SSND = 0;
  98. found_COMM = 0;
  99. found_VHDR = 0;
  100. found_BODY = 0;
  101. do {
  102. chunk_type = SDL_ReadLE32(src);
  103. chunk_length = SDL_ReadBE32(src);
  104. next_chunk = SDL_RWtell(src) + chunk_length;
  105. /* Paranoia to avoid infinite loops */
  106. if (chunk_length == 0)
  107. break;
  108. switch (chunk_type) {
  109. case SSND:
  110. found_SSND = 1;
  111. offset = SDL_ReadBE32(src);
  112. blocksize = SDL_ReadBE32(src);
  113. start = SDL_RWtell(src) + offset;
  114. break;
  115. case COMM:
  116. found_COMM = 1;
  117. channels = SDL_ReadBE16(src);
  118. numsamples = SDL_ReadBE32(src);
  119. samplesize = SDL_ReadBE16(src);
  120. SDL_RWread(src, sane_freq, sizeof(sane_freq), 1);
  121. frequency = SANE_to_Uint32(sane_freq);
  122. if (frequency == 0) {
  123. SDL_SetError("Bad AIFF sample frequency");
  124. was_error = 1;
  125. goto done;
  126. }
  127. break;
  128. case VHDR:
  129. found_VHDR = 1;
  130. SDL_ReadBE32(src);
  131. SDL_ReadBE32(src);
  132. SDL_ReadBE32(src);
  133. frequency = SDL_ReadBE16(src);
  134. channels = 1;
  135. samplesize = 8;
  136. break;
  137. case BODY:
  138. found_BODY = 1;
  139. numsamples = chunk_length;
  140. start = SDL_RWtell(src);
  141. break;
  142. default:
  143. break;
  144. }
  145. /* a 0 pad byte can be stored for any odd-length chunk */
  146. if (chunk_length&1)
  147. next_chunk++;
  148. } while ( ( ( (AIFFmagic == AIFF) && ( !found_SSND || !found_COMM ) )
  149.   || ( (AIFFmagic == _8SVX ) && ( !found_VHDR || !found_BODY ) ) )
  150.   && SDL_RWseek(src, next_chunk, RW_SEEK_SET) != 1 );
  151. if ( (AIFFmagic == AIFF) && !found_SSND ) {
  152. SDL_SetError("Bad AIFF (no SSND chunk)");
  153. was_error = 1;
  154. goto done;
  155. }
  156. if ( (AIFFmagic == AIFF) && !found_COMM ) {
  157. SDL_SetError("Bad AIFF (no COMM chunk)");
  158. was_error = 1;
  159. goto done;
  160. }
  161. if ( (AIFFmagic == _8SVX) && !found_VHDR ) {
  162. SDL_SetError("Bad 8SVX (no VHDR chunk)");
  163. was_error = 1;
  164. goto done;
  165. }
  166. if ( (AIFFmagic == _8SVX) && !found_BODY ) {
  167. SDL_SetError("Bad 8SVX (no BODY chunk)");
  168. was_error = 1;
  169. goto done;
  170. }
  171. /* Decode the audio data format */
  172. memset(spec, 0, sizeof(*spec));
  173. spec->freq = frequency;
  174. switch (samplesize) {
  175. case 8:
  176. spec->format = AUDIO_S8;
  177. break;
  178. case 16:
  179. spec->format = AUDIO_S16MSB;
  180. break;
  181. default:
  182. SDL_SetError("Unsupported AIFF samplesize");
  183. was_error = 1;
  184. goto done;
  185. }
  186. spec->channels = (Uint8) channels;
  187. spec->samples = 4096; /* Good default buffer size */
  188. *audio_len = channels * numsamples * (samplesize / 8);
  189. *audio_buf = (Uint8 *)malloc(*audio_len);
  190. if ( *audio_buf == NULL ) {
  191. SDL_SetError("Out of memory");
  192. return(NULL);
  193. }
  194. SDL_RWseek(src, start, RW_SEEK_SET);
  195. if ( SDL_RWread(src, *audio_buf, *audio_len, 1) != 1 ) {
  196. SDL_SetError("Unable to read audio data");
  197. return(NULL);
  198. }
  199. /* Don't return a buffer that isn't a multiple of samplesize */
  200. *audio_len &= ~((samplesize / 8) - 1);
  201. done:
  202. if ( freesrc && src ) {
  203. SDL_RWclose(src);
  204. }
  205. if ( was_error ) {
  206. spec = NULL;
  207. }
  208. return(spec);
  209. }