better waveforms

This commit is contained in:
itsmattkc
2018-06-19 19:29:51 -07:00
parent 34ba0e59ae
commit a7b3ba64e6
13 changed files with 63 additions and 26 deletions
+2
View File
@@ -48,7 +48,9 @@ void VolumeEffect::save(QXmlStreamWriter *stream) {
void VolumeEffect::process_audio(quint8 *samples, int nb_bytes) {
for (int i=0;i<nb_bytes;i+=2) {
qint16 full_sample = (qint16) ((samples[i+1] << 8) | samples[i]);
full_sample *= volume_val->value()*0.01;
samples[i+1] = (quint8) (full_sample >> 8);
samples[i] = (quint8) full_sample;
}
+1 -1
View File
@@ -18,7 +18,7 @@ struct MediaStream {
// preview thumbnail/waveform
bool preview_done;
QImage preview;
QImage preview; // TODO change to QPixmap
QMutex preview_lock;
int preview_audio_index;
};
+20 -6
View File
@@ -33,7 +33,7 @@ MediaStream* PreviewGenerator::get_stream_from_file_index(int index) {
return NULL;
}
#define WAVEFORM_RESOLUTION 256
#define WAVEFORM_RESOLUTION 64
void PreviewGenerator::run() {
if (media == NULL) {
@@ -55,7 +55,9 @@ void PreviewGenerator::run() {
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
// initiate qimage
MediaStream* ms = get_stream_from_file_index(i);
ms->preview = QImage(fmt_ctx->streams[i]->duration * av_q2d(fmt_ctx->streams[i]->time_base) * WAVEFORM_RESOLUTION, 255, QImage::Format_RGBA8888);
int width = fmt_ctx->streams[i]->duration * av_q2d(fmt_ctx->streams[i]->time_base) * WAVEFORM_RESOLUTION;
if (width > 32767) qDebug() << "[WARNING] Due to limitations in Qt's painter, this waveform may not appear correctly (see issue #76)";
ms->preview = QImage(width, 80, QImage::Format_RGBA8888);
ms->preview_audio_index = 0;
ms->preview.fill(Qt::transparent);
}
@@ -125,13 +127,25 @@ void PreviewGenerator::run() {
QPainter p;
p.begin(&s->preview);
p.setPen(QColor(80, 80, 80));
int channel_jump = swr_frame->channels * 2;
int divider = (32768.0/(s->preview.height()/2))*swr_frame->channels;
for (int i=0;i<swr_frame->nb_samples;i+=interval) {
for (int j=0;j<swr_frame->channels;j++) {
qint16 sample = ((swr_frame->data[0][i+1] << 8) | swr_frame->data[0][i]);
sample /= 256;
sample /= swr_frame->channels;
qint16 min = 0;
qint16 max = 0;
for (int k=j*2;k<interval;k+=channel_jump) {
qint16 sample = ((swr_frame->data[0][i+k+1] << 8) | swr_frame->data[0][i+k]);
if (sample > max) {
max = sample;
} else if (sample < min) {
min = sample;
}
}
min /= divider;
max /= divider;
int mid = channel_height*j+(channel_height/2);
p.drawLine(s->preview_audio_index, mid, s->preview_audio_index, mid+sample);
p.drawLine(s->preview_audio_index, mid+min, s->preview_audio_index, mid+max);
i += 2;
}
s->preview_audio_index++;
+7 -2
View File
@@ -23,12 +23,15 @@
#define OLIVE_FILE_FILTER "Olive Project (*.ove)"
void MainWindow::setup_layout() {
panel_project->show();
panel_effect_controls->show();
panel_viewer->show();
panel_timeline->show();
addDockWidget(Qt::TopDockWidgetArea, panel_project);
addDockWidget(Qt::TopDockWidgetArea, panel_effect_controls);
addDockWidget(Qt::TopDockWidgetArea, panel_viewer);
addDockWidget(Qt::BottomDockWidgetArea, panel_timeline);
setCentralWidget(NULL);
}
MainWindow::MainWindow(QWidget *parent) :
@@ -66,6 +69,8 @@ MainWindow::MainWindow(QWidget *parent) :
setWindowTitle("Olive (May 2018 | Pre-Alpha)");
statusBar()->showMessage("Welcome to Olive::Qt");
setCentralWidget(NULL);
// TODO maybe replace these with non-pointers later on?
panel_project = new Project(this);
panel_effect_controls = new EffectControls(this);
+1 -1
View File
@@ -95,7 +95,7 @@
</widget>
<widget class="QMenu" name="menuPlayback">
<property name="title">
<string>Playback</string>
<string>&amp;Playback</string>
</property>
<addaction name="actionGo_to_start"/>
<addaction name="actionPrevious_Frame"/>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.6.2, 2018-06-18T23:37:22. -->
<!-- Written by QtCreator 4.6.2, 2018-06-19T11:17:03. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
+5 -3
View File
@@ -80,13 +80,12 @@ void Timeline::seek(long p) {
repaint_timeline();
}
bool Timeline::toggle_play() {
void Timeline::toggle_play() {
if (playing) {
pause();
} else {
play();
}
return playing;
}
}
void Timeline::play() {
@@ -94,10 +93,12 @@ void Timeline::play() {
start_msecs = QDateTime::currentMSecsSinceEpoch();
playback_updater.start();
playing = true;
panel_viewer->set_playpause_icon(false);
}
void Timeline::pause() {
playing = false;
panel_viewer->set_playpause_icon(true);
}
void Timeline::go_to_end() {
@@ -167,6 +168,7 @@ void Timeline::redraw_all_clips() {
ui->video_area->redraw_clips();
ui->audio_area->redraw_clips();
ui->headers->update();
}
void Timeline::select_all() {
+1 -1
View File
@@ -84,7 +84,7 @@ public:
void previous_frame();
void next_frame();
void seek(long p);
bool toggle_play();
void toggle_play();
void play();
void pause();
void go_to_end();
+9 -6
View File
@@ -71,10 +71,13 @@ void Viewer::on_pushButton_4_clicked()
void Viewer::on_pushButton_3_clicked()
{
if (panel_timeline->toggle_play()) {
// playing
ui->pushButton_3->setIcon(QIcon(":/icons/pause.png"));
} else {
ui->pushButton_3->setIcon(QIcon(":/icons/play.png"));
}
panel_timeline->toggle_play();
}
void Viewer::set_playpause_icon(bool play) {
if (play) {
ui->pushButton_3->setIcon(QIcon(":/icons/play.png"));
} else {
ui->pushButton_3->setIcon(QIcon(":/icons/pause.png"));
}
}
+1
View File
@@ -20,6 +20,7 @@ public:
~Viewer();
void update_sequence();
void compose();
void set_playpause_icon(bool play);
ViewerWidget* viewer_widget;
+3 -1
View File
@@ -37,7 +37,9 @@ void init_audio() {
if (!info.isFormatSupported(audio_format)) {
qWarning() << "[WARNING] Couldn't initialize audio. Audio format is not supported by backend";
} else {
audio_output = new QAudioOutput(audio_format);
audio_output = new QAudioOutput(audio_format);
audio_output->setBufferSize(20480);
// connect
audio_io_device = audio_output->start();
audio_device_set = true;
+6 -1
View File
@@ -40,7 +40,12 @@ void TimelineHeader::paintEvent(QPaintEvent*) {
if (sequence != NULL) {
QPainter p(this);
p.setPen(Qt::gray);
int interval = panel_timeline->getScreenPointFromFrame(sequence->frame_rate);
int interval = 0;
int multiplier = 0;
do {
multiplier++;
interval = panel_timeline->getScreenPointFromFrame(sequence->frame_rate*multiplier);
} while (interval < 10);
for (int i=0;i<width();i+=interval) {
p.drawLine(i, 0, i, height());
}
+6 -3
View File
@@ -27,7 +27,7 @@ TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent)
setMouseTracking(true);
track_height = 80;
setAcceptDrops(true);
setAcceptDrops(true);
}
bool same_sign(int a, int b) {
@@ -760,8 +760,6 @@ int color_brightness(int r, int g, int b) {
}
void TimelineWidget::redraw_clips() {
qDebug() << "redraw called";
// Draw clips
int panel_width = panel_timeline->getScreenPointFromFrame(sequence->getEndFrame()) + 100;
@@ -817,6 +815,11 @@ void TimelineWidget::redraw_clips() {
}
QRect text_rect(clip_rect.left() + CLIP_TEXT_PADDING, clip_rect.top() + CLIP_TEXT_PADDING, clip_rect.width() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING, clip_rect.height() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING);
clip_painter.drawText(text_rect, 0, clip->name, &text_rect);
if (clip->linked.size() > 0) {
int underline_y = CLIP_TEXT_PADDING + clip_painter.fontMetrics().height() + clip_rect.top();
int underline_width = qMin(clip_rect.width() - CLIP_TEXT_PADDING, clip_rect.left() + CLIP_TEXT_PADDING+clip_painter.fontMetrics().width(clip->name));
clip_painter.drawLine(clip_rect.left() + CLIP_TEXT_PADDING, underline_y, underline_width, underline_y);
}
// bottom right gray
clip_painter.setPen(Qt::gray);