Example #1
0
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;
    }
}
Example #2
0
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);
}
Example #3
0
/*
 * 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;
}