Verified Commit 6abe81a1 authored by Phobos D'thorga's avatar Phobos D'thorga 🐲
Browse files

* Further experiments and learning with Opus encoding, as well as bug-fixes.

parent a1901e35
Pipeline #1034 passed with stages
in 29 minutes and 31 seconds
......@@ -80,8 +80,7 @@ using namespace GkXmpp;
#define OGG_VORBIS_READ (1024)
GkAudioEncoding::GkAudioEncoding(const QPointer<QBuffer> &audioInputBuf, const QPointer<QBuffer> &audioOutputBuf,
QPointer<GekkoFyre::GkLevelDb> database, QPointer<QAudioOutput> audioOutput,
GkAudioEncoding::GkAudioEncoding(QPointer<GekkoFyre::GkLevelDb> database, QPointer<QAudioOutput> audioOutput,
QPointer<QAudioInput> audioInput, QPointer<GekkoFyre::StringFuncs> stringFuncs,
QPointer<GekkoFyre::GkEventLogger> eventLogger, QObject *parent) : QObject(parent)
{
......@@ -101,8 +100,6 @@ GkAudioEncoding::GkAudioEncoding(const QPointer<QBuffer> &audioInputBuf, const Q
//
// Open and initialize the buffers for reading and writing purposes!
m_encoded_buf = new QBuffer(this);
gkAudioInputBuf = std::move(audioInputBuf);
gkAudioOutputBuf = std::move(audioOutputBuf);
QObject::connect(this, SIGNAL(pauseEncode()), this, SLOT(stopCaller()));
QObject::connect(this, SIGNAL(error(const QString &, const GekkoFyre::System::Events::Logging::GkSeverity &)),
......@@ -110,6 +107,11 @@ GkAudioEncoding::GkAudioEncoding(const QPointer<QBuffer> &audioInputBuf, const Q
QObject::connect(this, SIGNAL(recStatus(const GekkoFyre::GkAudioFramework::GkAudioRecordStatus &)),
this, SLOT(setRecStatus(const GekkoFyre::GkAudioFramework::GkAudioRecordStatus &)));
//
// Setup I/O!
m_audioInputBuf = gkAudioInput->start();
QObject::connect(m_audioInputBuf, &QIODevice::readyRead, this, &GkAudioEncoding::onReadyRead);
return;
}
......@@ -128,7 +130,7 @@ GkAudioEncoding::~GkAudioEncoding()
}
if (m_out_file.isOpen()) {
m_out_file.close();
m_out_file.commit();
}
}
......@@ -236,11 +238,6 @@ void GkAudioEncoding::startCaller(const QFileInfo &media_path, const qint32 &bit
throw std::invalid_argument(tr("An invalid or currently unsupported audio source has been chosen!").toStdString());
}
//
// Clear the audio buffer prior to use!
m_buffer.clear();
m_buffer.shrink_to_fit();
//
// Set frame-size!
m_frameSize = frame_size;
......@@ -370,94 +367,76 @@ void GkAudioEncoding::encodeOpus(const qint32 &bitrate, const GkAudioSource &aud
//
std::lock_guard<std::mutex> lock_g(m_encodeOggOpusMtx);
QDir::setCurrent(media_path.absolutePath());
m_out_file.setFileName(media_path.fileName());
m_out_file.setFileName(media_path.absoluteFilePath());
if (media_path.exists() && media_path.isFile()) {
throw std::invalid_argument(tr("Attempting to encode towards file, \"%1\", has failed! Error: file already exists.")
.arg(media_path.absoluteFilePath()).toStdString());
.arg(media_path.absoluteFilePath()).toStdString());
}
m_out_file.open(QIODevice::ReadWrite, QIODevice::NewOnly);
m_out_file.open(QIODevice::WriteOnly);
if (!m_out_file.isOpen()) {
throw std::runtime_error(tr("Error with opening file, \"%1\"!").arg(media_path.absoluteFilePath()).toStdString());
}
//
// Read any pre-existing data into the QByteArray, such as if we started encoding with Ogg Opus at a previous stage
// but then paused for some reason or another!
if (!m_out_file.readAll().isEmpty()) {
m_fileData = m_out_file.readAll();
qint32 err = 0;
if (audio_src == GkAudioSource::Input) {
if (gkAudioInput->state() != QAudio::ActiveState) {
gkEventLogger->publishEvent(tr("Opus encoding has terminated early. Reason: Audio 'input' was not active."), GkSeverity::Error, "",
false, true, false, true, false);
emit recStatus(GkAudioRecordStatus::Defunct);
return;
}
} else if (audio_src == GkAudioSource::Output) {
if (gkAudioOutput->state() != QAudio::ActiveState) {
gkEventLogger->publishEvent(tr("Opus encoding has terminated early. Reason: Audio 'output' was not active."), GkSeverity::Error, "",
false, true, false, true, false);
emit recStatus(GkAudioRecordStatus::Defunct);
return;
}
} else {
throw std::invalid_argument(tr("An invalid or currently unsupported audio source has been chosen!").toStdString());
}
qint32 err = 0;
const qint32 m_size = qint32(sizeof(float)) * m_channels * frame_size;
gkEventLogger->publishEvent(tr("Initiate encoding with Opus as the codec! Frame count: %1. Sample rate: %2. Bit rate: %3. Channels: %4.")
.arg(QString::number(m_buffer.size()), QString::number(AUDIO_OPUS_DEFAULT_SAMPLE_RATE), QString::number(bitrate), QString::number(m_channels)), GkSeverity::Info, "",
false, true, false, false, false);
m_initialized = true;
m_opusEncoder = opus_encoder_create(AUDIO_OPUS_DEFAULT_SAMPLE_RATE, m_channels, OPUS_APPLICATION_VOIP, &err);
if (err != OPUS_OK || !m_opusEncoder) {
throw std::runtime_error(gkStringFuncs->handleOpusError(err).toStdString());
throw std::runtime_error(tr("Error writing to file, \"%1\", via Opus encoder. Error: %2")
.arg(media_path.fileName(), gkStringFuncs->handleOpusError(err)).toStdString());
}
//
// Set the desired bit-rate while other parameters can be set as needed, also. Just remember that the Opus library
// is designed to have good defaults by standard, so only set parameters you know that are really needed. Doing so
// otherwise is likely to result in worsened multimedia quality and/or overall performance.
//
m_initialized = true;
err = opus_encoder_ctl(m_opusEncoder, OPUS_SET_BITRATE(bitrate));
gkEventLogger->publishEvent(tr("Initiate encoding with Opus as the codec! Frame size: %1. Sample rate: %2. Bit rate: %3. Channels: %4.")
.arg(QString::number(m_size), QString::number(AUDIO_OPUS_DEFAULT_SAMPLE_RATE), QString::number(bitrate), QString::number(m_channels)), GkSeverity::Info, "",
false, true, false, false, false);
err = opus_encoder_ctl(m_opusEncoder, OPUS_SET_BITRATE(bitrate * 1000)); // NOTE: The slider widget on `gkaudioplaydialog.ui` measures bit-rates in 'kilobits per second'!
if (err != OPUS_OK) {
throw std::runtime_error(gkStringFuncs->handleOpusError(err).toStdString());
throw std::runtime_error(tr("Issue encountered with setting bit-rate for encoding with Opus. Error: %1")
.arg(gkStringFuncs->handleOpusError(err)).toStdString());
}
refreshAudioBuffers(audio_src, m_size); // Execute this just once before the do-while loop, in order to prime the variables beforehand!
// std::this_thread::sleep_for (std::chrono::milliseconds(AUDIO_ENCODING_VAR_PRIME_SLEEP_MILLISECS));
do {
if (!m_initialized) {
if (m_opusEncoder) {
opus_encoder_destroy(m_opusEncoder);
}
return;
qint32 ret = 0;
qint64 file_pos = 0;
while (1) {
if (!m_initialized || m_recActive != GkAudioRecordStatus::Active) {
break;
}
if (audio_src == GkAudioSource::Input) {
if (gkAudioInput->state() != QAudio::ActiveState) {
gkEventLogger->publishEvent(tr("Opus encoding has terminated early. Reason: Audio 'input' was not active."), GkSeverity::Error, "",
false, true, false, true, false);
emit recStatus(GkAudioRecordStatus::Defunct);
if (m_opusEncoder) {
opus_encoder_destroy(m_opusEncoder);
}
return;
}
} else if (audio_src == GkAudioSource::Output) {
if (gkAudioOutput->state() != QAudio::ActiveState) {
gkEventLogger->publishEvent(tr("Opus encoding has terminated early. Reason: Audio 'output' was not active."), GkSeverity::Error, "",
false, true, false, true, false);
emit recStatus(GkAudioRecordStatus::Defunct);
if (m_opusEncoder) {
opus_encoder_destroy(m_opusEncoder);
}
return;
}
} else {
throw std::invalid_argument(tr("An invalid or currently unsupported audio source has been chosen!").toStdString());
}
ret = m_buffer.size();
if (ret > 0) {
const auto ba_val = opusEncodeHelper(m_opusEncoder, media_path);
refreshAudioBuffers(audio_src, m_size);
const auto result = opusEncodeHelper(m_opusEncoder, frame_size, m_size, AUDIO_OPUS_MAX_FRAMES_PER_BUFFER * 3);
if (!result.isEmpty()) {
//
// Write out the encoded, Ogg Opus data, to the given output file in question!
m_fileData.insert(m_out_file.size() + 1, result.data());
m_out_file.seek(0);
m_out_file.write(m_fileData);
m_out_file.flush();
// Commit out the memory buffer to the file itself!
m_out_file.seek(file_pos);
m_out_file.write(ba_val.constData());
file_pos += ba_val.size();
m_out_file.commit();
} else {
break;
}
} while (!m_buffer.isEmpty() || m_recActive == GkAudioRecordStatus::Active);
}
//
// Create and initiate the encoded Opus multimedia file comments!
......@@ -478,9 +457,9 @@ void GkAudioEncoding::encodeOpus(const qint32 &bitrate, const GkAudioSource &aud
.arg(gkStringFuncs->handleOpusError(err)).toStdString());
}
//
// Perform any cleanup operations now...
opusCleanup();
gkEventLogger->publishEvent(tr("Finished encoding with the Opus codec! File: %1").arg(media_path.absoluteFilePath()),
GkSeverity::Info, "", true, true, false, false, true);
} catch (const std::exception &e) {
gkStringFuncs->print_exception(e);
}
......@@ -508,24 +487,17 @@ void GkAudioEncoding::encodeVorbis(const qint32 &bitrate, qint32 sample_rate, co
//
std::lock_guard<std::mutex> lock_g(m_encodeOggVorbisMtx);
QDir::setCurrent(media_path.absolutePath());
m_out_file.setFileName(media_path.fileName());
m_out_file.setFileName(media_path.absoluteFilePath());
if (media_path.exists() && media_path.isFile()) {
throw std::invalid_argument(tr("Attempting to encode towards file, \"%1\", has failed! Error: file already exists.")
.arg(media_path.absoluteFilePath()).toStdString());
}
m_out_file.open(QIODevice::ReadWrite, QIODevice::NewOnly);
m_out_file.open(QIODevice::WriteOnly);
if (!m_out_file.isOpen()) {
throw std::runtime_error(tr("Error with opening file, \"%1\"!").arg(media_path.absoluteFilePath()).toStdString());
}
//
// Read any pre-existing data into the QByteArray, such as if we started encoding with Ogg Opus at a previous stage
// but then paused for some reason or another!
if (!m_out_file.readAll().isEmpty()) {
m_fileData = m_out_file.readAll();
}
const qint32 m_size = frame_size * m_channels;
m_initialized = true;
do {
......@@ -533,16 +505,6 @@ void GkAudioEncoding::encodeVorbis(const qint32 &bitrate, qint32 sample_rate, co
return;
}
if (audio_src == GkAudioSource::Input) {
gkAudioInputBuf->seek(0);
m_buffer.append(gkAudioInputBuf->readAll());
} else if (audio_src == GkAudioSource::Output) {
gkAudioOutputBuf->seek(0);
m_buffer.append(gkAudioOutputBuf->readAll());
} else {
throw std::invalid_argument(tr("An invalid or currently unsupported audio source has been chosen!").toStdString());
}
std::vector<qint32> input_frame;
input_frame.reserve(m_size);
for (qint32 i = 0; i < m_size; ++i) {
......@@ -599,24 +561,17 @@ void GkAudioEncoding::encodeFLAC(const qint32 &bitrate, qint32 sample_rate, cons
//
std::lock_guard<std::mutex> lock_g(m_encodeFlacMtx);
QDir::setCurrent(media_path.absolutePath());
m_out_file.setFileName(media_path.fileName());
m_out_file.setFileName(media_path.absoluteFilePath()); // This supports either no path (i.e. just the filename), a relative path, or an absolute path!
if (media_path.exists() && media_path.isFile()) {
throw std::invalid_argument(tr("Attempting to encode towards file, \"%1\", has failed! Error: file already exists.")
.arg(media_path.absoluteFilePath()).toStdString());
}
m_out_file.open(QIODevice::ReadWrite, QIODevice::NewOnly);
m_out_file.open(QIODevice::WriteOnly);
if (!m_out_file.isOpen()) {
throw std::runtime_error(tr("Error with opening file, \"%1\"!").arg(media_path.absoluteFilePath()).toStdString());
}
//
// Read any pre-existing data into the QByteArray, such as if we started encoding with Ogg Opus at a previous stage
// but then paused for some reason or another!
if (!m_out_file.readAll().isEmpty()) {
m_fileData = m_out_file.readAll();
}
const qint32 m_size = frame_size * m_channels;
m_initialized = true;
do {
......@@ -624,16 +579,6 @@ void GkAudioEncoding::encodeFLAC(const qint32 &bitrate, qint32 sample_rate, cons
return;
}
if (audio_src == GkAudioSource::Input) {
gkAudioInputBuf->seek(0);
m_buffer.append(gkAudioInputBuf->readAll());
} else if (audio_src == GkAudioSource::Output) {
gkAudioOutputBuf->seek(0);
m_buffer.append(gkAudioOutputBuf->readAll());
} else {
throw std::invalid_argument(tr("An invalid or currently unsupported audio source has been chosen!").toStdString());
}
std::vector<qint32> input_frame;
input_frame.reserve(m_size);
for (qint32 i = 0; i < m_size; ++i) {
......@@ -671,87 +616,55 @@ void GkAudioEncoding::encodeFLAC(const qint32 &bitrate, qint32 sample_rate, cons
}
/**
* @brief GkAudioEncoding::refreshAudioBuffers refreshes/updates the audio buffers for both the audio input and/or output
* devices.
* @brief GkAudioEncoding::onReadyRead
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param audio_src The audio source for which buffers to update henceforth.
* @param buf_size The minimum size of the buffer that must be reached to exit the internal loop within this function.
*/
void GkAudioEncoding::refreshAudioBuffers(const GkAudioSource &audio_src, const qint32 &buf_size)
void GkAudioEncoding::onReadyRead()
{
std::lock_guard<std::mutex> lock_guard(m_refreshAudioBufs);
if (audio_src == GkAudioSource::Input) {
if (gkAudioInput->state() != QAudio::ActiveState) {
m_recActive = GkAudioRecordStatus::Defunct; // Has to modify the variable directly, since we are working from differing threads than the main, GUI-thread!
return;
}
do {
gkAudioInputBuf->seek(0);
m_buffer.append(gkAudioInputBuf->readAll());
} while (m_buffer.isEmpty() && m_buffer.size() < buf_size);
} else if (audio_src == GkAudioSource::Output) {
if (gkAudioOutput->state() != QAudio::ActiveState) {
m_recActive = GkAudioRecordStatus::Defunct; // Has to modify the variable directly, since we are working from differing threads than the main, GUI-thread!
return;
}
do {
gkAudioOutputBuf->seek(0);
m_buffer.append(gkAudioOutputBuf->readAll());
} while (m_buffer.isEmpty() && m_buffer.size() < buf_size);
} else {
return;
}
m_buffer.append(m_audioInputBuf->readAll()); // Record QAudioInput to the buffer object, `m_buffer`!
return;
}
/**
* @brief GkAudioEncoding::opusEncodeHelper performs the actual encoding of given QByteArray data (obtained via either
* QAudioInput and/or QAudioOutput) into Ogg Opus data before returning said data also as a QByteArray, for easy handling
* via other Qt functions/code.
* @brief GkAudioEncoding::opusEncodeHelper
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param opusEncoder The Ogg Opus object required for doing the act of encoding itself.
* @param frame_size The frame size to use when encoding.
* @param max_packet_size The maximum packet size to use when encoding.
* @return The encoded Ogg Opus data, returned as a QByteArray for easy handling via other Qt functions/code.
* @param opusEnc
* @param media_path
* @return
*/
QByteArray GkAudioEncoding::opusEncodeHelper(OpusEncoder *opusEncoder, const qint32 &frame_size,
const qint32 &m_size, const qint32 &max_packet_size)
QByteArray GkAudioEncoding::opusEncodeHelper(OpusEncoder *opusEnc, const QFileInfo &media_path)
{
try {
if (!m_initialized) {
return QByteArray();
}
QByteArray input = m_buffer.mid(0, m_size);
QByteArray output = QByteArray(AUDIO_OPUS_MAX_FRAMES_PER_BUFFER * 3, char(0));
m_buffer.remove(0, m_size);
if (input.isEmpty()) {
emit error(tr("No input data to work with!"), GkSeverity::Error);
return QByteArray();
opus_int16 input_frame[AUDIO_OPUS_FRAMES_PER_BUFFER] = {};
unsigned char compressed_frame[AUDIO_OPUS_MAX_FRAMES_PER_BUFFER] = {};
QByteArray ba_ret_val;
const auto total_bytes_ready = m_buffer.size() * sizeof(opus_int16);
for (qint32 i = 0; i < total_bytes_ready; ++i) {
//
// Convert from littleEndian...
for (qint32 j = 0; j < AUDIO_OPUS_FRAMES_PER_BUFFER; ++j) {
input_frame[j] = qFromLittleEndian<opus_int16>(m_buffer.data() + j * sizeof(opus_int16));
}
//
// Encode the frame...
const qint32 nbBytes = opus_encode_float(opusEncoder, reinterpret_cast<const float *>(input.constData()), frame_size,
reinterpret_cast<uchar *>(output.data()), max_packet_size);
const opus_int32 nbBytes = opus_encode(opusEnc, input_frame, AUDIO_OPUS_FRAMES_PER_BUFFER, compressed_frame, AUDIO_OPUS_MAX_FRAMES_PER_BUFFER);
if (nbBytes < 0) {
throw std::runtime_error(tr("Error encoding with Opus. Given output was expected to be larger than zero, but instead were: %1 bytes.")
.arg(QString::number(nbBytes)).toStdString());
emit error(tr("Error encoding to file: %1").arg(media_path.absoluteFilePath()), GkSeverity::Fatal);
opusCleanup();
}
//
// Write out the encoded, Ogg Opus data, to the given output file in question!
output.resize(nbBytes);
return output;
} catch (const std::exception &e) {
std::throw_with_nested(std::runtime_error(tr("Ogg Opus encoding has failed! Error: %1")
.arg(QString::fromStdString(e.what())).toStdString()));
m_totalCompBytesWritten += nbBytes;
emit bytesRead(m_totalCompBytesWritten, false);
m_buffer.remove(0, AUDIO_OPUS_FRAMES_PER_BUFFER * sizeof(opus_int16));
ba_ret_val.append(reinterpret_cast<char *>(&compressed_frame[0]), AUDIO_OPUS_FRAMES_PER_BUFFER * sizeof(opus_int16));
}
return QByteArray();
if (ba_ret_val.isEmpty()) {
return QByteArray();
}
return ba_ret_val;
}
/**
......@@ -762,10 +675,6 @@ QByteArray GkAudioEncoding::opusEncodeHelper(OpusEncoder *opusEncoder, const qin
void GkAudioEncoding::opusCleanup()
{
emit recStatus(GkAudioRecordStatus::Finished);
if (m_out_file.isOpen()) {
m_out_file.close();
}
if (m_opusComments) {
ope_comments_destroy(m_opusComments);
}
......
......@@ -53,10 +53,10 @@
#include <cstdio>
#include <memory>
#include <string>
#include <QFile>
#include <QObject>
#include <QBuffer>
#include <QPointer>
#include <QSaveFile>
#include <QIODevice>
#include <QByteArray>
#include <QAudioInput>
......@@ -69,6 +69,8 @@ extern "C"
#endif
#include "src/contrib/opus/include/opus.h"
#include "src/contrib/opus/include/opus_types.h"
#include "src/contrib/opus/include/opus_defines.h"
#ifdef __cplusplus
}
......@@ -128,8 +130,7 @@ class GkAudioEncoding : public QObject {
Q_OBJECT
public:
explicit GkAudioEncoding(const QPointer<QBuffer> &audioInputBuf, const QPointer<QBuffer> &audioOutputBuf,
QPointer<GekkoFyre::GkLevelDb> database, QPointer<QAudioOutput> audioOutput,
explicit GkAudioEncoding(QPointer<GekkoFyre::GkLevelDb> database, QPointer<QAudioOutput> audioOutput,
QPointer<QAudioInput> audioInput, QPointer<GekkoFyre::StringFuncs> stringFuncs,
QPointer<GekkoFyre::GkEventLogger> eventLogger, QObject *parent = nullptr);
~GkAudioEncoding() override;
......@@ -156,7 +157,7 @@ private slots:
void encodeFLAC(const qint32 &bitrate, qint32 sample_rate, const GekkoFyre::Database::Settings::GkAudioSource &audio_src,
const QFileInfo &media_path, const qint32 &frame_size = AUDIO_FRAMES_PER_BUFFER);
void refreshAudioBuffers(const GekkoFyre::Database::Settings::GkAudioSource &audio_src, const qint32 &buf_size);
void onReadyRead();
signals:
void pauseEncode();
......@@ -166,6 +167,7 @@ signals:
void initialize();
void recStatus(const GekkoFyre::GkAudioFramework::GkAudioRecordStatus &status);
void bytesRead(const qint64 &bytes, const bool &uncompressed = false);
private:
QPointer<GekkoFyre::GkLevelDb> gkDb;
......@@ -176,6 +178,8 @@ private:
// QAudioSystem initialization and buffers
QPointer<QAudioInput> gkAudioInput;
QPointer<QAudioOutput> gkAudioOutput;
qint64 m_totalUncompBytesRead;
qint64 m_totalCompBytesWritten;
//
// Status variables
......@@ -184,13 +188,11 @@ private:
//
// Encoder variables
bool m_initialized = false; // Whether an encoding operation has begun or not; therefore block other attempts until this singular one has stopped.
QPointer<QIODevice> m_audioInputBuf; // The QIODevice for this particular audio device.
QByteArray m_buffer; // A QByteArray, providing more readily accessible information as needed by the FLAC, Ogg Vorbis, Ogg Opus, etc. encoders.
QByteArray m_fileData; // For any pre-existing data, such as an Ogg Opus file that had already started encoding previously.
QPointer<QBuffer> gkAudioInputBuf; // For reading RAW PCM audio data from a given QAudioInput into.
QPointer<QBuffer> gkAudioOutputBuf; // For reading RAW PCM audio data from a given QAudioOutput into.
QPointer<QBuffer> m_encoded_buf; // For holding the encoded data whether it be FLAC, Ogg Vorbis, Ogg Opus, etc. as calculated from `record_input_buf`.
SndfileHandle m_handle_in; // The libsndfile handler, for all related operations such as reading, writing (and hence conversion), etc.
QFile m_out_file;
QSaveFile m_out_file;
//
// Opus related
......@@ -209,8 +211,7 @@ private:
std::thread m_encodeVorbisThread;
std::thread m_encodeFLACThread;
[[nodiscard]] QByteArray opusEncodeHelper(OpusEncoder *opusEncoder, const qint32 &frame_size,
const qint32 &m_size, const qint32 &max_packet_size);
QByteArray opusEncodeHelper(OpusEncoder *opusEnc, const QFileInfo &media_path);
void opusCleanup();
void processByteArray();
......
......@@ -80,6 +80,8 @@ GkAudioPlayDialog::GkAudioPlayDialog(QPointer<GkLevelDb> database,
// Create SIGNALS and SLOTS
QObject::connect(this, SIGNAL(recStatus(const GekkoFyre::GkAudioFramework::GkAudioRecordStatus &)),
gkAudioEncoding, SLOT(setRecStatus(const GekkoFyre::GkAudioFramework::GkAudioRecordStatus &)));
QObject::connect(gkAudioEncoding, SIGNAL(bytesRead(const qint64 &, const bool &)),
this, SLOT(setBytesRead(const const qint64 &, const bool &)));
QObject::connect(this, SIGNAL(cleanupForms(const GekkoFyre::GkAudioFramework::GkClearForms &)),
this, SLOT(clearForms(const GekkoFyre::GkAudioFramework::GkClearForms &)));
......@@ -459,6 +461,30 @@ void GkAudioPlayDialog::on_horizontalSlider_playback_rec_bitrate_valueChanged(in
return;
}
/**
* @brief GkAudioPlayDialog::setBytesRead adjusts the GUI widget(s) in question to display the amount of bytes read so
* far, whether it be for uncompressed or compressed data.
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param bytes The amount of data read so far, measured in bytes.
* @param uncompressed Are we displaying measurements for uncompressed or compressed data?
*/
void GkAudioPlayDialog::setBytesRead(const qint64 &bytes, const bool &uncompressed)
{
// const auto hr_file_size = gkStringFuncs->fileSizeHumanReadable(bytes);
if (uncompressed) {
encode_uncompressed_bytes = bytes;
} else {
encode_compressed_bytes = bytes;
}
if (encode_compressed_bytes <= encode_uncompressed_bytes) {
ui->progressBar_playback->setFormat("%p%");
ui->progressBar_playback->setValue((encode_uncompressed_bytes / encode_compressed_bytes) * 100);
}
return;
}
/**
* @brief GkAudioPlayDialog::resetStopButtonColor
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
......
......@@ -98,6 +98,8 @@ private slots:
void on_comboBox_playback_rec_codec_currentIndexChanged(int index);
void on_horizontalSlider_playback_rec_bitrate_valueChanged(int value);
void setBytesRead(const qint64 &bytes, const bool &uncompressed = false);
void resetStopButtonColor();
void clearForms(const GekkoFyre::GkAudioFramework::GkClearForms &cat);
......@@ -144,6 +146,8 @@ private:
std::shared_ptr<AudioFile<double>> gkAudioFile; // Buffer for playback
GekkoFyre::GkAudioFramework::AudioFileInfo gkAudioFileInfo; // Information on file destined for playback!
GekkoFyre::Database::Settings::GkAudioChannels m_audioChannels; // Audio channel information for both playback and recording!
qint64 encode_compressed_bytes;
qint64 encode_uncompressed_bytes;
template <typename T>
struct gkConvertDoubleToFloat {
......
......@@ -735,8 +735,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
//
// Initialize the audio codec encoding/decoding libraries!
//
gkAudioEncoding = new GkAudioEncoding(gkAudioInputBuf, gkAudioOutputBuf, gkDb, gkAudioOutput,
gkAudioInput, gkStringFuncs, gkEventLogger, &gkAudioInputThread);
gkAudioEncoding = new GkAudioEncoding(gkDb, gkAudioOutput, gkAudioInput, gkStringFuncs, gkEventLogger, &gkAudioInputThread);
gkAudioEncoding->moveToThread(&gkAudioInputThread);
QObject::connect(&gkAudioInputThread, &QThread::finished, gkAudioEncoding, &QObject::deleteLater);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment