multi sample buttons

This commit is contained in:
mrbesen 2021-12-19 15:53:57 +01:00
parent 3585f6a538
commit 2f0c25c421
Signed by untrusted user: MrBesen
GPG Key ID: 596B2350DCD67504
5 changed files with 80 additions and 68 deletions

View File

@ -16,15 +16,22 @@ public:
std::vector<std::string> devices;
};
struct ButtonConfig {
std::string name;
struct SampleConfig {
std::string file;
std::string key;
uint64_t offset;
uint64_t length;
float volume;
bool isValid() const;
};
struct ButtonConfig {
std::string name;
std::string key;
uint8_t width; // default is 6
std::vector<SampleConfig> samples;
bool isValid() const;
};

View File

@ -12,20 +12,20 @@ class SoundButton : public QPushButton
Q_OBJECT
public:
explicit SoundButton(const std::string& filename, const std::string& name_ = "", const std::string& keycombo = "", QWidget* parent = nullptr);
struct Sample {
std::string file;
uint64_t startms = 0;
uint64_t lengthms = 0; // ignored when length = 0
float volume = 1.f;
};
explicit SoundButton(const std::string& name_ = "", const std::string& keycombo = "", QWidget* parent = nullptr);
~SoundButton();
const std::string& getName() const;
const std::string& getFile() const;
const std::string& getKeyCombo() const;
uint64_t getStartMS() const;
uint64_t getLengthMS() const;
float getVolume() const;
void setStartMS(uint64_t startms);
void setLengthMS(uint64_t lengthms);
void setVolume(float v);
void addSample(Sample& sample);
void setHighlighted(bool highlighted);
@ -42,11 +42,10 @@ private:
uint64_t id;
std::string name;
std::string file;
std::string keycombo;
uint64_t startms = 0;
uint64_t lengthms = 0; // ignored when length = 0
float volume = 1.f;
uint8_t currentSample = 0;
std::vector<Sample> samples;
bool highlighted = false;
bool disabled = false;

View File

@ -40,14 +40,30 @@ void from_json(const json& j, Config::AudioConfig& ac) {
readVector(ac.devices, j.value("devices", json::array()));
}
void from_json(const json& j, Config::SampleConfig& sc) {
sc.file = j.value("file", "");
sc.offset = j.value("offset", 0);
sc.length = j.value("length", 0);
sc.volume = j.value("volume", 1.f);
}
void from_json(const json& j, Config::ButtonConfig& bc) {
bc.name = j.value("name", "");
bc.file = j.value("file", "");
bc.key = j.value("key", "");
bc.offset = j.value("offset", 0);
bc.length = j.value("length", 0);
bc.volume = j.value("volume", 1.f);
bc.width = j.value("width", 6);
// make it possible to volume control all samples from one value
float volume = j.value("value", 1.0);
if(j.contains("samples")) {
// sample liste
readVector(bc.samples, j["samples"]);
for(Config::SampleConfig& sc : bc.samples) {
sc.volume *= volume;
}
} else if(j.contains("file")) {
bc.samples.push_back(j); // implizit cast
}
}
void from_json(const json& j, Config::RootConfig& rc) {
@ -64,10 +80,15 @@ void from_json(const json& j, Config::RootConfig& rc) {
rc.audioPath = j.value("audioPath", "");
}
bool Config::ButtonConfig::isValid() const {
bool Config::SampleConfig::isValid() const {
return !file.empty();
}
bool Config::ButtonConfig::isValid() const {
bool validfound = std::any_of(samples.begin(), samples.end(), [](const SampleConfig& sc){ return sc.isValid(); });
return !samples.empty() && !name.empty() && validfound;
}
void Config::load() {
std::ifstream stream(binaryPath + file);
json json;

View File

@ -169,12 +169,13 @@ void MainWindow::loadButtonsFromConfig() {
for (const Config::ButtonConfig& bc : line) {
if (!bc.isValid()) continue;
SoundButton* sb = new SoundButton(bc.file, bc.name, bc.key);
sb->setStartMS(bc.offset);
sb->setLengthMS(bc.length);
sb->setVolume(bc.volume);
SoundButton* sb = new SoundButton(bc.name, bc.key);
for(const Config::SampleConfig& sc : bc.samples) {
if(!sc.isValid()) continue;
Log::info << "Button: " << bc.name << ": " << bc.file << " " << x << " " << y;
SoundButton::Sample sample = {sc.file, sc.offset, sc.length, sc.volume};
sb->addSample(sample);
}
soundbuttons.push_back(sb);

View File

@ -8,9 +8,7 @@
uint64_t SoundButton::nextid = 0;
SoundButton::SoundButton(const std::string& filename, const std::string& name_, const std::string& keycombo, QWidget* parent) : QPushButton(parent), id(nextid++), file(filename), keycombo(keycombo) {
name = (name_.empty() ? filename : name_);
SoundButton::SoundButton(const std::string& name_, const std::string& keycombo, QWidget* parent) : QPushButton(parent), id(nextid++), name(name_), keycombo(keycombo) {
QString info = getInfo();
setText(info);
setObjectName(QString::fromStdString("soundButton" + std::to_string(id)));
@ -34,36 +32,12 @@ const std::string& SoundButton::getName() const {
return name;
}
const std::string& SoundButton::getFile() const {
return file;
}
const std::string& SoundButton::getKeyCombo() const {
return keycombo;
}
uint64_t SoundButton::getStartMS() const {
return startms;
}
uint64_t SoundButton::getLengthMS() const {
return lengthms;
}
float SoundButton::getVolume() const {
return volume;
}
void SoundButton::setStartMS(uint64_t startms_) {
startms = startms_;
}
void SoundButton::setLengthMS(uint64_t lengthms_) {
lengthms = lengthms_;
}
void SoundButton::setVolume(float v) {
volume = v;
void SoundButton::addSample(Sample& s) {
samples.push_back(s);
}
void SoundButton::setHighlighted(bool highlighted_) {
@ -78,33 +52,43 @@ void SoundButton::paintEvent(QPaintEvent* event) {
QPainter painter(this);
if(highlighted) {
QSize s = size();
QRect rect(HIGHLIGHTBORDEROFFSET, HIGHLIGHTBORDEROFFSET, s.width()-HIGHLIGHTBORDEROFFSET*2, s.height()-HIGHLIGHTBORDEROFFSET*2);
QRect rect(HIGHLIGHTBORDEROFFSET, HIGHLIGHTBORDEROFFSET, s.width() - HIGHLIGHTBORDEROFFSET*2, s.height() - HIGHLIGHTBORDEROFFSET*2);
painter.setPen(QPen(Qt::red));
painter.drawRect(rect);
}
QString text = "";
if(samples.size() > 1) {
QString text = QString::fromStdString(std::to_string(currentSample+1) + "/" + std::to_string(samples.size()));
// cancel if nothing to print
if(text.isEmpty())
return;
painter.setPen(QPen(Qt::white));
QPoint textPos(0, painter.fontMetrics().height());
textPos.rx() = width() - painter.fontMetrics().horizontalAdvance(text) - 6;
painter.drawText(textPos, text);
painter.setPen(QPen(Qt::white));
QPoint textPos(0, painter.fontMetrics().height());
textPos.rx() = width() - painter.fontMetrics().horizontalAdvance(text) - 6;
painter.drawText(textPos, text);
}
}
void SoundButton::play() {
if(disabled) return;
uint64_t endms = (lengthms == 0 ? 0 : startms + lengthms);
if(samples.size() == 0) {
Log::error << "Button " << name << " has no sample set";
setDisabled();
return;
}
const Sample& sample = samples.at(currentSample++);
if(currentSample >= samples.size())
currentSample = 0;
uint64_t endms = (sample.lengthms == 0 ? 0 : sample.startms + sample.lengthms);
try {
Sound::instance().addPlayback(file, volume, startms, endms);
Sound::instance().addPlayback(sample.file, sample.volume, sample.startms, endms);
} catch(const std::exception& e) {
Log::error << "Catched Exception when plaing Audio File: " << file;
Log::error << "Catched Exception when plaing Audio File: " << sample.file;
setDisabled();
}
repaint();
}
void SoundButton::setDisabled() {