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; } }