You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
VirusAttack/olcCodeJam2023Entry/olcPGEX_AudioSource.h

278 lines
7.8 KiB

/*
olcPGEX_AudioSource.h
+-------------------------------------------------------------+
| OneLoneCoder Pixel Game Engine Extension |
| AudioSource v1.0 |
+-------------------------------------------------------------+
What is this?
~~~~~~~~~~~~~
This is an extension to the olcPixelGameEngine v2.16 and above.
It is to be used in conjunction with olcPGEX_AudioListener.h.
A detailed description and instructions can be found in that
header file, please refer to it instead :-)
Enjoy!
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2019 OneLoneCoder.com
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions or derivations of source code must retain the above
copyright notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce
the above copyright notice. This list of conditions and the following
disclaimer must be reproduced in the documentation and/or other
materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Author
~~~~~~
Justin Richards
*/
#ifndef OLC_PGEX_AUDIO_SOURCE
#define OLC_PGEX_AUDIO_SOURCE
#pragma once
#include "olcPGEX_AudioListener.h"
class olcPGEX_AudioSource : public olc::PGEX
{
public:
// Pointer to the Audio Listener for this object
olcPGEX_AudioListener* AL=nullptr;
// Handle for this particular copy of the sound
int handle = 255;
// Maximum copies of this sound allowed for this audio source
//const int nMaxSamples = 4;
//int nSampleHandles[4] = { 255, 255, 255, 255 };
// Audio Sample ID used to locate which sound to play
int nID;
// Convenient BOOL to determine playback status
bool bIsPlaying = false;
// Current Playback Speed
float fPlaySpeed = 1.0f;
// Volume
float fVolume = 1.0f;
float fMinVolume = 0.0f;
float fMaxVolume = 1.0f;
// Does the Audio Sample Loop?
bool bLooping = false;
// Paused status
bool bPaused = false;
// Object position, used for calculating volume
olc::vf2d pos = { 0.0f, 0.0f };
// Instruct Audio Listener to load this sound (if not loaded already)
void LoadAudioSample(int ID, const char* fileName);
int PlayCentered(float speed = 1.0f, float vol = 1.0f, bool looping = false, bool paused = false,bool bgm=false);
// Play the Audio Sample, with given parameters
int Play(vf2d pos, float speed = 1.0f, float vol = 1.0f, bool looping = false, bool paused = false);
// Pause or Un-Pause - maintains the playback position and handle
void Pause(bool pauseState = true);
// Stop - playback position and handle will be lost
void Stop();
void Stop(int handle);
// Audio Modulation - control the speed of playback
void ModulateAudio(float minPlaySpeed, float maxPlaySpeed, float modulation, bool precise = false, bool deferred = false);
// Adjust Volume
void SetVolume(float vol, float minVol = 0.0f, float maxVol = 1.0f);
void SetVolume(int handle,float vol);
// Set Default Parameters
void SetDefaults(float speed, float vol, float minVol, float maxVol, bool looping);
};
#ifdef AUDIO_SOURCE_IMPLEMENTATION
#undef AUDIO_SOURCE_IMPLEMENTATION
void olcPGEX_AudioSource::LoadAudioSample(int ID, const char* fileName)
{
// Link the IDs together
nID = ID;
// Call the Audio Listener to load the sample
AL->LoadAudioSample(ID, fileName);
}
int olcPGEX_AudioSource::PlayCentered(float speed, float vol, bool looping, bool paused,bool bgm)
{
if(bgm&&!AL->bMusicOn)return -1;
if(!bgm&&!AL->bSoundOn)return -1;
// Set parameters
fPlaySpeed = speed;
fVolume = vol;
bLooping = looping;
bPaused = paused;
this->pos = pos;
// Assign a handle to this instance of the sound we are about to play
handle = AL->soloud.play(*AL->GetAudioSampleByID(nID)->wav, fVolume, 0.0f, bPaused);
// Set speed and looping
AL->soloud.setRelativePlaySpeed(handle, fPlaySpeed);
AL->soloud.setLooping(handle, looping);
// Update Play status
bIsPlaying = true;
return handle;
}
int olcPGEX_AudioSource::Play(vf2d pos, float speed, float vol, bool looping, bool paused)
{
if(!AL->bSoundOn||isnan(pos.x)||isnan(pos.y))return -1;
// Set parameters
fPlaySpeed = speed;
fVolume = vol*std::max(0.f,abs(1-std::min(1.0f,(AL->GetDistance(pos)/1024.f))));
bLooping = looping;
bPaused = paused;
this->pos = pos;
// Assign a handle to this instance of the sound we are about to play
handle = AL->soloud.play(*AL->GetAudioSampleByID(nID)->wav, fVolume, 0.0f, bPaused);
AL->handles.push_back({pos,vol,handle});
// Set speed and looping
AL->soloud.setRelativePlaySpeed(handle, fPlaySpeed);
AL->soloud.setLooping(handle, looping);
AL->soloud.setPan(handle,std::clamp((pos.x-AL->vecPos.x)/1024,-1.f,1.f));
// Update Play status
bIsPlaying = true;
return handle;
}
void olcPGEX_AudioSource::Pause(bool pauseState)
{
// Use the Audio Listener to pause or un-pause the sound as neccessary
AL->soloud.setPause(handle, pauseState);
// Update Play status
bIsPlaying = !pauseState;
}
void olcPGEX_AudioSource::Stop(int handle)
{
// Use the Audio Listener to stop the sound
if(handle!=-1){
AL->soloud.stop(handle);
}
}
void olcPGEX_AudioSource::Stop()
{
// Use the Audio Listener to stop the sound
AL->soloud.stop(handle);
// The current handle will now point to nothing, so we set it to MAX so we can test for validity if need be
handle = 255;
// Update Play status
bIsPlaying = false;
}
void olcPGEX_AudioSource::ModulateAudio(float minPlaySpeed, float maxPlaySpeed, float modulation, bool precise, bool deferred)
{
// Apply the modulation
if (precise)
fPlaySpeed = modulation;
else
fPlaySpeed += modulation;
// Adjust the play speed to keep it within range
if (fPlaySpeed < minPlaySpeed) fPlaySpeed = minPlaySpeed;
else if (fPlaySpeed > maxPlaySpeed) fPlaySpeed = maxPlaySpeed;
// If multiple adjustments to the playback speed are required, then the Audio Listener update itself can be
// deferred until the very last adjustment is made... A small optimisation
if (!deferred)
AL->soloud.setRelativePlaySpeed(handle, fPlaySpeed);
}
void olcPGEX_AudioSource::SetVolume(int handle,float vol)
{
// Set volume
fVolume = vol;
// Instruct the Audio Listener to apply the volume change
AL->soloud.setVolume(handle, fVolume);
}
void olcPGEX_AudioSource::SetVolume(float vol, float minVol, float maxVol)
{
// Set volume
fVolume = vol;
// Clamp volume withing set bounds
if (fVolume < minVol)
fVolume = minVol;
else if (fVolume > maxVol)
fVolume = maxVol;
// Instruct the Audio Listener to apply the volume change
AL->soloud.setVolume(handle, fVolume);
}
void olcPGEX_AudioSource::SetDefaults(float speed, float vol, float minVol, float maxVol, bool looping)
{
// Set defaults for this particular Audio Source
fPlaySpeed = speed;
fVolume = vol;
fMinVolume = minVol;
fMaxVolume = maxVol;
bLooping = looping;
}
#endif // AUDIO_SOURCE_IMPLEMENTATION
#endif
typedef olcPGEX_AudioSource Audio;