Undo changes to playback.cpp and playback.h that should be on another branch
Some checks failed
Build / build-gentoo (push) Failing after 25s
Build / download-system-deps (push) Successful in 3m42s
Build / get-source-code (push) Successful in 10m19s
Build / build-appimage (push) Successful in 4m3s
Build / build-android (push) Failing after 2m59s
Build / build-windows (push) Failing after 7m16s
Some checks failed
Build / build-gentoo (push) Failing after 25s
Build / download-system-deps (push) Successful in 3m42s
Build / get-source-code (push) Successful in 10m19s
Build / build-appimage (push) Successful in 4m3s
Build / build-android (push) Failing after 2m59s
Build / build-windows (push) Failing after 7m16s
This commit is contained in:
parent
373f9de27c
commit
ca1ac38885
2 changed files with 74 additions and 152 deletions
153
playback.cpp
153
playback.cpp
|
@ -31,93 +31,47 @@ void PlaybackInstance::SDLCallbackInner(Uint8 *stream, int len) {
|
|||
SDL_memset((void*)stream, 0, len);
|
||||
if (!playback_ready.load()) return;
|
||||
if (process == nullptr) return;
|
||||
if (st == nullptr) return;
|
||||
size_t unit = sizeof(SAMPLETYPE) * spec.channels;
|
||||
size_t bytes_per_iter = (bufsize / unit) * unit;
|
||||
SAMPLETYPE *tmpbuf = (SAMPLETYPE*)malloc(bytes_per_iter);
|
||||
memset(tmpbuf, 0, bytes_per_iter);
|
||||
while (m_st->numSamples() * unit <= (size_t)len) {
|
||||
for (auto &data : m_playback_data) {
|
||||
while (st->numSamples() * unit <= (size_t)len) {
|
||||
if (process == nullptr) {
|
||||
return;
|
||||
}
|
||||
Uint8 *new_buf;
|
||||
int new_bufsize;
|
||||
new_buf = buf;
|
||||
bytes_per_iter = data.m_backend_spec.size;
|
||||
bytes_per_iter = backend_spec.size;
|
||||
if (bytes_per_iter > bufsize) {
|
||||
bytes_per_iter = bufsize;
|
||||
}
|
||||
new_bufsize = bytes_per_iter;
|
||||
size_t new_bytes = data.m_pProcess->render(buf, bytes_per_iter);
|
||||
if (SDL_AudioStreamPut(data.m_pStream, buf, new_bytes) < 0) {
|
||||
if (this->process != nullptr) {
|
||||
size_t new_bytes = this->process->render(buf, bytes_per_iter);
|
||||
if (SDL_AudioStreamPut(sdl_stream, buf, new_bytes) < 0) {
|
||||
ERROR.writefln("SDL_AudioStreamPut: %s", SDL_GetError());
|
||||
DEBUG.writefln("Current audio backend: %s", data.m_pProcess->get_backend_id().c_str());
|
||||
DEBUG.writefln("SDL_AudioStream *sdl_stream = %0lx", (size_t)data.m_pStream);
|
||||
DEBUG.writefln("Current audio backend: %s", process->get_backend_id().c_str());
|
||||
DEBUG.writefln("SDL_AudioStream *sdl_stream = %0lx", (size_t)sdl_stream);
|
||||
return;
|
||||
}
|
||||
do {
|
||||
new_bufsize = SDL_AudioStreamGet(data.m_pStream, buf, bytes_per_iter);
|
||||
new_bufsize = SDL_AudioStreamGet(sdl_stream, buf, std::min((size_t)backend_spec.samples, bufsize / unit) * unit);
|
||||
if (new_bufsize < 0) {
|
||||
ERROR.writefln("SDL_AudioStreamGet: %s", SDL_GetError());
|
||||
DEBUG.writefln("Current audio backend: %s", data.m_pProcess->get_backend_id().c_str());
|
||||
DEBUG.writefln("Current audio backend: %s", process->get_backend_id().c_str());
|
||||
return;
|
||||
}
|
||||
SAMPLETYPE *sbuf = (SAMPLETYPE*)buf;
|
||||
for (size_t i = 0; i < (new_bufsize / unit) * spec.channels; i++) {
|
||||
if (data.m_fade_time >= 0.0) {
|
||||
if ((i % spec.channels) == 0) {
|
||||
data.m_fade_time -= 1.0 / (spec.freq);
|
||||
if (data.m_fade_time <= 0.0) {
|
||||
data.delete_needed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sbuf[i] *= data.m_fade_time;
|
||||
}
|
||||
tmpbuf[i] += sbuf[i];
|
||||
}
|
||||
data.m_st->putSamples(sbuf, new_bufsize / unit);
|
||||
if (data.delete_needed) {
|
||||
break;
|
||||
sbuf[i] *= real_volume;
|
||||
}
|
||||
st->putSamples(sbuf, new_bufsize / unit);
|
||||
} while (new_bufsize > 0);
|
||||
}
|
||||
for (auto &data : m_playback_data) {
|
||||
size_t tmplen = 0;
|
||||
size_t bufused = (bufsize / unit) * unit;
|
||||
bool done = false;
|
||||
{
|
||||
uint samples;
|
||||
do {
|
||||
samples = data.m_st->receiveSamples((SAMPLETYPE*)(void*)buf, tmplen / unit);
|
||||
m_st->putSamples((SAMPLETYPE*)(void*)buf, samples);
|
||||
} while (samples > 0);
|
||||
}
|
||||
for (size_t i = 0; i < len; i += bufused) {
|
||||
if (i + bufused >= len) {
|
||||
tmplen = len - i;
|
||||
} else {
|
||||
tmplen = bufused;
|
||||
}
|
||||
uint samples = m_st->receiveSamples((SAMPLETYPE*)(void*)buf, tmplen / unit);
|
||||
for (size_t j = 0; j < samples * spec.channels; j++) {
|
||||
((SAMPLETYPE*)(void*)stream)[j] += ((SAMPLETYPE*)(void*)buf)[(i * bufused / unit) + j];
|
||||
}
|
||||
if (samples == 0) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data.delete_needed) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i > m_playback_data.size();) {
|
||||
auto &data = m_playback_data[i];
|
||||
if (data.delete_needed) {
|
||||
m_playback_data.erase(m_playback_data.begin() + i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
st->receiveSamples((SAMPLETYPE*)stream, len / unit);
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
oboe::DataCallbackResult PlaybackInstance::onAudioReady(
|
||||
|
@ -155,23 +109,18 @@ void PlaybackInstance::Load(const char *file, int idx) {
|
|||
LockAudioDevice();
|
||||
load_finished.store(false);
|
||||
playback_ready.store(false);
|
||||
for (auto &data : m_playback_data) {
|
||||
data.m_fade_time = 1.0;
|
||||
}
|
||||
PlaybackProcess *process = nullptr;
|
||||
playback_data data;
|
||||
if (process != nullptr) delete process;
|
||||
try {
|
||||
process = new PlaybackProcess(file, idx);
|
||||
} catch (std::exception e) {
|
||||
ERROR.writefln("Exception caught when creating process: %s", e.what());
|
||||
data.delete_needed = true;
|
||||
process = nullptr;
|
||||
}
|
||||
length = 0.0;
|
||||
if (!data.delete_needed && process->process_running()) {
|
||||
if (process != nullptr && process->process_running()) {
|
||||
length = process->get_length();
|
||||
auto backend_spec_proxy = process->get_audio_spec();
|
||||
SDL_AudioSpec backend_spec;
|
||||
memset(&backend_spec, 0, sizeof(data.m_backend_spec));
|
||||
memset(&backend_spec, 0, sizeof(backend_spec));
|
||||
backend_spec.channels = backend_spec_proxy->channel_count();
|
||||
audio_data_t sample_fmt;
|
||||
sample_fmt.size = backend_spec_proxy->bits() / 8;
|
||||
|
@ -187,22 +136,23 @@ void PlaybackInstance::Load(const char *file, int idx) {
|
|||
DEBUG.writefln("\tChannels: %d", backend_spec.channels);
|
||||
DEBUG.writefln("\tSample rate: %d", backend_spec.freq);
|
||||
DEBUG.writefln("\tSamples: %d", backend_spec.samples);
|
||||
try {
|
||||
data = playback_data(backend_spec, spec, process);
|
||||
} catch (CustomException &e) {
|
||||
set_error(e.what());
|
||||
if (sdl_stream != nullptr) {
|
||||
SDL_FreeAudioStream(sdl_stream);
|
||||
}
|
||||
sdl_stream = SDL_NewAudioStream(backend_spec.format, backend_spec.channels, backend_spec.freq, spec.format, spec.channels, spec.freq);
|
||||
if (sdl_stream == nullptr) {
|
||||
ERROR.writefln("SDL_NewAudioStream: %s", SDL_GetError());
|
||||
DEBUG.writefln("format: AUDIO_%s%d%s", sample_fmt.is_float ? "F" : sample_fmt.is_signed ? "S" : "U", sample_fmt.size * 8, sample_fmt.endian ? "MSB" : "LSB");
|
||||
set_error("Failed to create SDL audio stream");
|
||||
set_signal(PlaybackSignalErrorOccurred);
|
||||
ERROR.writeln(e.what());
|
||||
}
|
||||
size_t required_size = sample_fmt.size * data.m_backend_spec.samples;
|
||||
m_st->setChannels(spec.channels);
|
||||
m_st->setRate(spec.freq);
|
||||
m_st->flush();
|
||||
data.m_backend_spec.size = required_size;
|
||||
if (bufsize < required_size || buf == nullptr) {
|
||||
bufsize = required_size;
|
||||
buf = (Uint8*)((buf == nullptr) ? malloc(bufsize) : realloc(buf, bufsize));
|
||||
}
|
||||
size_t required_size = sample_fmt.size * backend_spec.samples;
|
||||
st->setChannels(spec.channels);
|
||||
st->setRate(spec.freq);
|
||||
st->flush();
|
||||
backend_spec.size = required_size;
|
||||
bufsize = backend_spec.size;
|
||||
buf = (Uint8*)malloc(bufsize);
|
||||
if (buf == nullptr) {
|
||||
ERROR.writeln("Failed to allocate memory for playback!");
|
||||
set_error("Failed to allocate memory for playback!");
|
||||
|
@ -226,8 +176,12 @@ void PlaybackInstance::Load(const char *file, int idx) {
|
|||
flag_mutex.unlock();
|
||||
}
|
||||
void PlaybackInstance::Unload() {
|
||||
if (process == nullptr) return;
|
||||
LockAudioDevice();
|
||||
m_playback_data.clear();
|
||||
delete process;
|
||||
process = nullptr;
|
||||
SDL_FreeAudioStream(sdl_stream);
|
||||
sdl_stream = nullptr;
|
||||
if (buf) free(buf);
|
||||
buf = nullptr;
|
||||
UnlockAudioDevice();
|
||||
|
@ -236,25 +190,25 @@ void PlaybackInstance::UpdateST() {
|
|||
bool any_changed = false;
|
||||
if (speed > 0.0f && speed_changed.exchange(false)) {
|
||||
any_changed = true;
|
||||
m_st->setRate(speed);
|
||||
st->setRate(speed);
|
||||
set_signal(PlaybackSignalSpeedChanged);
|
||||
}
|
||||
if (tempo > 0.0f && tempo_changed.exchange(false)) {
|
||||
any_changed = true;
|
||||
m_st->setTempo(tempo);
|
||||
st->setTempo(tempo);
|
||||
set_signal(PlaybackSignalTempoChanged);
|
||||
}
|
||||
if (pitch > 0.0f && pitch_changed.exchange(false)) {
|
||||
any_changed = true;
|
||||
m_st->setPitch(pitch);
|
||||
st->setPitch(pitch);
|
||||
set_signal(PlaybackSignalPitchChanged);
|
||||
}
|
||||
if (any_changed && process != nullptr) {
|
||||
process->set_rate(m_st->getInputOutputSampleRatio());
|
||||
process->set_rate(st->getInputOutputSampleRatio());
|
||||
}
|
||||
}
|
||||
double PlaybackInstance::GetMaxSeconds() {
|
||||
return std::max((double)(MaxSpeed * MaxTempo), m_st->getInputOutputSampleRatio());
|
||||
return std::max((double)(MaxSpeed * MaxTempo), st->getInputOutputSampleRatio());
|
||||
}
|
||||
void PlaybackInstance::InitLoopFunction() {
|
||||
bool reload = false;
|
||||
|
@ -278,7 +232,7 @@ void PlaybackInstance::InitLoopFunction() {
|
|||
desired.channels = 2;
|
||||
desired.callback = PlaybackInstance::SDLCallback;
|
||||
desired.userdata = this;
|
||||
m_st = new SoundTouch();
|
||||
st = new SoundTouch();
|
||||
#ifdef USE_SDL
|
||||
if ((device = SDL_OpenAudioDevice(nullptr, 0, &desired, &obtained, SDL_AUDIO_ALLOW_CHANNELS_CHANGE|SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE)) == 0) {
|
||||
ERROR.writefln("Error opening audio device: '%s'", SDL_GetError());
|
||||
|
@ -335,8 +289,8 @@ Total samples: %u"
|
|||
#error Invalid configuration detected.
|
||||
#endif
|
||||
spec = obtained;
|
||||
m_st->setSampleRate(spec.freq);
|
||||
m_st->setChannels(spec.channels);
|
||||
st->setSampleRate(spec.freq);
|
||||
st->setChannels(spec.channels);
|
||||
UpdateST();
|
||||
|
||||
reload = false;
|
||||
|
@ -348,7 +302,9 @@ Total samples: %u"
|
|||
flag_mutex.unlock();
|
||||
playback_ready.store(false);
|
||||
length = 0.0;
|
||||
m_playback_data.clear();
|
||||
memset(&backend_spec, 0, sizeof(backend_spec));
|
||||
if (sdl_stream) SDL_FreeAudioStream(sdl_stream);
|
||||
sdl_stream = nullptr;
|
||||
bufsize = 0;
|
||||
if (buf) free((void*)buf);
|
||||
buf = nullptr;
|
||||
|
@ -450,8 +406,8 @@ void PlaybackInstance::DeinitLoopFunction() {
|
|||
SDL_CloseAudioDevice(device);
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
#endif
|
||||
delete m_st;
|
||||
m_st = nullptr;
|
||||
delete st;
|
||||
st = nullptr;
|
||||
if (buf) free(buf);
|
||||
current_file_mutex.lock();
|
||||
current_file = {};
|
||||
|
@ -474,6 +430,7 @@ PlaybackInstance::PlaybackInstance() {
|
|||
running = false;
|
||||
paused = true;
|
||||
position = 0;
|
||||
sdl_stream = nullptr;
|
||||
length = 0;
|
||||
volume = 100.0;
|
||||
real_volume = 1.0;
|
||||
|
|
41
playback.h
41
playback.h
|
@ -21,8 +21,6 @@
|
|||
#include "playback_process.hpp"
|
||||
#include <google/protobuf/any.h>
|
||||
#include <ipc/internal.pb.h>
|
||||
#include "playlist.hpp"
|
||||
#include "util.hpp"
|
||||
using namespace soundtouch;
|
||||
using std::span;
|
||||
using std::optional;
|
||||
|
@ -274,45 +272,12 @@ private:
|
|||
double length;
|
||||
bool paused;
|
||||
Uint8* buf;
|
||||
size_t tmpbuf_len;
|
||||
size_t bufsize;
|
||||
SDL_AudioDeviceID device;
|
||||
SoundTouch *st;
|
||||
SDL_AudioSpec spec;
|
||||
struct playback_data {
|
||||
SDL_AudioStream *m_pStream = nullptr;
|
||||
SDL_AudioSpec m_backend_spec = {0};
|
||||
PlaybackProcess *m_pProcess = nullptr;
|
||||
SoundTouch *m_st = nullptr;
|
||||
bool delete_needed = false;
|
||||
inline bool fading() {
|
||||
return m_fade_time >= 0.0;
|
||||
}
|
||||
double m_fade_time = -1.0;
|
||||
inline bool valid() {
|
||||
return m_st != nullptr && m_pStream != nullptr && m_pProcess != nullptr;
|
||||
}
|
||||
inline playback_data() {}
|
||||
inline playback_data(SDL_AudioSpec backend_spec, SDL_AudioSpec spec, PlaybackProcess *process, double speed = 1.0, double tempo = 1.0, double pitch = 1.0) {
|
||||
m_backend_spec = backend_spec;
|
||||
m_pStream = SDL_NewAudioStream(backend_spec.format, backend_spec.channels, backend_spec.freq, spec.format, spec.channels, spec.freq);
|
||||
if (m_pStream == nullptr) throw CustomException(fmt::format("Could not create stream: {}", SDL_GetError()));
|
||||
m_st = new SoundTouch();
|
||||
m_st->setChannels(spec.channels);
|
||||
m_st->setSampleRate(spec.freq);
|
||||
m_st->setRate(speed);
|
||||
m_st->setPitch(pitch);
|
||||
m_st->setTempo(tempo);
|
||||
}
|
||||
inline ~playback_data() {
|
||||
if (m_pStream != nullptr) SDL_FreeAudioStream(m_pStream);
|
||||
delete m_pProcess;
|
||||
delete m_st;
|
||||
}
|
||||
};
|
||||
Playlist playlist;
|
||||
SoundTouch *m_st;
|
||||
std::vector<playback_data> m_playback_data;
|
||||
void CleanPlaybackData();
|
||||
SDL_AudioSpec backend_spec;
|
||||
SDL_AudioStream *sdl_stream = nullptr;
|
||||
void SDLCallbackInner(Uint8 *stream, int len);
|
||||
static void SDLCallback(void *userdata, Uint8 *stream, int len);
|
||||
void Load(const char *file, int idx);
|
||||
|
|
Loading…
Reference in a new issue