Pārlūkot izejas kodu

audio: avoid a buffer copy and a potential division by zero in the QOA decoder

main
Sam Hocevar pirms 8 mēnešiem
vecāks
revīzija
9e289cdd12
1 mainītis faili ar 15 papildinājumiem un 16 dzēšanām
  1. +15
    -16
      src/audio/qoa.cpp

+ 15
- 16
src/audio/qoa.cpp Parādīt failu

@@ -12,7 +12,6 @@

#include <lol/engine/audio>
#include <memory>
#include <vector>

#include "../3rdparty/qoa/qoa.h"

@@ -26,48 +25,48 @@ class qoa_decoder : public stream<int16_t>
public:
qoa_decoder(uint8_t const *data, size_t size)
: stream<int16_t>(1, 0),
m_sample_pos(0)
m_frame_count(0),
m_frame_pos(0)
{
qoa_desc qoa;
if (auto qoa_data = qoa_decode(data, (int)size, &qoa); qoa_data)
{
m_channels = qoa.channels;
m_frequency = qoa.samplerate;
// This is possibly a large memory copy but we accept the overhead; the other way
// to do this would be to duplicate the qoa_decode() code and I don’t like that.
m_samples.assign(qoa_data, qoa_data + qoa.samples * qoa.channels);
// Should be QOA_FREE() for consistency but it is private to the implementation.
free(qoa_data);
// Should use QOA_FREE() instead of free() but it is private to the implementation.
m_qoa_data = std::shared_ptr<int16_t>(qoa_data, [](int16_t *p) { free(p); });
m_frame_count = qoa.samples;
}
}

virtual size_t get(int16_t *buf, size_t frames) override
{
size_t samples = std::min(frames * m_channels, m_samples.size() - m_sample_pos);
std::copy_n(std::next(m_samples.begin(), m_sample_pos), samples, buf);
m_sample_pos += samples;
return samples / m_channels;
size_t todo = std::min(frames, m_frame_count - m_frame_pos);
std::copy_n(m_qoa_data.get() + m_frame_pos * m_channels, todo * m_channels, buf);
m_frame_pos += todo;
return todo;
}

virtual std::optional<size_t> size() const override
{
return m_samples.size() / m_channels;
return m_frame_count;
}

virtual std::optional<size_t> pos() const override
{
return m_sample_pos / m_channels;
return m_frame_pos;
}

virtual bool seek(size_t pos) override
{
m_sample_pos = std::min(pos * m_channels, m_samples.size());
m_frame_pos = std::min(pos, m_frame_count);
return true;
}

protected:
std::vector<int16_t> m_samples;
size_t m_sample_pos;
std::shared_ptr<int16_t> m_qoa_data;
size_t m_frame_count;
size_t m_frame_pos;
};

std::shared_ptr<stream<int16_t>> make_qoa_decoder(uint8_t const *data, size_t size)


Notiek ielāde…
Atcelt
Saglabāt