diff --git a/libmve/movie_sound.cpp b/libmve/movie_sound.cpp index acf02944..ecbd69d9 100644 --- a/libmve/movie_sound.cpp +++ b/libmve/movie_sound.cpp @@ -21,15 +21,6 @@ namespace D3 { -void MovieSoundDevice::SDLAudioCallback(void *userdata, unsigned char *stream, int len) { - auto device = static_cast(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,8 +28,8 @@ 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); @@ -48,16 +39,20 @@ MovieSoundDevice::MovieSoundDevice(int sample_rate, uint16_t sample_size, uint8_ 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 diff --git a/libmve/movie_sound.h b/libmve/movie_sound.h index 7779ca23..c306926c 100644 --- a/libmve/movie_sound.h +++ b/libmve/movie_sound.h @@ -49,19 +49,17 @@ 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; void Play() override; void Stop() override; void Lock() override; void Unlock() override; - using ISoundDevice::GetBuffer; using ISoundDevice::IsCompressed; }; diff --git a/libmve/mve_audio.cpp b/libmve/mve_audio.cpp index 1e88c05f..e3c27e7a 100644 --- a/libmve/mve_audio.cpp +++ b/libmve/mve_audio.cpp @@ -16,8 +16,7 @@ */ #include -#include -#include +#include #include "byteswap.h" @@ -62,26 +61,23 @@ static int16_t getWord(unsigned char **fin) { return value; } -void mveaudio_process(std::unique_ptr> &buffer, unsigned char *data, bool is_compressed) { +void mveaudio_process(char *buffer, unsigned char *data, bool is_compressed) { if (is_compressed) { int nCurOffsets[2]; data += 4; - int swath = getWord(&data) / 2; + int samples = getWord(&data) / 2; + // 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 * 2, &nCurOffsets[i & 1], 2); } } else { data += 2; int samples = getWord(&data); - for (int i = 0; i < samples; i++) { - buffer->push_back(getWord(&data)); - } + memcpy(buffer, &data, samples * 2); } } diff --git a/libmve/mve_audio.h b/libmve/mve_audio.h index 06ed6e89..68124758 100644 --- a/libmve/mve_audio.h +++ b/libmve/mve_audio.h @@ -24,6 +24,6 @@ * @param data input data * @param is_compress true if input data is compressed */ -void mveaudio_process(std::unique_ptr> &buffer, unsigned char *data, bool is_compressed = true); +void mveaudio_process(char *buffer, unsigned char *data, bool is_compressed = true); #endif /* INCLUDED_MVE_AUDIO_H */ diff --git a/libmve/mveplay.cpp b/libmve/mveplay.cpp index 4aefdaf4..f0fca7b0 100644 --- a/libmve/mveplay.cpp +++ b/libmve/mveplay.cpp @@ -184,7 +184,7 @@ static int create_audiobuf_handler(unsigned char major, unsigned char minor, uns is_compressed = true; } - snd_ds = std::make_unique(sample_rate, sample_size, channels, desired_buffer, is_compressed); + snd_ds = std::make_unique(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->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 diff --git a/libmve/sound_interface.h b/libmve/sound_interface.h index 250ab0bb..a532f919 100644 --- a/libmve/sound_interface.h +++ b/libmve/sound_interface.h @@ -20,19 +20,15 @@ #define LIBMVE_SOUND_INTERFACE_H_ #include -#include -#include namespace D3 { /// Abstract class for sound device. class ISoundDevice { protected: - std::unique_ptr> m_sound_buffer; bool m_is_compressed = false; public: - ISoundDevice() { this->m_sound_buffer = std::make_unique>(); }; /// 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> &GetBuffer() { return m_sound_buffer; } /// Check if encoded sound is compressed [[nodiscard]] bool IsCompressed() const { return m_is_compressed; };