2014-06-22 15:02:04 +00:00
|
|
|
#pragma once
|
|
|
|
|
2021-02-16 02:04:11 +00:00
|
|
|
#include <atomic>
|
2020-08-02 17:56:57 +00:00
|
|
|
#include <mutex>
|
2021-02-16 02:04:11 +00:00
|
|
|
#include <string>
|
2020-08-02 19:55:46 +00:00
|
|
|
#include <vector>
|
2014-06-22 15:02:04 +00:00
|
|
|
|
2021-05-05 23:31:38 +00:00
|
|
|
#include "Common/File/Path.h"
|
2020-10-04 18:48:47 +00:00
|
|
|
#include "Common/UI/Root.h"
|
2020-08-02 17:44:48 +00:00
|
|
|
|
2020-08-03 09:29:54 +00:00
|
|
|
class AT3PlusReader;
|
2020-08-02 19:55:46 +00:00
|
|
|
|
2023-07-12 13:37:16 +00:00
|
|
|
struct Sample {
|
2024-04-09 15:29:57 +00:00
|
|
|
// data must be new[]-ed.
|
2023-07-16 13:04:21 +00:00
|
|
|
Sample(int16_t *data, int channels, int length, int rateInHz) : channels_(channels), data_(data), length_(length), rateInHz_(rateInHz) {}
|
2023-07-12 13:37:16 +00:00
|
|
|
~Sample() {
|
|
|
|
delete[] data_;
|
|
|
|
}
|
|
|
|
int16_t *data_;
|
2023-07-16 13:04:21 +00:00
|
|
|
int length_; // stereo or mono samples.
|
2023-07-12 15:54:41 +00:00
|
|
|
int rateInHz_; // sampleRate
|
2023-07-16 13:04:21 +00:00
|
|
|
int channels_;
|
2023-07-16 10:15:44 +00:00
|
|
|
|
|
|
|
static Sample *Load(const std::string &path);
|
2023-07-12 13:37:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Mixer for things played on top of everything.
|
|
|
|
class SoundEffectMixer {
|
|
|
|
public:
|
2024-10-11 09:31:17 +00:00
|
|
|
void Init();
|
2023-07-12 13:37:16 +00:00
|
|
|
void Mix(int16_t *buffer, int sz, int sampleRateHz);
|
2023-07-12 17:18:56 +00:00
|
|
|
void Play(UI::UISound sfx, float volume);
|
2023-07-12 13:37:16 +00:00
|
|
|
|
2023-07-16 10:15:44 +00:00
|
|
|
void UpdateSample(UI::UISound sound, Sample *sample);
|
|
|
|
void LoadDefaultSample(UI::UISound sound);
|
|
|
|
|
2023-07-12 13:37:16 +00:00
|
|
|
std::vector<std::unique_ptr<Sample>> samples_;
|
|
|
|
|
|
|
|
struct PlayInstance {
|
|
|
|
UI::UISound sound;
|
2023-07-12 15:54:41 +00:00
|
|
|
int64_t offset; // 32.32 fixed point
|
2023-07-12 13:37:16 +00:00
|
|
|
int volume; // 0..255
|
|
|
|
bool done;
|
|
|
|
};
|
|
|
|
|
2024-10-11 09:31:17 +00:00
|
|
|
// This can be called on a thread.
|
|
|
|
void LoadSamplesOnThread();
|
2023-07-16 10:15:44 +00:00
|
|
|
private:
|
2023-07-12 13:37:16 +00:00
|
|
|
std::mutex mutex_;
|
2023-07-12 18:09:52 +00:00
|
|
|
std::vector<PlayInstance> queue_;
|
2023-07-12 13:37:16 +00:00
|
|
|
std::vector<PlayInstance> plays_;
|
|
|
|
};
|
|
|
|
|
2020-08-02 17:44:48 +00:00
|
|
|
class BackgroundAudio {
|
|
|
|
public:
|
2020-08-02 17:56:57 +00:00
|
|
|
BackgroundAudio();
|
|
|
|
~BackgroundAudio();
|
|
|
|
|
2021-05-05 23:31:38 +00:00
|
|
|
void SetGame(const Path &path);
|
2020-08-02 17:44:48 +00:00
|
|
|
void Update();
|
2023-03-24 11:00:36 +00:00
|
|
|
bool Play();
|
2020-08-02 19:55:46 +00:00
|
|
|
|
2023-07-12 13:37:16 +00:00
|
|
|
SoundEffectMixer &SFX() {
|
|
|
|
return sfxMixer_;
|
|
|
|
}
|
2020-08-02 19:55:46 +00:00
|
|
|
|
2020-08-02 17:44:48 +00:00
|
|
|
private:
|
2021-02-16 02:04:11 +00:00
|
|
|
void Clear(bool hard);
|
|
|
|
|
2020-08-02 17:56:57 +00:00
|
|
|
enum {
|
2023-12-04 12:22:32 +00:00
|
|
|
// 0.5 ms buffer at 44.1 khz should be enough.
|
|
|
|
BUFSIZE = 22050,
|
2020-08-02 17:56:57 +00:00
|
|
|
};
|
|
|
|
|
2020-08-03 09:29:54 +00:00
|
|
|
std::mutex mutex_;
|
2021-05-05 23:31:38 +00:00
|
|
|
Path bgGamePath_;
|
2021-02-16 02:04:11 +00:00
|
|
|
std::atomic<bool> sndLoadPending_;
|
2020-08-03 09:29:54 +00:00
|
|
|
int playbackOffset_ = 0;
|
2023-07-12 13:37:16 +00:00
|
|
|
AT3PlusReader *at3Reader_ = nullptr;
|
2020-08-03 09:29:54 +00:00
|
|
|
double gameLastChanged_ = 0.0;
|
|
|
|
double lastPlaybackTime_ = 0.0;
|
2020-08-02 17:56:57 +00:00
|
|
|
int *buffer = nullptr;
|
2020-08-03 09:29:54 +00:00
|
|
|
bool fadingOut_ = true;
|
|
|
|
float volume_ = 0.0f;
|
|
|
|
float delta_ = -0.0001f;
|
2023-07-12 13:37:16 +00:00
|
|
|
SoundEffectMixer sfxMixer_;
|
2020-08-02 17:44:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
extern BackgroundAudio g_BackgroundAudio;
|