81 lines
1.9 KiB
C++
81 lines
1.9 KiB
C++
#include <psemek/audio/track.hpp>
|
|
#include <psemek/audio/constants.hpp>
|
|
#include <psemek/audio/detail/resampler.hpp>
|
|
#include <psemek/util/to_string.hpp>
|
|
#include <psemek/util/at_scope_exit.hpp>
|
|
|
|
#ifdef __GNUC__
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
|
#endif
|
|
|
|
#include <psemek/audio/audio_file/AudioFile.h>
|
|
|
|
#ifdef __GNUC__
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
namespace psemek::audio
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
std::vector<float> convert_audio(std::vector<std::vector<float>> const & channels, int frequency)
|
|
{
|
|
if (channels.empty() || channels.size() > 2)
|
|
throw std::runtime_error(util::to_string("Can't convert audio with ", static_cast<int>(channels.size()), " channels"));
|
|
|
|
std::vector<float> result(channels[0].size() * 2);
|
|
auto out = result.begin();
|
|
|
|
if (channels.size() == 1)
|
|
{
|
|
for (auto p = channels[0].begin(); p != channels[0].end(); ++p)
|
|
{
|
|
*out++ = *p;
|
|
*out++ = *p;
|
|
}
|
|
}
|
|
else if (channels.size() == 2)
|
|
{
|
|
for (auto p0 = channels[0].begin(), p1 = channels[1].begin(); p0 != channels[0].end(); ++p0, ++p1)
|
|
{
|
|
*out++ = *p0;
|
|
*out++ = *p1;
|
|
}
|
|
}
|
|
|
|
if (frequency != audio::frequency)
|
|
{
|
|
audio::resampler resampler(audio::frequency * 1.f / frequency);
|
|
resampler.feed(result);
|
|
result = resampler.grab_result();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
track_ptr load_wav(util::span<char const> data)
|
|
{
|
|
std::vector<std::uint8_t> data_u8(data.size());
|
|
std::copy(data.begin(), data.end(), reinterpret_cast<char *>(data_u8.data()));
|
|
|
|
AudioFile<float> audio_file;
|
|
audio_file.shouldLogErrorsToConsole(false);
|
|
audio_file.onError = [](std::string const & error) {
|
|
throw std::runtime_error("failed to load WAV file: " + error);
|
|
};
|
|
audio_file.loadFromMemory(data_u8);
|
|
|
|
return load_raw(convert_audio(audio_file.samples, audio_file.getSampleRate()));
|
|
}
|
|
|
|
track_ptr load_wav(std::vector<char> const & data)
|
|
{
|
|
return load_wav(util::span<char const>(data));
|
|
}
|
|
|
|
}
|