vastly improved audio
This commit is contained in:
@@ -21,10 +21,9 @@ PanEffect::PanEffect(Clip* c) : Effect(c, EFFECT_TYPE_AUDIO, AUDIO_PAN_EFFECT) {
|
||||
void PanEffect::refresh() {}
|
||||
|
||||
Effect* PanEffect::copy(Clip* c) {
|
||||
/*PanEffect* p = new PanEffect(c);
|
||||
p->pan_val->set_value(pan_val->value());
|
||||
return p;*/
|
||||
return NULL;
|
||||
PanEffect* p = new PanEffect(c);
|
||||
p->pan_val->set_double_value(pan_val->get_double_value());
|
||||
return p;
|
||||
}
|
||||
|
||||
void PanEffect::process_audio(quint8 *samples, int nb_bytes) {
|
||||
|
||||
@@ -44,12 +44,11 @@ void ShakeEffect::refresh() {
|
||||
}
|
||||
|
||||
Effect* ShakeEffect::copy(Clip* c) {
|
||||
/*ShakeEffect* e = new ShakeEffect(c);
|
||||
e->intensity_val->set_value(intensity_val->value());
|
||||
e->rotation_val->set_value(rotation_val->value());
|
||||
e->frequency_val->set_value(frequency_val->value());
|
||||
return e;*/
|
||||
return NULL;
|
||||
ShakeEffect* e = new ShakeEffect(c);
|
||||
e->intensity_val->set_double_value(intensity_val->get_double_value());
|
||||
e->rotation_val->set_double_value(rotation_val->get_double_value());
|
||||
e->frequency_val->set_double_value(frequency_val->get_double_value());
|
||||
return e;
|
||||
}
|
||||
|
||||
void ShakeEffect::process_gl(int*, int*) {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#define SAVE_VERSION "180727"
|
||||
#define SAVE_VERSION "180814"
|
||||
|
||||
struct Config {
|
||||
Config();
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "dialogs/exportdialog.h"
|
||||
#include "dialogs/preferencesdialog.h"
|
||||
|
||||
#include "playback/audio.h"
|
||||
|
||||
#include "ui_timeline.h"
|
||||
|
||||
#include <QDebug>
|
||||
@@ -149,6 +151,8 @@ MainWindow::~MainWindow() {
|
||||
config.save(config_dir);
|
||||
}
|
||||
|
||||
stop_audio();
|
||||
|
||||
delete ui;
|
||||
|
||||
delete panel_project;
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
#include "panels.h"
|
||||
|
||||
Project* panel_project;
|
||||
EffectControls* panel_effect_controls;
|
||||
Viewer* panel_viewer;
|
||||
Timeline* panel_timeline;
|
||||
Project* panel_project = 0;
|
||||
EffectControls* panel_effect_controls = 0;
|
||||
Viewer* panel_viewer = 0;
|
||||
Timeline* panel_timeline = 0;
|
||||
|
||||
+4
-3
@@ -138,16 +138,16 @@ void Timeline::reset_all_audio() {
|
||||
}
|
||||
ui->audio_monitor->reset();
|
||||
clear_audio_ibuffer();
|
||||
audio_ibuffer_frame = playhead;
|
||||
}
|
||||
|
||||
void Timeline::seek(long p) {
|
||||
pause();
|
||||
|
||||
reset_all_audio();
|
||||
audio_ibuffer_frame = p;
|
||||
|
||||
playhead = p;
|
||||
|
||||
reset_all_audio();
|
||||
|
||||
repaint_timeline();
|
||||
}
|
||||
|
||||
@@ -170,6 +170,7 @@ void Timeline::play() {
|
||||
void Timeline::pause() {
|
||||
playing = false;
|
||||
panel_viewer->set_playpause_icon(true);
|
||||
playback_updater.stop();
|
||||
}
|
||||
|
||||
void Timeline::go_to_end() {
|
||||
|
||||
+1
-3
@@ -29,9 +29,7 @@ Viewer::Viewer(QWidget *parent) :
|
||||
update_end_timecode();
|
||||
}
|
||||
|
||||
Viewer::~Viewer()
|
||||
{
|
||||
init_audio();
|
||||
Viewer::~Viewer() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
+92
-5
@@ -2,6 +2,10 @@
|
||||
|
||||
#include "project/sequence.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "ui_timeline.h"
|
||||
|
||||
#include <QAudioOutput>
|
||||
#include <QtMath>
|
||||
#include <QDebug>
|
||||
@@ -18,12 +22,10 @@ qint8 audio_ibuffer[audio_ibuffer_size];
|
||||
int audio_ibuffer_read = 0;
|
||||
long audio_ibuffer_frame = 0;
|
||||
|
||||
AudioSenderThread* audio_thread;
|
||||
|
||||
void init_audio() {
|
||||
if (audio_device_set) {
|
||||
audio_output->stop();
|
||||
delete audio_output;
|
||||
audio_device_set = false;
|
||||
}
|
||||
stop_audio();
|
||||
|
||||
if (sequence != NULL) {
|
||||
QAudioFormat audio_format;
|
||||
@@ -45,11 +47,25 @@ void init_audio() {
|
||||
audio_io_device = audio_output->start();
|
||||
audio_device_set = true;
|
||||
|
||||
// start sender thread
|
||||
audio_thread = new AudioSenderThread();
|
||||
audio_thread->start();
|
||||
|
||||
clear_audio_ibuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop_audio() {
|
||||
if (audio_device_set) {
|
||||
audio_thread->stop();
|
||||
|
||||
audio_output->stop();
|
||||
delete audio_output;
|
||||
audio_device_set = false;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_audio_ibuffer() {
|
||||
memset(audio_ibuffer, 0, audio_ibuffer_size);
|
||||
audio_ibuffer_read = 0;
|
||||
@@ -63,3 +79,74 @@ int get_buffer_offset_from_frame(long frame) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
AudioSenderThread::AudioSenderThread() : close(false) {
|
||||
connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
|
||||
}
|
||||
|
||||
void AudioSenderThread::stop() {
|
||||
close = true;
|
||||
cond.wakeAll();
|
||||
wait();
|
||||
}
|
||||
|
||||
void AudioSenderThread::run() {
|
||||
// start data loop
|
||||
send_audio_to_output(0, audio_ibuffer_size);
|
||||
|
||||
lock.lock();
|
||||
while (true) {
|
||||
msleep(20);
|
||||
if (close) {
|
||||
break;
|
||||
} else if (panel_timeline->playing) {
|
||||
int written_bytes = 0;
|
||||
|
||||
int adjusted_read_index = audio_ibuffer_read%audio_ibuffer_size;
|
||||
int max_write = audio_ibuffer_size - adjusted_read_index;
|
||||
int actual_write = send_audio_to_output(adjusted_read_index, max_write);
|
||||
written_bytes += actual_write;
|
||||
if (actual_write == max_write) {
|
||||
// got all the bytes, write again
|
||||
written_bytes += send_audio_to_output(0, audio_ibuffer_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
int AudioSenderThread::send_audio_to_output(int offset, int max) {
|
||||
// send audio to device
|
||||
int actual_write = audio_io_device->write((const char*) audio_ibuffer+offset, max);
|
||||
audio_ibuffer_read += actual_write;
|
||||
|
||||
// send samples to audio monitor cache
|
||||
if (panel_timeline->ui->audio_monitor->sample_cache_offset == -1) {
|
||||
panel_timeline->ui->audio_monitor->sample_cache_offset = panel_timeline->playhead;
|
||||
}
|
||||
int channel_count = av_get_channel_layout_nb_channels(sequence->audio_layout);
|
||||
long sample_cache_playhead = panel_timeline->ui->audio_monitor->sample_cache_offset + (panel_timeline->ui->audio_monitor->sample_cache.size()/channel_count);
|
||||
int next_buffer_offset, buffer_offset_adjusted, i;
|
||||
int buffer_offset = get_buffer_offset_from_frame(sample_cache_playhead);
|
||||
if (samples.size() != channel_count) samples.resize(channel_count);
|
||||
samples.fill(0);
|
||||
|
||||
// TODO: I don't like this, but i'm not sure if there's a smarter way to do it
|
||||
while (buffer_offset < audio_ibuffer_read) {
|
||||
sample_cache_playhead++;
|
||||
next_buffer_offset = qMin(get_buffer_offset_from_frame(sample_cache_playhead), audio_ibuffer_read);
|
||||
while (buffer_offset < next_buffer_offset) {
|
||||
for (i=0;i<samples.size();i++) {
|
||||
buffer_offset_adjusted = buffer_offset%audio_ibuffer_size;
|
||||
samples[i] = qMax(qAbs((qint16) (((audio_ibuffer[buffer_offset_adjusted+1] & 0xFF) << 8) | (audio_ibuffer[buffer_offset_adjusted] & 0xFF))), samples[i]);
|
||||
buffer_offset += 2;
|
||||
}
|
||||
}
|
||||
panel_timeline->ui->audio_monitor->sample_cache.append(samples);
|
||||
buffer_offset = next_buffer_offset;
|
||||
}
|
||||
|
||||
memset(audio_ibuffer+offset, 0, actual_write);
|
||||
|
||||
return actual_write;
|
||||
}
|
||||
|
||||
+19
-1
@@ -2,12 +2,15 @@
|
||||
#define AUDIO_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QThread>
|
||||
#include <QWaitCondition>
|
||||
#include <QMutex>
|
||||
|
||||
//#define INT16_MAX 0x7fff
|
||||
//#define INT16_MIN (-INT16_MAX-1)
|
||||
|
||||
class QAudioOutput;
|
||||
class QIODevice;
|
||||
class QAudioOutput;
|
||||
|
||||
struct Sequence;
|
||||
|
||||
@@ -21,6 +24,21 @@ extern long audio_ibuffer_frame;
|
||||
void clear_audio_ibuffer();
|
||||
|
||||
void init_audio();
|
||||
void stop_audio();
|
||||
int get_buffer_offset_from_frame(long frame);
|
||||
|
||||
class AudioSenderThread : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioSenderThread();
|
||||
void run();
|
||||
void stop();
|
||||
QWaitCondition cond;
|
||||
bool close;
|
||||
QMutex lock;
|
||||
private:
|
||||
QVector<qint16> samples;
|
||||
int send_audio_to_output(int offset, int max);
|
||||
};
|
||||
|
||||
#endif // AUDIO_H
|
||||
|
||||
+90
-5
@@ -48,9 +48,7 @@ EffectRow* Effect::row(int i) {
|
||||
return rows.at(i);
|
||||
}
|
||||
|
||||
void Effect::refresh() {
|
||||
qDebug() << "[WARNING] Tried to init base Effect class - type:" << type << "- id:" << id;
|
||||
}
|
||||
void Effect::refresh() {}
|
||||
|
||||
void Effect::field_changed() {
|
||||
panel_viewer->viewer_widget->update();
|
||||
@@ -65,9 +63,80 @@ bool Effect::is_enabled() {
|
||||
return container->enabled_check->isChecked();
|
||||
}
|
||||
|
||||
void Effect::load(QXmlStreamReader* stream) {
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
while (!stream->atEnd()) {
|
||||
stream->readNext();
|
||||
if (stream->name() == "row" && stream->isStartElement()) {
|
||||
for (int j=0;j<row->fieldCount();j++) {
|
||||
EffectField* field = row->field(j);
|
||||
while (!stream->atEnd()) {
|
||||
stream->readNext();
|
||||
if (stream->name() == "field" && stream->isStartElement()) {
|
||||
stream->readNext();
|
||||
switch (field->type) {
|
||||
case EFFECT_FIELD_DOUBLE:
|
||||
field->set_double_value(stream->text().toDouble());
|
||||
break;
|
||||
case EFFECT_FIELD_COLOR:
|
||||
field->set_color_value(QColor(stream->text().toString()));
|
||||
break;
|
||||
case EFFECT_FIELD_STRING:
|
||||
field->set_string_value(stream->text().toString());
|
||||
break;
|
||||
case EFFECT_FIELD_BOOL:
|
||||
field->set_bool_value(stream->text() == "1");
|
||||
break;
|
||||
case EFFECT_FIELD_COMBO:
|
||||
field->set_combo_string(stream->text().toString());
|
||||
break;
|
||||
case EFFECT_FIELD_FONT:
|
||||
field->set_combo_string(stream->text().toString());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::save(QXmlStreamWriter* stream) {
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
stream->writeStartElement("row");
|
||||
for (int j=0;j<row->fieldCount();j++) {
|
||||
EffectField* field = row->field(j);
|
||||
switch (field->type) {
|
||||
case EFFECT_FIELD_DOUBLE:
|
||||
stream->writeTextElement("field", QString::number(field->get_double_value()));
|
||||
break;
|
||||
case EFFECT_FIELD_COLOR:
|
||||
stream->writeTextElement("field", field->get_color_value().name());
|
||||
break;
|
||||
case EFFECT_FIELD_STRING:
|
||||
stream->writeTextElement("field", field->get_string_value());
|
||||
break;
|
||||
case EFFECT_FIELD_BOOL:
|
||||
stream->writeTextElement("field", QString::number(field->get_bool_value()));
|
||||
break;
|
||||
case EFFECT_FIELD_COMBO:
|
||||
stream->writeTextElement("field", field->get_combo_string());
|
||||
break;
|
||||
case EFFECT_FIELD_FONT:
|
||||
stream->writeTextElement("field", field->get_font_name());
|
||||
break;
|
||||
}
|
||||
}
|
||||
stream->writeEndElement(); // row
|
||||
}
|
||||
}
|
||||
|
||||
Effect* Effect::copy(Clip*) {return NULL;}
|
||||
void Effect::load(QXmlStreamReader*) {}
|
||||
void Effect::save(QXmlStreamWriter*) {}
|
||||
void Effect::process_gl(int*, int*) {}
|
||||
void Effect::post_gl() {}
|
||||
void Effect::process_audio(uint8_t*, int) {}
|
||||
@@ -92,6 +161,14 @@ EffectRow::~EffectRow() {
|
||||
}
|
||||
}
|
||||
|
||||
EffectField* EffectRow::field(int i) {
|
||||
return fields.at(i);
|
||||
}
|
||||
|
||||
int EffectRow::fieldCount() {
|
||||
return fields.size();
|
||||
}
|
||||
|
||||
/* Effect Field Definitions */
|
||||
|
||||
EffectField::EffectField(Effect *parent, int t) : type(t) {
|
||||
@@ -191,6 +268,10 @@ void EffectField::set_combo_index(int index) {
|
||||
static_cast<QComboBox*>(ui_element)->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void EffectField::set_combo_string(const QString& s) {
|
||||
static_cast<QComboBox*>(ui_element)->setCurrentText(s);
|
||||
}
|
||||
|
||||
bool EffectField::get_bool_value() {
|
||||
return static_cast<QCheckBox*>(ui_element)->isChecked();
|
||||
}
|
||||
@@ -214,3 +295,7 @@ const QString EffectField::get_font_name() {
|
||||
QColor EffectField::get_color_value() {
|
||||
return static_cast<ColorButton*>(ui_element)->get_color();
|
||||
}
|
||||
|
||||
void EffectField::set_color_value(QColor color) {
|
||||
static_cast<ColorButton*>(ui_element)->set_color(color);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
const QVariant get_combo_data();
|
||||
const QString get_combo_string();
|
||||
void set_combo_index(int index);
|
||||
void set_combo_string(const QString& s);
|
||||
|
||||
bool get_bool_value();
|
||||
void set_bool_value(bool b);
|
||||
@@ -51,6 +52,7 @@ public:
|
||||
const QString get_font_name();
|
||||
|
||||
QColor get_color_value();
|
||||
void set_color_value(QColor color);
|
||||
|
||||
QWidget* get_ui_element();
|
||||
void set_enabled(bool e);
|
||||
@@ -64,6 +66,7 @@ public:
|
||||
~EffectRow();
|
||||
EffectField* add_field(int type);
|
||||
EffectField* field(int i);
|
||||
int fieldCount();
|
||||
void set_keyframe(int field, long time);
|
||||
void move_keyframe(int field, long from, long to);
|
||||
void delete_keyframe(int field, long time);
|
||||
|
||||
@@ -37,6 +37,7 @@ void AudioMonitor::resizeEvent(QResizeEvent *e) {
|
||||
|
||||
void AudioMonitor::paintEvent(QPaintEvent *) {
|
||||
if (sequence != NULL) {
|
||||
|
||||
QPainter p(this);
|
||||
int channel_x = AUDIO_MONITOR_GAP;
|
||||
int channel_count = av_get_channel_layout_nb_channels(sequence->audio_layout);
|
||||
|
||||
+3
-2
@@ -16,23 +16,24 @@ QColor ColorButton::get_color() {
|
||||
|
||||
void ColorButton::set_color(QColor c) {
|
||||
color = c;
|
||||
set_button_color();
|
||||
}
|
||||
|
||||
void ColorButton::set_button_color() {
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Button, color);
|
||||
setPalette(pal);
|
||||
emit color_changed();
|
||||
}
|
||||
|
||||
void ColorButton::open_dialog() {
|
||||
QColor old_color = color;
|
||||
QColor new_color = QColorDialog::getColor(color, NULL);
|
||||
if (old_color != new_color) {
|
||||
if (new_color.isValid() && old_color != new_color) {
|
||||
ColorCommand* command = new ColorCommand(this, old_color, new_color);
|
||||
undo_stack.push(command);
|
||||
|
||||
set_button_color();
|
||||
emit color_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-16
@@ -3,20 +3,5 @@
|
||||
#include <QFontDatabase>
|
||||
|
||||
FontCombobox::FontCombobox(QWidget* parent) : ComboBoxEx(parent) {
|
||||
addItem(QFont().family());
|
||||
}
|
||||
|
||||
void FontCombobox::showPopup() {
|
||||
QString current = currentText();
|
||||
clear();
|
||||
QStringList fonts = QFontDatabase().families();
|
||||
bool found = false;
|
||||
for (int i=0;i<fonts.size();i++) {
|
||||
addItem(fonts.at(i));
|
||||
if (!found && fonts.at(i) == current) {
|
||||
setCurrentIndex(i);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
QComboBox::showPopup();
|
||||
addItems(QFontDatabase().families());
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
class FontCombobox : public ComboBoxEx {
|
||||
public:
|
||||
FontCombobox(QWidget* parent = 0);
|
||||
protected:
|
||||
void showPopup();
|
||||
};
|
||||
|
||||
#endif // FONTCOMBOBOX_H
|
||||
|
||||
+1
-75
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QAudioOutput>
|
||||
#include <QtMath>
|
||||
|
||||
extern "C" {
|
||||
@@ -31,20 +32,11 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
format.setDepthBufferSize(24);
|
||||
setFormat(format);
|
||||
|
||||
// start audio sending thread
|
||||
audio_sender_thread.start();
|
||||
|
||||
// error handler - retries after 250ms if we couldn't get the entire image
|
||||
retry_timer.setInterval(250);
|
||||
connect(&retry_timer, SIGNAL(timeout()), this, SLOT(retry()));
|
||||
}
|
||||
|
||||
ViewerWidget::~ViewerWidget() {
|
||||
audio_sender_thread.close = true;
|
||||
audio_sender_thread.cond.wakeAll();
|
||||
audio_sender_thread.wait();
|
||||
}
|
||||
|
||||
void ViewerWidget::deleteFunction() {
|
||||
// destroy all textures as well
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
@@ -241,11 +233,6 @@ void ViewerWidget::paintGL() {
|
||||
QVector<Clip*> nests;
|
||||
compose_sequence(nests, (panel_timeline->playing || force_audio));
|
||||
|
||||
// send audio to IO device
|
||||
if (panel_timeline->playing) {
|
||||
audio_sender_thread.cond.wakeAll();
|
||||
}
|
||||
|
||||
if (texture_failed) {
|
||||
if (multithreaded) {
|
||||
retry_timer.start();
|
||||
@@ -256,64 +243,3 @@ void ViewerWidget::paintGL() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioSenderThread::AudioSenderThread() : close(false) {
|
||||
connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
|
||||
}
|
||||
|
||||
void AudioSenderThread::run() {
|
||||
lock.lock();
|
||||
while (true) {
|
||||
cond.wait(&lock);
|
||||
if (close) {
|
||||
break;
|
||||
} else {
|
||||
int written_bytes = 0;
|
||||
|
||||
int adjusted_read_index = audio_ibuffer_read%audio_ibuffer_size;
|
||||
int max_write = audio_ibuffer_size - adjusted_read_index;
|
||||
int actual_write = send_audio_to_output(adjusted_read_index, max_write);
|
||||
written_bytes += actual_write;
|
||||
if (actual_write == max_write) {
|
||||
// got all the bytes, write again
|
||||
written_bytes += send_audio_to_output(0, audio_ibuffer_size);
|
||||
}
|
||||
|
||||
qDebug() << "WB:" << written_bytes;
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
int AudioSenderThread::send_audio_to_output(int offset, int max) {
|
||||
// send audio to device
|
||||
int actual_write = audio_io_device->write((const char*) audio_ibuffer+offset, max);
|
||||
audio_ibuffer_read += actual_write;
|
||||
|
||||
// send samples to audio monitor cache
|
||||
if (panel_timeline->ui->audio_monitor->sample_cache_offset == -1) {
|
||||
panel_timeline->ui->audio_monitor->sample_cache_offset = panel_timeline->playhead;
|
||||
}
|
||||
long sample_cache_playhead = panel_timeline->ui->audio_monitor->sample_cache_offset + panel_timeline->ui->audio_monitor->sample_cache.size();
|
||||
int next_buffer_offset, buffer_offset_adjusted, i;
|
||||
int buffer_offset = get_buffer_offset_from_frame(sample_cache_playhead);
|
||||
samples.resize(av_get_channel_layout_nb_channels(sequence->audio_layout));
|
||||
samples.fill(0);
|
||||
while (buffer_offset < audio_ibuffer_read) {
|
||||
sample_cache_playhead++;
|
||||
next_buffer_offset = qMin(get_buffer_offset_from_frame(sample_cache_playhead), audio_ibuffer_read);
|
||||
while (buffer_offset < next_buffer_offset) {
|
||||
for (i=0;i<samples.size();i++) {
|
||||
buffer_offset_adjusted = buffer_offset%audio_ibuffer_size;
|
||||
samples[i] = qMax(qAbs((qint16) (((audio_ibuffer[buffer_offset_adjusted+1] & 0xFF) << 8) | (audio_ibuffer[buffer_offset_adjusted] & 0xFF))), samples[i]);
|
||||
buffer_offset += 2;
|
||||
}
|
||||
}
|
||||
panel_timeline->ui->audio_monitor->sample_cache.append(samples);
|
||||
buffer_offset = next_buffer_offset;
|
||||
}
|
||||
|
||||
memset(audio_ibuffer+offset, 0, actual_write);
|
||||
|
||||
return actual_write;
|
||||
}
|
||||
|
||||
@@ -13,24 +13,11 @@
|
||||
struct Clip;
|
||||
struct Sequence;
|
||||
|
||||
class AudioSenderThread : public QThread {
|
||||
public:
|
||||
AudioSenderThread();
|
||||
void run();
|
||||
QWaitCondition cond;
|
||||
bool close;
|
||||
QMutex lock;
|
||||
private:
|
||||
QVector<qint16> samples;
|
||||
int send_audio_to_output(int offset, int max);
|
||||
};
|
||||
|
||||
class ViewerWidget : public QOpenGLWidget, public QOpenGLFunctions
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerWidget(QWidget *parent = 0);
|
||||
~ViewerWidget();
|
||||
|
||||
bool multithreaded;
|
||||
bool force_audio;
|
||||
@@ -43,7 +30,6 @@ protected:
|
||||
// void resizeGL(int w, int h);
|
||||
private:
|
||||
QTimer retry_timer;
|
||||
AudioSenderThread audio_sender_thread;
|
||||
private slots:
|
||||
void retry();
|
||||
void deleteFunction();
|
||||
|
||||
Reference in New Issue
Block a user