mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 14:08:37 +00:00
cellMusic/Decode: implement playlist shuffle and repeat
This commit is contained in:
parent
683fa2a392
commit
c40439ae6b
13 changed files with 790 additions and 247 deletions
|
|
@ -2,6 +2,9 @@
|
|||
#include "media_utils.h"
|
||||
#include "logs.hpp"
|
||||
#include "Utilities/StrUtil.h"
|
||||
#include "Emu/Cell/Modules/cellSearch.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
|
|
@ -196,9 +199,9 @@ namespace utils
|
|||
stop();
|
||||
}
|
||||
|
||||
void audio_decoder::set_path(const std::string& path)
|
||||
void audio_decoder::set_context(music_selection_context context)
|
||||
{
|
||||
m_path = path;
|
||||
m_context = std::move(context);
|
||||
}
|
||||
|
||||
void audio_decoder::set_swap_endianness(bool swapped)
|
||||
|
|
@ -206,27 +209,41 @@ namespace utils
|
|||
m_swap_endianness = swapped;
|
||||
}
|
||||
|
||||
void audio_decoder::clear()
|
||||
{
|
||||
track_fully_decoded = false;
|
||||
track_fully_consumed = false;
|
||||
has_error = false;
|
||||
m_size = 0;
|
||||
duration_ms = 0;
|
||||
timestamps_ms.clear();
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void audio_decoder::stop()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
auto& thread = *m_thread;
|
||||
thread = thread_state::aborting;
|
||||
track_fully_consumed = true;
|
||||
track_fully_consumed.notify_one();
|
||||
thread();
|
||||
m_thread.reset();
|
||||
}
|
||||
|
||||
has_error = false;
|
||||
m_size = 0;
|
||||
timestamps_ms.clear();
|
||||
data.clear();
|
||||
clear();
|
||||
}
|
||||
|
||||
void audio_decoder::decode()
|
||||
{
|
||||
stop();
|
||||
|
||||
m_thread = std::make_unique<named_thread<std::function<void()>>>("Music Decode Thread", [this, path = m_path]()
|
||||
media_log.notice("audio_decoder: %d entries in playlist. Start decoding...", m_context.playlist.size());
|
||||
|
||||
const auto decode_track = [this](const std::string& path)
|
||||
{
|
||||
media_log.notice("audio_decoder: decoding %s", path);
|
||||
scoped_av av;
|
||||
|
||||
// Get format from audio file
|
||||
|
|
@ -411,9 +428,61 @@ namespace utils
|
|||
if (buffer)
|
||||
av_free(buffer);
|
||||
|
||||
media_log.trace("audio_decoder: decoded frame_count=%d buffer_size=%d timestamp_us=%d", frame_count, buffer_size, av.frame->best_effort_timestamp);
|
||||
media_log.notice("audio_decoder: decoded frame_count=%d buffer_size=%d timestamp_us=%d", frame_count, buffer_size, av.frame->best_effort_timestamp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
m_thread = std::make_unique<named_thread<std::function<void()>>>("Music Decode Thread", [this, decode_track]()
|
||||
{
|
||||
for (const std::string& track : m_context.playlist)
|
||||
{
|
||||
media_log.notice("audio_decoder: playlist entry: %s", track);
|
||||
}
|
||||
|
||||
if (m_context.playlist.empty())
|
||||
{
|
||||
media_log.error("audio_decoder: Can not play empty playlist");
|
||||
has_error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_context.current_track = m_context.first_track;
|
||||
|
||||
if (m_context.context_option == CELL_SEARCH_CONTEXTOPTION_SHUFFLE && m_context.playlist.size() > 1)
|
||||
{
|
||||
// Shuffle once if necessary
|
||||
media_log.notice("audio_decoder: shuffling initial playlist...");
|
||||
auto engine = std::default_random_engine{};
|
||||
std::shuffle(std::begin(m_context.playlist), std::end(m_context.playlist), engine);
|
||||
}
|
||||
|
||||
while (thread_ctrl::state() != thread_state::aborting)
|
||||
{
|
||||
ensure(m_context.current_track < m_context.playlist.size());
|
||||
media_log.notice("audio_decoder: about to decode: %s (index=%d)", m_context.playlist.at(m_context.current_track), m_context.current_track);
|
||||
|
||||
decode_track(m_context.playlist.at(m_context.current_track));
|
||||
track_fully_decoded = true;
|
||||
|
||||
if (has_error)
|
||||
{
|
||||
media_log.notice("audio_decoder: stopping with error...");
|
||||
break;
|
||||
}
|
||||
|
||||
// Let's only decode one track at a time. Wait for the consumer to finish reading the track.
|
||||
media_log.notice("audio_decoder: waiting until track is consumed...");
|
||||
thread_ctrl::wait_on(track_fully_consumed, false);
|
||||
track_fully_consumed = false;
|
||||
}
|
||||
|
||||
media_log.notice("audio_decoder: finished playlist");
|
||||
});
|
||||
}
|
||||
|
||||
u32 audio_decoder::set_next_index(bool next)
|
||||
{
|
||||
return m_context.step_track(next);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <thread>
|
||||
#include "Utilities/StrUtil.h"
|
||||
#include "Utilities/Thread.h"
|
||||
#include "Emu/Cell/Modules/cellMusic.h"
|
||||
|
||||
namespace utils
|
||||
{
|
||||
|
|
@ -49,22 +50,26 @@ namespace utils
|
|||
audio_decoder();
|
||||
~audio_decoder();
|
||||
|
||||
void set_path(const std::string& path);
|
||||
void set_context(music_selection_context context);
|
||||
void set_swap_endianness(bool swapped);
|
||||
void clear();
|
||||
void stop();
|
||||
void decode();
|
||||
u32 set_next_index(bool next);
|
||||
|
||||
std::mutex m_mtx;
|
||||
shared_mutex m_mtx;
|
||||
const s32 sample_rate = 48000;
|
||||
std::vector<u8> data;
|
||||
atomic_t<u64> m_size = 0;
|
||||
atomic_t<u64> duration_ms = 0;
|
||||
atomic_t<bool> track_fully_decoded{false};
|
||||
atomic_t<bool> track_fully_consumed{false};
|
||||
atomic_t<bool> has_error{false};
|
||||
std::deque<std::pair<u64, u64>> timestamps_ms;
|
||||
|
||||
private:
|
||||
bool m_swap_endianness = false;
|
||||
std::string m_path;
|
||||
music_selection_context m_context{};
|
||||
std::unique_ptr<named_thread<std::function<void()>>> m_thread;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,4 +80,5 @@ template u32 get_yaml_node_value<u32>(YAML::Node, std::string&);
|
|||
template u64 get_yaml_node_value<u64>(YAML::Node, std::string&);
|
||||
template s64 get_yaml_node_value<s64>(YAML::Node, std::string&);
|
||||
template f64 get_yaml_node_value<f64>(YAML::Node, std::string&);
|
||||
template std::string get_yaml_node_value<std::string>(YAML::Node, std::string&);
|
||||
template cheat_info get_yaml_node_value<cheat_info>(YAML::Node, std::string&);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue