-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
85ad7b0
commit f5ef3ea
Showing
10 changed files
with
682 additions
and
434 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#include "Audio.h" | ||
|
||
#include "Log.h" | ||
|
||
SDL_AudioDeviceID Audio::audioDeviceId = 0; | ||
std::ifstream Audio::currentAudioStream = std::ifstream(); | ||
int32_t Audio::currentAudioStreamLegth = 0; | ||
|
||
bool Audio::Initialize() | ||
{ | ||
if (IsInitialized()) return false; | ||
|
||
SDL_AudioSpec desiredAudioSpec, obtainedAudioSpec; | ||
SDL_memset(&desiredAudioSpec, 0, sizeof(desiredAudioSpec)); | ||
desiredAudioSpec.freq = WAV_FREQUENCY; | ||
desiredAudioSpec.format = WAV_FORMAT; | ||
desiredAudioSpec.channels = WAV_CHANNELS; | ||
desiredAudioSpec.samples = WAV_SAMPLES; | ||
desiredAudioSpec.callback = AudioCallback; | ||
audioDeviceId = SDL_OpenAudioDevice(NULL, 0, &desiredAudioSpec, &obtainedAudioSpec, /*SDL_AUDIO_ALLOW_FORMAT_CHANGE*/ 0); | ||
|
||
if (audioDeviceId == 0) | ||
{ | ||
Log::Print(LogTypes::Error, "Can't open audio device: %s", SDL_GetError()); | ||
return false; | ||
} | ||
else | ||
{ | ||
Log::Print(LogTypes::Info, "Audio Initialized: frequency %i, channels %u, samples %u, buffer size %u.", obtainedAudioSpec.freq, obtainedAudioSpec.channels, obtainedAudioSpec.samples, obtainedAudioSpec.size); | ||
} | ||
|
||
SDL_PauseAudioDevice(audioDeviceId, 0); | ||
|
||
return true; | ||
} | ||
|
||
void Audio::Dispose() | ||
{ | ||
StopAudio(); | ||
|
||
if (audioDeviceId > 0) | ||
{ | ||
SDL_CloseAudioDevice(audioDeviceId); | ||
audioDeviceId = 0; | ||
} | ||
} | ||
|
||
bool Audio::LoadAudioFromWAV(const std::string baseDataPath, const std::string fileName) | ||
{ | ||
if (!IsInitialized()) return false; | ||
|
||
StopAudio(); | ||
|
||
currentAudioStream = std::ifstream(baseDataPath + fileName, std::ios::binary); | ||
|
||
if (!currentAudioStream.is_open()) | ||
{ | ||
Log::Print(LogTypes::Error, "Can't load audio file: %s", SDL_GetError()); | ||
return false; | ||
} | ||
|
||
currentAudioStream.seekg(0, std::ios_base::end); | ||
currentAudioStreamLegth = static_cast<int32_t>(currentAudioStream.tellg()); | ||
|
||
// TODO: Does audio data in a WAV always start in the same offset? | ||
currentAudioStream.seekg(WAV_DATA_START_POSITION, std::ios_base::beg); | ||
|
||
Log::Print(LogTypes::Info, "Playing audio %s...", fileName.c_str()); | ||
|
||
return true; | ||
} | ||
|
||
void Audio::StopAudio() | ||
{ | ||
if (!currentAudioStream.is_open()) return; | ||
|
||
currentAudioStream.close(); | ||
currentAudioStream = std::ifstream(); | ||
currentAudioStreamLegth = 0; | ||
} | ||
|
||
void Audio::SetAudioPlaybackTime(const double elapsedTime) | ||
{ | ||
if (!IsInitialized()) return; | ||
if (!currentAudioStream.is_open()) return; | ||
|
||
int32_t samplePosition = static_cast<int32_t>(elapsedTime * WAV_FREQUENCY * WAV_FORMAT_BYTES * WAV_CHANNELS); | ||
|
||
// Make sure samplePosition is even, not odd, as audio is 16bit. | ||
samplePosition &= ~1; | ||
|
||
currentAudioStream.seekg(WAV_DATA_START_POSITION + samplePosition, std::ios_base::beg); | ||
} | ||
|
||
void Audio::AudioCallback(void* userdata, uint8_t* stream, int32_t len) | ||
{ | ||
if (currentAudioStream.is_open()) | ||
{ | ||
currentAudioStream.read((char*)stream, len); | ||
|
||
int32_t bytesRead = static_cast<int32_t>(currentAudioStream.gcount()); | ||
int32_t remainingBytes = len - bytesRead; | ||
|
||
if (remainingBytes > 0) | ||
{ | ||
SDL_memset(stream + bytesRead, 0, remainingBytes); | ||
|
||
// We have finished reading the audio file, | ||
// don't need to keep it open. | ||
|
||
currentAudioStream.close(); | ||
currentAudioStream = std::ifstream(); | ||
currentAudioStreamLegth = 0; | ||
} | ||
} | ||
else | ||
{ | ||
SDL_memset(stream, 0, len); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#pragma once | ||
|
||
#include <fstream> | ||
|
||
#include <SDL.h> | ||
|
||
// Format of game's WAV files | ||
|
||
constexpr int32_t WAV_FREQUENCY = 11025; // Hz | ||
constexpr SDL_AudioFormat WAV_FORMAT = AUDIO_S16; // 16 bits | ||
constexpr int32_t WAV_FORMAT_BYTES = 2; // 16 bits | ||
constexpr int32_t WAV_CHANNELS = 2; // Stereo | ||
constexpr int32_t WAV_SAMPLES = 256; | ||
|
||
// TODO: Does audio data in a WAV always start in the same offset? | ||
|
||
constexpr int32_t WAV_DATA_START_POSITION = 0x2c; | ||
|
||
class Audio | ||
{ | ||
private: | ||
static SDL_AudioDeviceID audioDeviceId; | ||
static std::ifstream currentAudioStream; | ||
static int32_t currentAudioStreamLegth; | ||
|
||
public: | ||
static bool Initialize(); | ||
static void Dispose(); | ||
|
||
static bool LoadAudioFromWAV(const std::string baseDataPath, const std::string fileName); | ||
static void StopAudio(); | ||
static void SetAudioPlaybackTime(const double elapsedTime); | ||
|
||
inline static bool IsInitialized() { return audioDeviceId > 0; } | ||
|
||
private: | ||
static void AudioCallback(void* userdata, uint8_t* stream, int32_t len); | ||
}; |
Oops, something went wrong.