Skip to content

Commit

Permalink
Completed: Sound
Browse files Browse the repository at this point in the history
  • Loading branch information
WillisMedwell committed Mar 11, 2024
1 parent c9b1ba2 commit 104bdf0
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 40 deletions.
7 changes: 3 additions & 4 deletions code/Demos/src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,11 +420,10 @@ struct IsoLogic {

std::cout << std::thread::hardware_concurrency() << '\n';

Media::Sound sound {};
/*Media::Sound sound {};*/

Media::Sound sound = Media::Sound::create("assets/background_sound.wav").on_error_panic().value_move();

auto wav_file_data = Utily::FileReader::load_entire_file("assets/background_sound.wav");
wav_file_data.on_error(print_then_quit);
sound.init_from_wav(wav_file_data.value()).on_error(print_then_quit);

auto res = audio.load_sound_into_buffer(sound).on_error(print_then_quit);

Expand Down
20 changes: 12 additions & 8 deletions code/Engine/include/Media/Sound.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Media {
stereo16 = AL_FORMAT_STEREO16
};

[[nodiscard]] auto init_from_wav(const std::vector<uint8_t>& encoded_wav) -> Utily::Result<void, Utily::Error>;
[[nodiscard]] static auto create(std::filesystem::path wav_path) noexcept -> Utily::Result<Sound, Utily::Error>;

inline static auto to_openal_format(const Format& format) -> FormatOpenal {
if (format == Format::mono_i16) {
Expand All @@ -36,14 +36,18 @@ namespace Media {
}
}

[[nodiscard]] inline auto raw_bytes() const noexcept -> std::span<const int16_t> { return { _data.cbegin(), _data.cend() }; }
[[nodiscard]] inline auto frequency() const noexcept -> size_t { return _frequency; }
[[nodiscard]] inline auto openal_format() const noexcept -> FormatOpenal { return to_openal_format(_format); }
[[nodiscard]] inline auto raw_bytes() const noexcept -> std::span<const int16_t> { return { _m.data.cbegin(), _m.data.cend() }; }
[[nodiscard]] inline auto frequency() const noexcept -> size_t { return _m.frequency; }
[[nodiscard]] inline auto openal_format() const noexcept -> FormatOpenal { return to_openal_format(_m.format); }

private:
std::vector<int16_t> _data = {};
size_t _data_size_bytes = 0;
size_t _frequency = 0;
Format _format = {};
struct M {
std::vector<int16_t> data;
size_t frequency;
Format format;
} _m;

explicit Sound(M&& m)
: _m(std::move(m)) { }
};
}
59 changes: 31 additions & 28 deletions code/Engine/src/Media/Sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,60 @@
#include "Profiler/Profiler.hpp"
#include <Utily/Utily.hpp>


#define DR_WAV_IMPLEMENTATION
#include <dr_wav.h>

namespace Media {
auto Sound::init_from_wav(const std::vector<uint8_t>& encoded_wav) -> Utily::Result<void, Utily::Error> {
Profiler::Timer timer("Media::Sound::init_from_wav()");
auto Sound::create(std::filesystem::path wav_path) noexcept -> Utily::Result<Sound, Utily::Error> {
Profiler::Timer timer("Media::Sound::create()");
// 1. Load the raw contents of the wav file.
// 2. Decode the contents use dr-wav.
// 3. Compress stereo audio into mono audio and copy into buffer.
// 4. Free resources
// 5. Create Media::Sound

// 1.
auto load_file_result = Utily::FileReader::load_entire_file(wav_path);
if (load_file_result.has_error()) {
return load_file_result.error();
}
const auto& encoded_wav = load_file_result.value();

// 2.
uint32_t num_channels = 0;
uint32_t sample_rate = 0;
uint64_t frame_count = 0;

int16_t* dr_wav_ptr = drwav_open_memory_and_read_pcm_frames_s16(encoded_wav.data(), encoded_wav.size(), &num_channels, &sample_rate, &frame_count, nullptr);

auto dr_wav_data_i16 = std::span<const int16_t> { dr_wav_ptr, static_cast<size_t>(num_channels * frame_count) };

if (!dr_wav_ptr) {
return Utily::Error("Media::Sound::init_from_wave() failed. Dr wav failed to parse the file.");
}
auto dr_wav_data_i16 = std::span<const int16_t> { dr_wav_ptr, static_cast<size_t>(num_channels * frame_count) };

#if 1 // Convert all sounds to mono format. Stereo is not used for spatial audio.
// 3.
std::vector<int16_t> data;
if (num_channels == 2) {
_data.resize(dr_wav_data_i16.size() / 2);
auto iter = _data.begin();
data.resize(dr_wav_data_i16.size() / 2);
auto iter = data.begin();
// Combine to mono by taking average of the two channels.
for (int i = 0; i < dr_wav_data_i16.size(); i += 2) {
*iter = (dr_wav_data_i16[i] / 2) + (dr_wav_data_i16[i + 1] / 2);
++iter;
}
num_channels = 1;

} else
#endif
{
_data.resize(dr_wav_data_i16.size());
std::ranges::copy(dr_wav_data_i16, _data.begin());
} else {
data.resize(dr_wav_data_i16.size());
std::ranges::copy(dr_wav_data_i16, data.begin());
}

// 4.
drwav_free(dr_wav_ptr, nullptr);

_frequency = sample_rate;

if (num_channels == 1) {
_format = Format::mono_i16;
} else if (num_channels == 2) {
_format = Format::stereo_i16;
} else {
_data.clear();
_frequency = 0;
return Utily::Error("Media::Sound::init_from_wave() failed. Too many channels in .wav data. Can only handle 2 channels.");
}
return {};
// 5.
return Sound(M {
.data = std::move(data),
.frequency = sample_rate,
.format = Format::mono_i16,
});
}

}

0 comments on commit 104bdf0

Please sign in to comment.