void *ac_getWAVEadpcm_info(void *data, ALuint *size, void *spec) { void *retval; alWaveFMT_LOKI *format; alMSADPCM_state_LOKI *mss; alIMAADPCM_state_LOKI *ias; Chunk riffchunk = { 0, 0, 0 }; int offset = 12; ALubyte *ext_format_reader; ALushort reader16; int i; do { ReadChunk(data, &offset, &riffchunk); } while ((riffchunk.magic == WAVE) || (riffchunk.magic == RIFF)); if(riffchunk.magic != FMT) { fprintf(stderr, "returning NULL\n"); return NULL; } format = (alWaveFMT_LOKI *) riffchunk.data; do { ReadChunk(data, &offset, &riffchunk); retval = riffchunk.data; } while (riffchunk.magic != DATA); *size = riffchunk.length; switch(swap16le(format->encoding)) { case MS_ADPCM_CODE: ext_format_reader = (ALubyte *) format + 18; mss = (alMSADPCM_state_LOKI *) spec; mss->wavefmt.encoding = swap16le(format->encoding); mss->wavefmt.channels = swap16le(format->channels); mss->wavefmt.frequency = swap32le(format->frequency); mss->wavefmt.byterate = swap32le(format->byterate); mss->wavefmt.blockalign = swap16le(format->blockalign); mss->wavefmt.bitspersample = swap16le(format->bitspersample); ext_format_reader = cp16le(ext_format_reader, &reader16); mss->wSamplesPerBlock = reader16; ext_format_reader = cp16le(ext_format_reader, &reader16); mss->wNumCoef = reader16; if(mss->wNumCoef != 7) { fprintf(stderr, "wNumCoeff != 7\n"); } for(i = 0; i < mss->wNumCoef; i++) { ext_format_reader = cp16le(ext_format_reader,&reader16); mss->aCoeff[i][0] = reader16; ext_format_reader = cp16le(ext_format_reader,&reader16); mss->aCoeff[i][1] = reader16; } return retval; case IMA_ADPCM_CODE: ias = (alIMAADPCM_state_LOKI *) spec; InitIMA_ADPCM(ias, format); return retval; case PCM_CODE: default: fprintf(stderr, "returning NULL\n"); return NULL; } }
SDL_AudioSpec * SDL_LoadWAV_RW (SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { int was_error; Chunk chunk; int lenread; int MS_ADPCM_encoded, IMA_ADPCM_encoded; int samplesize; /* WAV magic header */ Uint32 RIFFchunk; Uint32 wavelen; Uint32 WAVEmagic; /* FMT chunk */ WaveFMT *format = NULL; /* Make sure we are passed a valid data source */ was_error = 0; if ( src == NULL ) { was_error = 1; goto done; } /* Check the magic header */ RIFFchunk = SDL_ReadLE32(src); wavelen = SDL_ReadLE32(src); if ( wavelen == WAVE ) { /* The RIFFchunk has already been read */ WAVEmagic = wavelen; wavelen = RIFFchunk; RIFFchunk = RIFF; } else { WAVEmagic = SDL_ReadLE32(src); } if ( (RIFFchunk != RIFF) || (WAVEmagic != WAVE) ) { SDL_SetError("Unrecognized file type (not WAVE)"); was_error = 1; goto done; } /* Read the audio data format chunk */ chunk.data = NULL; do { if ( chunk.data != NULL ) { free(chunk.data); } lenread = ReadChunk(src, &chunk); if ( lenread < 0 ) { was_error = 1; goto done; } } while ( (chunk.magic == FACT) || (chunk.magic == LIST) ); /* Decode the audio data format */ format = (WaveFMT *)chunk.data; if ( chunk.magic != FMT ) { SDL_SetError("Complex WAVE files not supported"); was_error = 1; goto done; } MS_ADPCM_encoded = IMA_ADPCM_encoded = 0; switch (SDL_SwapLE16(format->encoding)) { case PCM_CODE: /* We can understand this */ break; case MS_ADPCM_CODE: /* Try to understand this */ if ( InitMS_ADPCM(format) < 0 ) { was_error = 1; goto done; } MS_ADPCM_encoded = 1; break; case IMA_ADPCM_CODE: /* Try to understand this */ if ( InitIMA_ADPCM(format) < 0 ) { was_error = 1; goto done; } IMA_ADPCM_encoded = 1; break; default: SDL_SetError("Unknown WAVE data format: 0x%.4x", SDL_SwapLE16(format->encoding)); was_error = 1; goto done; } memset(spec, 0, (sizeof *spec)); spec->freq = SDL_SwapLE32(format->frequency); switch (SDL_SwapLE16(format->bitspersample)) { case 4: if ( MS_ADPCM_encoded || IMA_ADPCM_encoded ) { spec->format = AUDIO_S16; } else { was_error = 1; } break; case 8: spec->format = AUDIO_U8; break; case 16: spec->format = AUDIO_S16; break; default: was_error = 1; break; } if ( was_error ) { SDL_SetError("Unknown %d-bit PCM data format", SDL_SwapLE16(format->bitspersample)); goto done; } spec->channels = (Uint8)SDL_SwapLE16(format->channels); spec->samples = 4096; /* Good default buffer size */ /* Read the audio data chunk */ *audio_buf = NULL; do { if ( *audio_buf != NULL ) { free(*audio_buf); } lenread = ReadChunk(src, &chunk); if ( lenread < 0 ) { was_error = 1; goto done; } *audio_len = lenread; *audio_buf = chunk.data; } while ( chunk.magic != DATA ); if ( MS_ADPCM_encoded ) { if ( MS_ADPCM_decode(audio_buf, audio_len) < 0 ) { was_error = 1; goto done; } } if ( IMA_ADPCM_encoded ) { if ( IMA_ADPCM_decode(audio_buf, audio_len) < 0 ) { was_error = 1; goto done; } } /* Don't return a buffer that isn't a multiple of samplesize */ samplesize = ((spec->format & 0xFF)/8)*spec->channels; *audio_len &= ~(samplesize-1); done: if ( format != NULL ) { free(format); } if ( freesrc && src ) { SDL_RWclose(src); } if ( was_error ) { spec = NULL; } return(spec); }
/* * convert wave to pcm data, setting size, fmt, chan, and freq. * * usually just a memcpy, but for MS_ADPCM does that too. */ void *ac_wave_to_pcm(const void *data, ALuint *size, ALushort *fmt, ALushort *chan, ALushort *freq) { ALubyte *retval; alWaveFMT_LOKI *format; Chunk riffchunk = { 0, 0, 0 }; int offset = 12; alIMAADPCM_state_LOKI ima_decoder; ALuint tempfreq; do { ReadChunk(data, &offset, &riffchunk); } while ((riffchunk.magic == WAVE) || (riffchunk.magic == RIFF)); if(riffchunk.magic != FMT) { fprintf(stderr, "ouch II magic|FMT [0x%x|0x%x]\n", riffchunk.magic, FMT); return NULL; } format = (alWaveFMT_LOKI *) riffchunk.data; /* channels */ *chan = swap16le(format->channels); /* freq */ tempfreq = swap32le(format->frequency); *freq = (ALushort) tempfreq; switch(swap16le(format->encoding)) { case PCM_CODE: switch(swap16le(format->bitspersample)) { case 8: *fmt = AUDIO_U8; break; case 16: *fmt = AUDIO_S16LSB; break; default: fprintf(stderr, "Unknown bits %d\n", swap16le(format->bitspersample)); break; } do { ReadChunk(data, &offset, &riffchunk); } while(riffchunk.magic != DATA); retval = malloc(riffchunk.length); if(retval == NULL) { return NULL; } /* FIXME: Need to convert to native format? */ #if defined(WORDS_BIGENDIAN) && DEBUG_CONVERT fprintf(stderr, "[%s:%d] do we need to convert to host native format here?\n", __FILE__, __LINE__); #endif memcpy(retval, riffchunk.data, riffchunk.length); *size = riffchunk.length; return retval; break; case MS_ADPCM_CODE: /* not possible to do an inplace conversion */ *fmt = AUDIO_S16LSB; if(InitMS_ADPCM(format) < 0) { #ifdef DEBUG fprintf(stderr, "Couldn't init MSADPCM\n"); #endif return NULL; } do { ReadChunk(data, &offset, &riffchunk); retval = riffchunk.data; } while (riffchunk.magic != DATA); if(MS_ADPCM_decode_FULL(&retval, &riffchunk.length) < 0) { #ifdef DEBUG fprintf(stderr, "Couldn't decode MS_ADPCM\n"); #endif return NULL; } *size = riffchunk.length; return retval; break; case IMA_ADPCM_CODE: /* not possible to do an inplace conversion */ *fmt = AUDIO_S16LSB; if(InitIMA_ADPCM(&ima_decoder, format) < 0) { #ifdef DEBUG_CONVERT fprintf(stderr, "Couldn't init IMA ADPCM\n"); #endif return NULL; } do { ReadChunk(data, &offset, &riffchunk); retval = riffchunk.data; } while (riffchunk.magic != DATA); if(IMA_ADPCM_decode_FULL(&ima_decoder, &retval, &riffchunk.length) < 0) { #ifdef DEBUG_CONVERT fprintf(stderr, "Couldn't decode IMA_ADPCM\n"); #endif return NULL; } *size = riffchunk.length; return retval; break; default: #ifdef DEBUG_CONVERT fprintf(stderr, "[%s:%d] unknown WAVE format 0x%x\n", __FILE__, __LINE__, *fmt); #endif break; } return NULL; }