More minor things.

This commit is contained in:
2024-09-06 12:00:52 -04:00
parent 78ee29288b
commit dfaf7150ea
3 changed files with 85 additions and 14 deletions

View File

@@ -17,8 +17,12 @@
#include <ReMixer/ReMixer.h>
#include <iterator>
#include <vorbis/vorbisfile.h>
#include <algorithm>
int mix(int a, int b);
namespace ReMixer {
// TODO: Implement support for loading Linear-PCM if necessary.
// TODO: Correctly handle different 'sample-depths'. PCM Samples can be encoded at 8, 16, 20, or 24 bits-per-sample.
@@ -26,6 +30,9 @@ namespace ReMixer {
class Sound {
public:
/// The default constructor for a Sound object is intentionally left undefined.
/// It is intended that you use the static constructors below to load Sound objects.
Sound() = default;
@@ -35,7 +42,7 @@ namespace ReMixer {
/// @param file_name The full path relative to the executable in which the file is located.
/// @see https://en.wikipedia.org/wiki/Vorbis
/// @see LoadOGGVorbisFile().
static Sound FromOGGVorbisFile(const std::filesystem::path& file_name);
static Sound FromOGGVorbisFile(const std::filesystem::path &file_name);
/// Returns a sound object loaded from a file containing raw PCM sound data in binary form.
/// @param file_name The full path relative to the executable in which the file is located.
@@ -43,34 +50,38 @@ namespace ReMixer {
/// @param streamMode An enum representing the number of channels.
/// @see https://en.wikipedia.org/wiki/Pulse-code_modulation.
/// @see FromPCMBuffer(), LoadPCMFile(), enum StreamMode.
static Sound FromPCMFile(const std::filesystem::path& file_name, uint sampleRate = 44.1_kHz, StreamMode streamMode = StreamMode::STEREO);
static Sound FromPCMFile(const std::filesystem::path &file_name, uint sampleRate = 44.1_kHz,
StreamMode streamMode = StreamMode::STEREO);
/// Returns a sound object loaded from a byte-buffer containing raw PCM sound data.
/// @param buffer The byte buffer that will be copied into this sound object.
/// @param sampleRate A uint that indicates the samples-per-second of the sound data.
/// @param streamMode An enum representing the number of channels.
/// @see https://en.wikipedia.org/wiki/Pulse-code_modulation.
static Sound FromPCMBuffer(std::vector<char> buffer, uint sampleRate = 44.1_kHz, StreamMode streamMode = StreamMode::STEREO);
static Sound
FromPCMBuffer(std::vector<char> buffer, uint sampleRate = 44.1_kHz, StreamMode streamMode = StreamMode::STEREO);
/// Fills this sound instance with data from a file encoded with OGG vorbis, usually with an .ogg extension.
/// @param file_name The full path relative to the executable in which the file is located.
/// @see https://en.wikipedia.org/wiki/Vorbis
/// @see FromOGGVorbisFile().
void LoadOGGVorbisFile(const std::filesystem::path& file_name);
void LoadOGGVorbisFile(const std::filesystem::path &file_name);
/// Fills this sound instance with data from a file containing raw PCM sound data.
/// @param file_name The full path relative to the executable in which the file is located.
/// @param sampleRate A uint that indicates the samples-per-second of the sound data.
/// @param streamMode An enum representing the number of channels.
/// @see https://en.wikipedia.org/wiki/Pulse-code_modulation.
void LoadPCMFile(const std::filesystem::path& file_name, uint sampleRate = 44.1_kHz, StreamMode streamMode = StreamMode::STEREO);
void LoadPCMFile(const std::filesystem::path &file_name, uint sampleRate = 44.1_kHz,
StreamMode streamMode = StreamMode::STEREO);
/// Fills this sound instance with data from a byte-buffer containing raw PCM sound data.
/// @param buffer The byte buffer that will be copied into this sound object.
/// @param sampleRate A uint that indicates the samples-per-second of the sound data.
/// @param streamMode An enum representing the number of channels.
/// @see https://en.wikipedia.org/wiki/Pulse-code_modulation.
void LoadPCMBuffer(std::vector<char> buffer, uint sampleRate = 44.1_kHz, StreamMode streamMode = StreamMode::STEREO);
void
LoadPCMBuffer(std::vector<char> buffer, uint sampleRate = 44.1_kHz, StreamMode streamMode = StreamMode::STEREO);
/// Returns the sample count of the sound.
uint SampleCount() const;;
@@ -81,14 +92,29 @@ namespace ReMixer {
/// Returns the samples-per-second of this sound.
uint SampleRate() const;
/// Returns an enumeration indicating the channel mode of the sound resource (MONO, STEREO).
StreamMode GetStreamMode() const;
/// Returns the number of separate channels this sound resource contains.
uint Channels() const;
/// Returns the time length, in seconds, of this sound resource.
float PlaybackLength();
/// Returns a pointer to the beginning of the audio data
char* ptr() { return audio_data.data();}
[[nodiscard]] const char* ptr() const { return audio_data.data();}
/// Returns a pointer to the beginning of the audio data buffer.
char *ptr() { return audio_data.data(); }
/// Same as above, but const-qualified for simple reads into the buffer.
[[nodiscard]] const char *ptr() const { return audio_data.data(); }
/// Returns a particular sample at a given index.
char &At(uint index);
/// Returns a particular sample at a given index.
[[nodiscard]] char At(uint index) const;
/// Mixing Test Operator
Sound operator+(const Sound &rhs) const;
private:
uint sample_rate;
@@ -101,7 +127,7 @@ namespace ReMixer {
// TODO: Implement SFX class.
};
/// Music class is for longer sounds that should be streamed in.
/// Music class is for longer sounds that should be streamed in from disk.
class Music : public Sound {
// TODO: Implement Music class.
};

View File

@@ -38,8 +38,11 @@
PulseStream test_stream = test.CreateStream("Test Stream");
//PulseStream test_stream2 = test.CreateStream("Another Test Stream");
//Sound test_sound = Sound::FromPCMFile("output.raw");
Sound ogg_test_sound = Sound::FromOGGVorbisFile("song.ogg");
Sound test_sound = Sound::FromPCMFile("output.raw");
Sound ogg_test_sound = Sound::FromOGGVorbisFile("wind.ogg");
test_sound = test_sound + ogg_test_sound;
auto sample_depth = 2;
@@ -47,8 +50,7 @@
std::thread playback_thread([](PulseAudioSubsystem system, PulseStream stream, Sound sound){
system.Play(stream, sound);
}, test, test_stream, ogg_test_sound);
}, test, test_stream, test_sound);
while (true) {

View File

@@ -127,3 +127,46 @@ uint ReMixer::Sound::SampleCount() const {
// Consider sample_depth = 2, each 16-bit sample would hold two elements in the char buffer.
return audio_data.size();
}
uint ReMixer::Sound::DataSizeInBytes() const {
return audio_data.size() * sizeof(decltype(audio_data)::value_type);
}
char ReMixer::Sound::At(uint index) const {
return audio_data[index];
}
char &ReMixer::Sound::At(uint index) {
return audio_data[index];
}
ReMixer::Sound ReMixer::Sound::operator+(const ReMixer::Sound &rhs) const {
// TODO: Consider differing paramters for mixing
// sample_rate, sample_depth, and so on.
std::vector<char> sum;
auto rhs_buf = rhs.audio_data;
auto lhs_buf = this->audio_data;
for (int i = 0; i < std::max(lhs_buf.size(), rhs_buf.size()); i++)
{
int a = 0;
if (i >= lhs_buf.size() && i < rhs_buf.size()) {
sum.push_back(rhs_buf[i]);
continue;
}
if (i >= rhs_buf.size() && i < lhs_buf.size()) {
sum.push_back(lhs_buf[i]);
continue;
}
sum.push_back(mix(lhs_buf[i], rhs_buf[i]));
}
return Sound::FromPCMBuffer(sum);
}
int mix(int a, int b) {
return std::clamp(a + b, -128, 128);
}