⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_wave.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 2 页
字号:
		state->index = 0;
	}

	/* Clamp output sample */
	if ( state->sample > max_audioval ) {
		state->sample = max_audioval;
	} else
	if ( state->sample < min_audioval ) {
		state->sample = min_audioval;
	}
	return(state->sample);
}

/* Fill the decode buffer with a channel block of data (8 samples) */
static void Fill_IMA_ADPCM_block(Uint8 *decoded, Uint8 *encoded,
	int channel, int numchannels, struct IMA_ADPCM_decodestate *state)
{
	int i;
	Sint8 nybble;
	Sint32 new_sample;

	decoded += (channel * 2);
	for ( i=0; i<4; ++i ) {
		nybble = (*encoded)&0x0F;
		new_sample = IMA_ADPCM_nibble(state, nybble);
		decoded[0] = new_sample&0xFF;
		new_sample >>= 8;
		decoded[1] = new_sample&0xFF;
		decoded += 2 * numchannels;

		nybble = (*encoded)>>4;
		new_sample = IMA_ADPCM_nibble(state, nybble);
		decoded[0] = new_sample&0xFF;
		new_sample >>= 8;
		decoded[1] = new_sample&0xFF;
		decoded += 2 * numchannels;

		++encoded;
	}
}

static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
{
	struct IMA_ADPCM_decodestate *state;
	Uint8 *freeable, *encoded, *decoded;
	Sint32 encoded_len, samplesleft;
	int c, channels;

	/* Check to make sure we have enough variables in the state array */
	channels = IMA_ADPCM_state.wavefmt.channels;
	if ( channels > NELEMS(IMA_ADPCM_state.state) ) {
		SDL_SetError("IMA ADPCM decoder can only handle %d channels",
						NELEMS(IMA_ADPCM_state.state));
		return(-1);
	}
	state = IMA_ADPCM_state.state;

	/* Allocate the proper sized output buffer */
	encoded_len = *audio_len;
	encoded = *audio_buf;
	freeable = *audio_buf;
	*audio_len = (encoded_len/IMA_ADPCM_state.wavefmt.blockalign) * 
				IMA_ADPCM_state.wSamplesPerBlock*
				IMA_ADPCM_state.wavefmt.channels*sizeof(Sint16);
	*audio_buf = (Uint8 *)malloc(*audio_len);
	if ( *audio_buf == NULL ) {
		SDL_Error(SDL_ENOMEM);
		return(-1);
	}
	decoded = *audio_buf;

	/* Get ready... Go! */
	while ( encoded_len >= IMA_ADPCM_state.wavefmt.blockalign ) {
		/* Grab the initial information for this block */
		for ( c=0; c<channels; ++c ) {
			/* Fill the state information for this block */
			state[c].sample = ((encoded[1]<<8)|encoded[0]);
			encoded += 2;
			if ( state[c].sample & 0x8000 ) {
				state[c].sample -= 0x10000;
			}
			state[c].index = *encoded++;
			/* Reserved byte in buffer header, should be 0 */
			if ( *encoded++ != 0 ) {
				/* Uh oh, corrupt data?  Buggy code? */;
			}

			/* Store the initial sample we start with */
			decoded[0] = state[c].sample&0xFF;
			decoded[1] = state[c].sample>>8;
			decoded += 2;
		}

		/* Decode and store the other samples in this block */
		samplesleft = (IMA_ADPCM_state.wSamplesPerBlock-1)*channels;
		while ( samplesleft > 0 ) {
			for ( c=0; c<channels; ++c ) {
				Fill_IMA_ADPCM_block(decoded, encoded,
						c, channels, &state[c]);
				encoded += 4;
				samplesleft -= 8;
			}
			decoded += (channels * 8 * 2);
		}
		encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
	}
	free(freeable);
	return(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);
}

/* Since the WAV memory is allocated in the shared library, it must also
   be freed here.  (Necessary under Win32, VC++)
 */
void SDL_FreeWAV(Uint8 *audio_buf)
{
	if ( audio_buf != NULL ) {
		free(audio_buf);
	}
}

static int ReadChunk(SDL_RWops *src, Chunk *chunk)
{
	chunk->magic	= SDL_ReadLE32(src);
	chunk->length	= SDL_ReadLE32(src);
	chunk->data = (Uint8 *)malloc(chunk->length);
	if ( chunk->data == NULL ) {
		SDL_Error(SDL_ENOMEM);
		return(-1);
	}
	if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) {
		SDL_Error(SDL_EFREAD);
		free(chunk->data);
		return(-1);
	}
	return(chunk->length);
}

#endif /* ENABLE_FILE */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -