Use spectrum plugin for moodbar

This commit is contained in:
Jonas Kvinge 2024-09-22 13:24:21 +02:00
parent fa96cdfaea
commit 7e0231cb77
4 changed files with 75 additions and 4 deletions

View File

@ -22,6 +22,9 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <glib-object.h>
#include <gst/gst.h>
#include <QList> #include <QList>
#include <QByteArray> #include <QByteArray>
@ -61,6 +64,29 @@ void MoodbarBuilder::Init(const int bands, const int rate_hz) {
} }
void MoodbarBuilder::AddFrame(const GValue *magnitudes, const int size) {
if (size > barkband_table_.length()) {
return;
}
// Calculate total magnitudes for different bark bands.
double bands[sBarkBandCount]{};
for (int i = 0; i < size; ++i) {
const GValue *magnitude = gst_value_list_get_value(magnitudes, i);
bands[barkband_table_[i]] += g_value_get_float(magnitude);
}
// Now divide the bark bands into thirds and compute their total amplitudes.
double rgb[] = { 0, 0, 0 };
for (int i = 0; i < sBarkBandCount; ++i) {
rgb[(i * 3) / sBarkBandCount] += bands[i] * bands[i];
}
frames_.append(Rgb(sqrt(rgb[0]), sqrt(rgb[1]), sqrt(rgb[2])));
}
void MoodbarBuilder::AddFrame(const double *magnitudes, const int size) { void MoodbarBuilder::AddFrame(const double *magnitudes, const int size) {
if (size > barkband_table_.length()) { if (size > barkband_table_.length()) {

View File

@ -22,6 +22,8 @@
#ifndef MOODBARBUILDER_H #ifndef MOODBARBUILDER_H
#define MOODBARBUILDER_H #define MOODBARBUILDER_H
#include <glib-object.h>
#include <QtGlobal> #include <QtGlobal>
#include <QList> #include <QList>
#include <QByteArray> #include <QByteArray>
@ -31,6 +33,7 @@ class MoodbarBuilder {
explicit MoodbarBuilder(); explicit MoodbarBuilder();
void Init(const int bands, const int rate_hz); void Init(const int bands, const int rate_hz);
void AddFrame(const GValue *magnitudes, const int size);
void AddFrame(const double *magnitudes, const int size); void AddFrame(const double *magnitudes, const int size);
QByteArray Finish(const int width); QByteArray Finish(const int width);

View File

@ -99,7 +99,7 @@ void MoodbarPipeline::Start() {
GstElement *decodebin = CreateElement(QStringLiteral("uridecodebin")); GstElement *decodebin = CreateElement(QStringLiteral("uridecodebin"));
convert_element_ = CreateElement(QStringLiteral("audioconvert")); convert_element_ = CreateElement(QStringLiteral("audioconvert"));
GstElement *spectrum = CreateElement(QStringLiteral("fastspectrum")); GstElement *spectrum = CreateElement(QStringLiteral("spectrum"));
GstElement *fakesink = CreateElement(QStringLiteral("fakesink")); GstElement *fakesink = CreateElement(QStringLiteral("fakesink"));
if (!decodebin || !convert_element_ || !spectrum || !fakesink) { if (!decodebin || !convert_element_ || !spectrum || !fakesink) {
@ -118,7 +118,7 @@ void MoodbarPipeline::Start() {
return; return;
} }
builder_ = make_unique<MoodbarBuilder>(); //builder_ = make_unique<MoodbarBuilder>();
// Set properties // Set properties
@ -126,8 +126,16 @@ void MoodbarPipeline::Start() {
g_object_set(decodebin, "uri", gst_url.constData(), nullptr); g_object_set(decodebin, "uri", gst_url.constData(), nullptr);
g_object_set(spectrum, "bands", kBands, nullptr); g_object_set(spectrum, "bands", kBands, nullptr);
GstStrawberryFastSpectrum *fastspectrum = reinterpret_cast<GstStrawberryFastSpectrum*>(spectrum); //GstStrawberryFastSpectrum *fastspectrum = reinterpret_cast<GstStrawberryFastSpectrum*>(spectrum);
fastspectrum->output_callback = [this](double *magnitudes, const int size) { builder_->AddFrame(magnitudes, size); }; //fastspectrum->output_callback = [this](double *magnitudes, const int size) { builder_->AddFrame(magnitudes, size); };
{
GstPad *pad = gst_element_get_static_pad(fakesink, "src");
if (pad) {
buffer_probe_cb_id_ = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, BufferProbeCallback, this, nullptr);
gst_object_unref(pad);
}
}
// Connect signals // Connect signals
CHECKED_GCONNECT(decodebin, "pad-added", &NewPadCallback, this); CHECKED_GCONNECT(decodebin, "pad-added", &NewPadCallback, this);
@ -206,6 +214,20 @@ GstBusSyncReply MoodbarPipeline::BusCallbackSync(GstBus *bus, GstMessage *messag
MoodbarPipeline *instance = reinterpret_cast<MoodbarPipeline*>(self); MoodbarPipeline *instance = reinterpret_cast<MoodbarPipeline*>(self);
switch (GST_MESSAGE_TYPE(message)) { switch (GST_MESSAGE_TYPE(message)) {
#if 0
case GST_MESSAGE_ELEMENT:{
const GstStructure *structure = gst_message_get_structure(message);
const gchar *name = gst_structure_get_name(structure);
if (strcmp(name, "spectrum") == 0) {
const GValue *magnitudes = gst_structure_get_value(structure, "magnitude");
if (instance->builder_) {
instance->builder_->AddFrame(magnitudes, kBands);
}
}
break;
}
#endif
case GST_MESSAGE_EOS: case GST_MESSAGE_EOS:
instance->Stop(true); instance->Stop(true);
break; break;
@ -223,6 +245,24 @@ GstBusSyncReply MoodbarPipeline::BusCallbackSync(GstBus *bus, GstMessage *messag
} }
GstPadProbeReturn MoodbarPipeline::BufferProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self) {
Q_UNUSED(pad)
MoodbarPipeline *instance = reinterpret_cast<MoodbarPipeline*>(self);
GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
GstMapInfo map;
gst_buffer_map(buffer, &map, GST_MAP_READ);
instance->data_.append(reinterpret_cast<const char*>(map.data), map.size);
gst_buffer_unmap(buffer, &map);
gst_buffer_unref(buffer);
return GST_PAD_PROBE_OK;
}
void MoodbarPipeline::Stop(const bool success) { void MoodbarPipeline::Stop(const bool success) {
success_ = success; success_ = success;

View File

@ -62,6 +62,7 @@ class MoodbarPipeline : public QObject {
static void NewPadCallback(GstElement *element, GstPad *pad, gpointer self); static void NewPadCallback(GstElement *element, GstPad *pad, gpointer self);
static GstBusSyncReply BusCallbackSync(GstBus *bus, GstMessage *message, gpointer self); static GstBusSyncReply BusCallbackSync(GstBus *bus, GstMessage *message, gpointer self);
static GstPadProbeReturn BufferProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self);
private: private:
QUrl url_; QUrl url_;
@ -73,6 +74,7 @@ class MoodbarPipeline : public QObject {
bool success_; bool success_;
bool running_; bool running_;
QByteArray data_; QByteArray data_;
gint buffer_probe_cb_id_;
}; };
#endif // MOODBARPIPELINE_H #endif // MOODBARPIPELINE_H