Skip to content

Commit

Permalink
Merge pull request #491 from winterheart/mve-update
Browse files Browse the repository at this point in the history
MVE refactoring
  • Loading branch information
Lgt2x authored Jul 18, 2024
2 parents 91354d5 + 4b8328c commit 5641ba4
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 48 deletions.
24 changes: 10 additions & 14 deletions libmve/movie_sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,39 @@

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;
SDL_AudioSpec spec;
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
17 changes: 11 additions & 6 deletions libmve/movie_sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace D3 {
class MovieSoundDevice : ISoundDevice {
private:
SDL_AudioDeviceID m_device_id = 0;
uint16_t m_sample_size = 0;

public:
/**
Expand All @@ -49,19 +50,23 @@ class MovieSoundDevice : ISoundDevice {
[[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;

};
Expand Down
22 changes: 9 additions & 13 deletions libmve/mve_audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
*/

#include <algorithm>
#include <deque>
#include <memory>
#include <cstring>

#include "byteswap.h"

Expand Down Expand Up @@ -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);
}
}
3 changes: 2 additions & 1 deletion libmve/mve_audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
15 changes: 7 additions & 8 deletions libmve/mveplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down
6 changes: 0 additions & 6 deletions libmve/sound_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -42,8 +38,6 @@ class ISoundDevice {
/// 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; };

Expand Down

0 comments on commit 5641ba4

Please sign in to comment.