#include #include #include #include #include #include #include namespace psemek::audio { namespace { std::vector convert_audio(SDL_AudioSpec const & spec, std::uint8_t * samples, std::size_t length) { if (spec.channels > 2) throw std::runtime_error(util::to_string("Can't convert audio with ", static_cast(spec.channels), " channels")); if (spec.freq != audio::frequency) throw std::runtime_error(util::to_string("Can't convert audio with frequency ", spec.freq)); if (spec.format != AUDIO_S16SYS) throw std::runtime_error(util::to_string("Can't convert audio with format ", spec.format)); auto p = reinterpret_cast(samples); std::vector result; if (spec.channels == 1) { result.resize(length); for (std::size_t i = 0; i < length / 2; ++i) { float v = (p[i] * 2.f + 1.f) / 65536.f; result[2 * i + 0] = v; result[2 * i + 1] = v; } } else { result.resize(length / 2); for (std::size_t i = 0; i < length / 2; ++i) result[i] = (p[i] * 2.f + 1.f) / 65536.f; } return result; } } track_ptr load_wav(util::span data) { SDL_AudioSpec spec; std::uint8_t * samples; std::uint32_t length; if (!SDL_LoadWAV_RW(SDL_RWFromConstMem(data.data(), data.size()), 1, &spec, &samples, &length)) sdl2::fail("SDL_LoadWAV_RW failed:"); util::at_scope_exit release_samples([samples]{ SDL_FreeWAV(samples); }); return load_raw(convert_audio(spec, samples, length)); } track_ptr load_wav(std::vector const & data) { return load_wav(util::span(data)); } }