Merge pull request #491 from winterheart/mve-update

MVE refactoring
This commit is contained in:
Louis Gombert 2024-07-18 21:37:59 +00:00 committed by GitHub
commit 5641ba49bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 39 additions and 48 deletions

View File

@ -21,15 +21,6 @@
namespace D3 {
void MovieSoundDevice::SDLAudioCallback(void *userdata, unsigned char *stream, int len) {
auto device = static_cast<MovieSoundDevice *>(userdata);
for (int i = 0; i < len; i += 2) {
int16_t sample = device->m_sound_buffer->front();
device->m_sound_buffer->pop_front();
memcpy(&stream[i], &sample, 2);
}
}
MovieSoundDevice::MovieSoundDevice(int sample_rate, uint16_t sample_size, uint8_t channels, uint32_t buf_size,
bool is_compressed) {
SDL_AudioFormat format = (sample_size == 2) ? AUDIO_S16LSB : AUDIO_U8;
@ -37,27 +28,32 @@ MovieSoundDevice::MovieSoundDevice(int sample_rate, uint16_t sample_size, uint8_
spec.freq = sample_rate;
spec.format = format;
spec.channels = channels;
spec.size = 4096;
spec.callback = &MovieSoundDevice::SDLAudioCallback;
spec.size = buf_size;
spec.callback = nullptr;
spec.userdata = this;
m_device_id = SDL_OpenAudioDevice(nullptr, 0, &spec, nullptr, 0);
m_is_compressed = is_compressed;
m_sample_size = sample_size;
};
MovieSoundDevice::~MovieSoundDevice() {
if (m_device_id > 0) {
SDL_CloseAudioDevice(m_device_id);
m_device_id = 0;
}
m_sound_buffer.reset();
}
void MovieSoundDevice::FillBuffer(char *stream, int len) const {
SDL_QueueAudio(m_device_id, stream, len);
};
void MovieSoundDevice::Play() { SDL_PauseAudioDevice(m_device_id, 0); }
void MovieSoundDevice::Stop() { SDL_PauseAudioDevice(m_device_id, 1); }
void MovieSoundDevice::Lock() { SDL_LockAudioDevice(m_device_id); };
void MovieSoundDevice::Lock() { SDL_LockAudioDevice(m_device_id); }
void MovieSoundDevice::Unlock() { SDL_UnlockAudioDevice(m_device_id); };
void MovieSoundDevice::Unlock() { SDL_UnlockAudioDevice(m_device_id); }
} // namespace D3

View File

@ -29,6 +29,7 @@ namespace D3 {
class MovieSoundDevice : ISoundDevice {
private:
SDL_AudioDeviceID m_device_id = 0;
uint16_t m_sample_size = 0;
public:
/**
@ -49,19 +50,23 @@ public:
[[nodiscard]] bool IsInitialized() const { return m_device_id > 0; }
/**
* Callback for filling SDL audio buffer
* @param userdata pointer to instance of this class
* @param stream stream that will be filled on callback
* @param len length of stream
* Fill internal audio stream to be played
* @param stream source buffer
* @param len length of source buffer
*/
void static SDLAudioCallback(void *userdata, unsigned char *stream, int len);
void FillBuffer(char *stream, int len) const;
/**
* Get sample size
* @return 2 (for 16 bit), 1 (for 8 bit)
*/
[[nodiscard]] uint16_t GetSampleSize() const { return m_sample_size; };
void Play() override;
void Stop() override;
void Lock() override;
void Unlock() override;
using ISoundDevice::GetBuffer;
using ISoundDevice::IsCompressed;
};

View File

@ -16,8 +16,7 @@
*/
#include <algorithm>
#include <deque>
#include <memory>
#include <cstring>
#include "byteswap.h"
@ -62,26 +61,23 @@ static int16_t getWord(unsigned char **fin) {
return value;
}
void mveaudio_process(std::unique_ptr<std::deque<int16_t>> &buffer, unsigned char *data, bool is_compressed) {
void mveaudio_process(char *buffer, unsigned char *data, int sample_size, bool is_compressed) {
if (is_compressed) {
int nCurOffsets[2];
data += 4;
int swath = getWord(&data) / 2;
int samples = getWord(&data) / sample_size;
// Fill predictors
nCurOffsets[0] = getWord(&data);
nCurOffsets[1] = getWord(&data);
buffer->push_back((int16_t)std::clamp(nCurOffsets[0], -32768, 32767));
buffer->push_back((int16_t)std::clamp(nCurOffsets[1], -32768, 32767));
for (int i = 0; i < swath; i++) {
nCurOffsets[i & 1] += audio_exp_table[data[i]];
buffer->push_back((int16_t)std::clamp(nCurOffsets[i & 1], -32768, 32767));
for (int i = 0; i < samples; i++) {
nCurOffsets[i & 1] = std::clamp(nCurOffsets[i & 1] + audio_exp_table[data[i]], -32768, 32767);
memcpy(buffer + i * sample_size, &nCurOffsets[i & 1], sample_size);
}
} else {
data += 2;
int samples = getWord(&data);
for (int i = 0; i < samples; i++) {
buffer->push_back(getWord(&data));
}
int size = getWord(&data);
memcpy(buffer, &data, size);
}
}

View File

@ -22,8 +22,9 @@
* Process input data and send parsed data into queue buffer
* @param buffer output queue buffer
* @param data input data
* @param sample_size size of sample (1 for 8 bit, 2 for 16 bit)
* @param is_compress true if input data is compressed
*/
void mveaudio_process(std::unique_ptr<std::deque<int16_t>> &buffer, unsigned char *data, bool is_compressed = true);
void mveaudio_process(char *buffer, unsigned char *data, int sample_size, bool is_compressed = true);
#endif /* INCLUDED_MVE_AUDIO_H */

View File

@ -184,7 +184,7 @@ static int create_audiobuf_handler(unsigned char major, unsigned char minor, uns
is_compressed = true;
}
snd_ds = std::make_unique<D3::MovieSoundDevice>(sample_rate, sample_size, channels, desired_buffer, is_compressed);
snd_ds = std::make_unique<D3::MovieSoundDevice>(sample_rate, sample_size, channels, 4096, is_compressed);
#endif
return 1;
@ -204,18 +204,17 @@ static int audio_data_handler(unsigned char major, unsigned char minor, unsigned
static const int selected_chan = 1;
if (snd_ds->IsInitialized()) {
int chan = get_ushort(data + 2);
int size = get_ushort(data + 4);
if (chan & selected_chan) {
void *buf = malloc(size);
if (major == MVE_OPCODE_AUDIOFRAMEDATA) {
snd_ds->Lock();
mveaudio_process(snd_ds->GetBuffer(), data, snd_ds->IsCompressed());
snd_ds->Unlock();
mveaudio_process((char *)buf, data, snd_ds->GetSampleSize(), snd_ds->IsCompressed());
} else {
// SILENCE, MORTALS!
int nsamp = get_ushort(data + 4);
snd_ds->Lock();
snd_ds->GetBuffer()->insert(snd_ds->GetBuffer()->end(), nsamp, 0);
snd_ds->Unlock();
memset(data, 0, size);
}
snd_ds->FillBuffer((char *)buf, size);
free(buf);
}
}
#endif

View File

@ -20,19 +20,15 @@
#define LIBMVE_SOUND_INTERFACE_H_
#include <cstdint>
#include <deque>
#include <memory>
namespace D3 {
/// Abstract class for sound device.
class ISoundDevice {
protected:
std::unique_ptr<std::deque<int16_t>> m_sound_buffer;
bool m_is_compressed = false;
public:
ISoundDevice() { this->m_sound_buffer = std::make_unique<std::deque<int16_t>>(); };
/// Play stream
virtual void Play() {};
/// Stop stream
@ -42,8 +38,6 @@ public:
/// Unlock buffer
virtual void Unlock() {};
/// Get access to sound buffer
std::unique_ptr<std::deque<int16_t>> &GetBuffer() { return m_sound_buffer; }
/// Check if encoded sound is compressed
[[nodiscard]] bool IsCompressed() const { return m_is_compressed; };