示例#1
0
AudioBuffer::AudioBuffer(const String &filename) {
	if (filename.ExtractExt() == "wav") {
		m_alBuffer = 0;
		File * file = new File(filename, FILE_READ);

		int32 chunkId = file->ReadInt();
		int32 riffChunkSize = file->ReadInt();
		int32 format = file->ReadInt();
		int32 subChunkId = file->ReadInt();
		int32 fmtChunkSize = file->ReadInt();
		int16 audioFormat = file->ReadInt16();
		int16 channels = file->ReadInt16();
		int32 sampleRate = file->ReadInt();
		int32 byteRate = file->ReadInt();
		int16 blockAlign = file->ReadInt16();
		int16 bitsPerSample = file->ReadInt16();
		if (fmtChunkSize > 16) {
			int16 extraParamsSize = file->ReadInt16();
			file->Seek(file->Pos() + extraParamsSize);
		}

		char text[5] = "";
		file->ReadBytes(text, 4);
		while (String(text) != "data" && !file->Eof()) {
			file->ReadBytes(text, 4);
			if (String(text) == "data")
				break;
			file->Seek(file->Pos() + 4);
		}

		int32 dataSize = file->ReadInt();
		uint32 * data = (uint32 *)malloc(dataSize);
		file->ReadBytes(data, dataSize);

		ALenum bufferFormat;
		if (bitsPerSample == 8) {
			if (channels == 1)
				bufferFormat = AL_FORMAT_MONO8;
			else
				bufferFormat = AL_FORMAT_STEREO8;
		}
		else {
			if (channels == 1)
				bufferFormat = AL_FORMAT_MONO16;
			else
				bufferFormat = AL_FORMAT_STEREO16;
		}

		alGenBuffers(1, &m_alBuffer);
		alBufferData(m_alBuffer, bufferFormat, data, dataSize, sampleRate);
		delete file;
		free(data);
	} else if (filename.ExtractExt() == "ogg") {
		stb_vorbis * file = stb_vorbis_open_filename(filename.ToCString(), nullptr, nullptr);

		if (file) {
			stb_vorbis_info info = stb_vorbis_get_info(file);
			uint32 size = stb_vorbis_stream_length_in_samples(file) * info.channels;
			int16 * buffer = (int16 *)malloc(size * sizeof(int16));
			stb_vorbis_get_samples_short_interleaved(file, info.channels, buffer, size);
			alGenBuffers(1, &m_alBuffer);
			ALenum bufferFormat;
			if (info.channels == 1)
				bufferFormat = AL_FORMAT_MONO16;
			else
				bufferFormat = AL_FORMAT_STEREO16;
			alBufferData(m_alBuffer, bufferFormat, buffer, size, info.sample_rate);
			stb_vorbis_close(file);
			free(buffer);
		}
	}
}
bool WavStream::LoadFile( const char *filename ) {
	File *file = audioFS->OpenRead( filename );
	if ( !file )
		return false;

	short formatTag;
	unsigned short channels, bitsPerSample;
	data = OG_NULL;

	try {
		uInt chunkID	= file->ReadUint();
		uInt chunkSize	= file->ReadUint();
		uInt fileType	= file->ReadUint();

		bool hasFormat = false;
		bool failed = false;
		if ( chunkID != chunkID_RIFF || fileType != fileType_WAVE )
			failed = true;

		while ( !failed && !file->Eof() ) {
			chunkID = file->ReadUint();
			chunkSize = file->ReadUint();

			switch( chunkID ) {
				case chunkID_fmt:
					formatTag	= file->ReadShort();
					channels	= file->ReadUshort();
					freq		= file->ReadUint();

					file->Seek( 6, SEEK_CUR ); // AvgBytesPerSec(4), BlockAlign(2)

					bitsPerSample = file->ReadUshort();

					if ( channels == 1 )
						format = (bitsPerSample == 8) ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16;
					else
						format = (bitsPerSample == 8) ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16;

					// Must be PCM/uncompressed
					if ( formatTag != 1 )
						failed = true;

					hasFormat = true;
					break;
				case chunkID_data:
					if ( hasFormat ) {
						outSize = dataSize = chunkSize;
						data = new byte[chunkSize];
						file->Read( data, dataSize );
						return true;
					}
					failed = true;
					break;
				default:
					// We don't need other chunks
					file->Seek( chunkSize, SEEK_CUR );
					break;
			}
		}
		file->Close();
		User::Error( ERR_BAD_FILE_FORMAT, "File is no PCM wave file.", filename );
		return false;
	}
	catch( FileReadWriteError &err ) {
		SafeDeleteArray( data );
		file->Close();
		User::Error( ERR_FILE_CORRUPT, Format("Wave: $*" ) << err.ToString(), filename );
		return false;
	}
}