|
|
@@ -28,7 +28,7 @@ AudioBuffer::~AudioBuffer()
|
|
|
|
|
|
if (_alBuffer)
|
|
|
{
|
|
|
- alDeleteBuffers(1, &_alBuffer);
|
|
|
+ AL_CHECK( alDeleteBuffers(1, &_alBuffer) );
|
|
|
_alBuffer = 0;
|
|
|
}
|
|
|
}
|
|
|
@@ -43,6 +43,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
|
|
|
for (unsigned int i = 0; i < bufferCount; i++)
|
|
|
{
|
|
|
buffer = __buffers[i];
|
|
|
+ GP_ASSERT(buffer);
|
|
|
if (buffer->_filePath.compare(path) == 0)
|
|
|
{
|
|
|
buffer->addRef();
|
|
|
@@ -51,15 +52,13 @@ AudioBuffer* AudioBuffer::create(const char* path)
|
|
|
}
|
|
|
|
|
|
ALuint alBuffer;
|
|
|
- ALCenum al_error;
|
|
|
|
|
|
// Load audio data into a buffer.
|
|
|
- alGenBuffers(1, &alBuffer);
|
|
|
- al_error = alGetError();
|
|
|
- if (al_error != AL_NO_ERROR)
|
|
|
+ AL_CHECK( alGenBuffers(1, &alBuffer) );
|
|
|
+ if (AL_LAST_ERROR())
|
|
|
{
|
|
|
- GP_ERROR("AudioBuffer alGenBuffers AL error: %d", al_error);
|
|
|
- alDeleteBuffers(1, &alBuffer);
|
|
|
+ GP_ERROR("Failed to create OpenAL buffer; alGenBuffers error: %d", AL_LAST_ERROR());
|
|
|
+ AL_CHECK( alDeleteBuffers(1, &alBuffer) );
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
@@ -67,7 +66,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
|
|
|
FILE* file = FileSystem::openFile(path, "rb");
|
|
|
if (!file)
|
|
|
{
|
|
|
- GP_ERROR("Invalid audio buffer file: %s", path);
|
|
|
+ GP_ERROR("Failed to load audio file %s.", path);
|
|
|
goto cleanup;
|
|
|
}
|
|
|
|
|
|
@@ -75,7 +74,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
|
|
|
char header[12];
|
|
|
if (fread(header, 1, 12, file) != 12)
|
|
|
{
|
|
|
- GP_ERROR("Invalid audio buffer file: %s", path);
|
|
|
+ GP_ERROR("Invalid header for audio file %s.", path);
|
|
|
goto cleanup;
|
|
|
}
|
|
|
|
|
|
@@ -99,6 +98,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
|
|
|
else
|
|
|
{
|
|
|
GP_ERROR("Unsupported audio file: %s", path);
|
|
|
+ goto cleanup;
|
|
|
}
|
|
|
|
|
|
fclose(file);
|
|
|
@@ -115,17 +115,21 @@ cleanup:
|
|
|
if (file)
|
|
|
fclose(file);
|
|
|
if (alBuffer)
|
|
|
- alDeleteBuffers(1, &alBuffer);
|
|
|
+ AL_CHECK( alDeleteBuffers(1, &alBuffer) );
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
|
|
|
{
|
|
|
+ GP_ASSERT(file);
|
|
|
unsigned char stream[12];
|
|
|
|
|
|
// Verify the wave fmt magic value meaning format.
|
|
|
if (fread(stream, 1, 8, file) != 8 || memcmp(stream, "fmt ", 4) != 0 )
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to verify the magic value for the wave file format.");
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
unsigned int section_size;
|
|
|
section_size = stream[7]<<24;
|
|
|
@@ -136,21 +140,27 @@ bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
|
|
|
// Check for a valid pcm format.
|
|
|
if (fread(stream, 1, 2, file) != 2 || stream[1] != 0 || stream[0] != 1)
|
|
|
{
|
|
|
- GP_ERROR("Unsupported audio file, not PCM format.");
|
|
|
+ GP_ERROR("Unsupported audio file format (must be a valid PCM format).");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- // Get the channel count (16-bit little-endian)
|
|
|
+ // Get the channel count (16-bit little-endian).
|
|
|
int channels;
|
|
|
if (fread(stream, 1, 2, file) != 2)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read the wave file's channel count.");
|
|
|
return false;
|
|
|
+ }
|
|
|
channels = stream[1]<<8;
|
|
|
channels |= stream[0];
|
|
|
|
|
|
- // Get the sample frequency (32-bit little-endian)
|
|
|
+ // Get the sample frequency (32-bit little-endian).
|
|
|
ALuint frequency;
|
|
|
if (fread(stream, 1, 4, file) != 4)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read the wave file's sample frequency.");
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
frequency = stream[3]<<24;
|
|
|
frequency |= stream[2]<<16;
|
|
|
@@ -161,12 +171,18 @@ bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
|
|
|
// We don't need that info, so just read and ignore it.
|
|
|
// We could use this later if we need to know the duration.
|
|
|
if (fread(stream, 1, 6, file) != 6)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read past the wave file's block size and bytes-per-second.");
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
- // Get the bit depth (16-bit little-endian)
|
|
|
+ // Get the bit depth (16-bit little-endian).
|
|
|
int bits;
|
|
|
if (fread(stream, 1, 2, file) != 2)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read the wave file's bit depth.");
|
|
|
return false;
|
|
|
+ }
|
|
|
bits = stream[1]<<8;
|
|
|
bits |= stream[0];
|
|
|
|
|
|
@@ -188,68 +204,91 @@ bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- GP_ERROR("Incompatible format: (%d, %d)", channels, bits);
|
|
|
+ GP_ERROR("Incompatible wave file format: (%d, %d)", channels, bits);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- // Check against the size of the format header as there may be more data that we need to read
|
|
|
+ // Check against the size of the format header as there may be more data that we need to read.
|
|
|
if (section_size > 16)
|
|
|
{
|
|
|
unsigned int length = section_size - 16;
|
|
|
|
|
|
- // extension size is 2 bytes
|
|
|
+ // Extension size is 2 bytes.
|
|
|
if (fread(stream, 1, length, file) != length)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read extension size from wave file.");
|
|
|
return false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ // Read in the type of the next section of the file.
|
|
|
if (fread(stream, 1, 4, file) != 4)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read next section type (fact or data) from wave file.");
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
- // read the next chunk, could be fact section or the data section
|
|
|
+ // Read the fact section if it is there.
|
|
|
if (memcmp(stream, "fact", 4) == 0)
|
|
|
{
|
|
|
if (fread(stream, 1, 4, file) != 4)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read fact section size from wave file.");
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
section_size = stream[3]<<24;
|
|
|
section_size |= stream[2]<<16;
|
|
|
section_size |= stream[1]<<8;
|
|
|
section_size |= stream[0];
|
|
|
|
|
|
- // read in the rest of the fact section
|
|
|
+ // Read in the fact section.
|
|
|
if (fread(stream, 1, section_size, file) != section_size)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read fact section from wave file.");
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
+ // Read in the type of the next section of the file.
|
|
|
if (fread(stream, 1, 4, file) != 4)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read next section type (should be data) from wave file.");
|
|
|
return false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // should now be the data section which holds the decoded sample data
|
|
|
+ // Should now be the data section which holds the decoded sample data.
|
|
|
if (memcmp(stream, "data", 4) != 0)
|
|
|
{
|
|
|
- GP_ERROR("WAV file has no data.");
|
|
|
+ GP_ERROR("Failed to load wave file; file appears to have no data.");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// Read how much data is remaining and buffer it up.
|
|
|
unsigned int dataSize;
|
|
|
- fread(&dataSize, sizeof(int), 1, file);
|
|
|
+ if (fread(&dataSize, sizeof(int), 1, file) != 1)
|
|
|
+ {
|
|
|
+ GP_ERROR("Failed to read size of data section from wave file.");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
char* data = new char[dataSize];
|
|
|
if (fread(data, sizeof(char), dataSize, file) != dataSize)
|
|
|
{
|
|
|
- GP_ERROR("WAV file missing data.");
|
|
|
+ GP_ERROR("Failed to load wave file; file is missing data.");
|
|
|
SAFE_DELETE_ARRAY(data);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- alBufferData(buffer, format, data, dataSize, frequency);
|
|
|
+ AL_CHECK( alBufferData(buffer, format, data, dataSize, frequency) );
|
|
|
SAFE_DELETE_ARRAY(data);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
|
|
|
{
|
|
|
+ GP_ASSERT(file);
|
|
|
+
|
|
|
OggVorbis_File ogg_file;
|
|
|
vorbis_info* info;
|
|
|
ALenum format;
|
|
|
@@ -262,18 +301,18 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
|
|
|
if ((result = ov_open(file, &ogg_file, NULL, 0)) < 0)
|
|
|
{
|
|
|
fclose(file);
|
|
|
- GP_ERROR("Could not open Ogg stream.");
|
|
|
+ GP_ERROR("Failed to open ogg file.");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
info = ov_info(&ogg_file, -1);
|
|
|
-
|
|
|
+ GP_ASSERT(info);
|
|
|
if (info->channels == 1)
|
|
|
format = AL_FORMAT_MONO16;
|
|
|
else
|
|
|
format = AL_FORMAT_STEREO16;
|
|
|
|
|
|
- // size = #samples * #channels * 2 (for 16 bit)
|
|
|
+ // size = #samples * #channels * 2 (for 16 bit).
|
|
|
unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
|
|
|
char* data = new char[data_size];
|
|
|
|
|
|
@@ -287,7 +326,7 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
|
|
|
else if (result < 0)
|
|
|
{
|
|
|
SAFE_DELETE_ARRAY(data);
|
|
|
- GP_ERROR("OGG file missing data.");
|
|
|
+ GP_ERROR("Failed to read ogg file; file is missing data.");
|
|
|
return false;
|
|
|
}
|
|
|
else
|
|
|
@@ -299,16 +338,16 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
|
|
|
if (size == 0)
|
|
|
{
|
|
|
SAFE_DELETE_ARRAY(data);
|
|
|
- GP_ERROR("Unable to read OGG data.");
|
|
|
+ GP_ERROR("Filed to read ogg file; unable to read any data.");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- alBufferData(buffer, format, data, data_size, info->rate);
|
|
|
+ AL_CHECK( alBufferData(buffer, format, data, data_size, info->rate) );
|
|
|
|
|
|
SAFE_DELETE_ARRAY(data);
|
|
|
ov_clear(&ogg_file);
|
|
|
|
|
|
- // ov_clear actually closes the file pointer as well
|
|
|
+ // ov_clear actually closes the file pointer as well.
|
|
|
file = 0;
|
|
|
|
|
|
return true;
|