Initial OpenAL code.

This commit is contained in:
Justin Marshall
2020-06-02 12:39:34 -07:00
parent a529937ee5
commit c09d3cf3cd
17 changed files with 2889 additions and 158 deletions
+221
View File
@@ -0,0 +1,221 @@
/*
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#include "function.h"
#include "AUDIOMIX.H"
#include <AL/al.h>
#include <AL/alc.h>
ALCdevice* device = nullptr;
ALCcontext* context = nullptr;
struct AudioBuffer_t {
ALuint sourceId;
ALuint buffer;
ALsizei size;
ALsizei frequency;
ALenum format;
};
enum AudioBufferType_t {
AUDIO_BUFFER_HOUSE_NONE = 0,
AUDIO_BUFFER_HOUSE_ALIED,
AUDIO_BUFFER_HOUSE_SOVIET,
AUDIO_BUFFER_NUMTYPES
};
#define MAX_PRECACHE_AUDIO 512
AudioBuffer_t precacheAudioTable[AUDIO_BUFFER_NUMTYPES][MAX_PRECACHE_AUDIO];
struct RIFF_Header {
char chunkID[4];
long chunkSize;
char format[4];
};
struct WAVE_Format {
char subChunkID[4];
long subChunkSize;
short audioFormat;
short numChannels;
long sampleRate;
long byteRate;
short blockAlign;
short bitsPerSample;
};
struct WAVE_Data {
char subChunkID[4];
long subChunk2Size;
};
bool loadWavFile(const char* filename, AudioBuffer_t &audioBuffer) {
FILE* soundFile = NULL;
WAVE_Format wave_format;
RIFF_Header riff_header;
WAVE_Data wave_data;
unsigned char* data;
ALuint* buffer = &audioBuffer.buffer;
ALsizei* size = &audioBuffer.size;
ALsizei* frequency = &audioBuffer.frequency;
ALenum* format = &audioBuffer.format;
try {
soundFile = fopen(filename, "rb");
if (!soundFile) {
return false;
}
fread(&riff_header, sizeof(RIFF_Header), 1, soundFile);
if ((riff_header.chunkID[0] != 'R' ||
riff_header.chunkID[1] != 'I' ||
riff_header.chunkID[2] != 'F' ||
riff_header.chunkID[3] != 'F') &&
(riff_header.format[0] != 'W' ||
riff_header.format[1] != 'A' ||
riff_header.format[2] != 'V' ||
riff_header.format[3] != 'E'))
throw ("Invalid RIFF or WAVE Header");
fread(&wave_format, sizeof(WAVE_Format), 1, soundFile);
if (wave_format.subChunkID[0] != 'f' ||
wave_format.subChunkID[1] != 'm' ||
wave_format.subChunkID[2] != 't' ||
wave_format.subChunkID[3] != ' ')
throw ("Invalid Wave Format");
if (wave_format.subChunkSize > 16)
fseek(soundFile, sizeof(short), SEEK_CUR);
fread(&wave_data, sizeof(WAVE_Data), 1, soundFile);
if (wave_data.subChunkID[0] != 'd' ||
wave_data.subChunkID[1] != 'a' ||
wave_data.subChunkID[2] != 't' ||
wave_data.subChunkID[3] != 'a')
throw ("Invalid data header");
data = new unsigned char[wave_data.subChunk2Size];
if (!fread(data, wave_data.subChunk2Size, 1, soundFile))
throw ("error loading WAVE data into struct!");
*size = wave_data.subChunk2Size;
*frequency = wave_format.sampleRate;
if (wave_format.numChannels == 1) {
if (wave_format.bitsPerSample == 8)
*format = AL_FORMAT_MONO8;
else if (wave_format.bitsPerSample == 16)
*format = AL_FORMAT_MONO16;
}
else if (wave_format.numChannels == 2) {
if (wave_format.bitsPerSample == 8)
*format = AL_FORMAT_STEREO8;
else if (wave_format.bitsPerSample == 16)
*format = AL_FORMAT_STEREO16;
}
alGenBuffers(1, buffer);
alBufferData(*buffer, *format, (void*)data,
*size, *frequency);
fclose(soundFile);
alGenSources(1, &audioBuffer.sourceId);
alSourcei(audioBuffer.sourceId, AL_BUFFER, *buffer);
alSource3f(audioBuffer.sourceId, AL_POSITION, 0.0f, 0.0f, 0.0f);
return true;
}
catch (char* error) {
if (soundFile != NULL)
fclose(soundFile);
return false;
}
}
/*
=============
AudMix_IsEnabled
=============
*/
bool AudMix_IsEnabled(void) {
return device != NULL && context != NULL;
}
/*
=============
AudMix_Init
=============
*/
void AudMix_Init(void) {
// Open up the audio device.
device = alcOpenDevice(NULL);
if (!device) {
return;
}
context = alcCreateContext(device, NULL);
if (!alcMakeContextCurrent(context)) {
return;
}
// Precache all of the audio.
for (int i = 0; i < VOC_COUNT; i++) {
char expandedFilePath[512];
sprintf(expandedFilePath, "sound/%s.wav", GetEffectFileName(i));
if (!loadWavFile(expandedFilePath, precacheAudioTable[AUDIO_BUFFER_HOUSE_NONE][i]))
{
sprintf(expandedFilePath, "sound/alied/%s.wav", GetEffectFileName(i));
if (!loadWavFile(expandedFilePath, precacheAudioTable[AUDIO_BUFFER_HOUSE_ALIED][i])) {
// assert(!"failed to load audio!");
}
sprintf(expandedFilePath, "sound/russian/%s.wav", GetEffectFileName(i));
if (!loadWavFile(expandedFilePath, precacheAudioTable[AUDIO_BUFFER_HOUSE_SOVIET][i])) {
//assert(!"failed to load audio!");
}
}
}
alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
}
void On_Sound_Effect(int sound_index, int variation, COORDINATE coord, int house)
{
// MBL 06.17.2019
int voc = sound_index;
if (voc == VOC_NONE)
{
return;
}
alSourcePlay(precacheAudioTable[AUDIO_BUFFER_HOUSE_NONE][sound_index].sourceId);
}
// void On_Speech(int speech_index) // MBL 02.06.2020
void On_Speech(int speech_index, HouseClass* house)
{
// DLLExportClass::On_Speech(PlayerPtr, speech_index); // MBL 02.06.2020
//if (house == NULL) {
// DLLExportClass::On_Speech(PlayerPtr, speech_index);
//}
//else
//{
// DLLExportClass::On_Speech(house, speech_index);
//}
}