From 7592898cbf244cb47f7d462b9f4acf9b8431f6d0 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 7 Oct 2018 23:21:59 +1100 Subject: [PATCH] VERY buggy audio reversing implemented --- panels/project.cpp | 7 +++++- playback/cacher.cpp | 52 ++++++++++++++++++++++++++++++++++++++++--- ui/timelinewidget.cpp | 4 ++-- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/panels/project.cpp b/panels/project.cpp index b3fe873f0..364c8a6ca 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -788,6 +788,10 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { stream_id = attr.value().toInt(); } else if (attr.name() == "speed") { c->speed = attr.value().toDouble(); + } else if (attr.name() == "maintainpitch") { + c->maintain_audio_pitch = (attr.value() == "1"); + } else if (attr.name() == "reverse") { + c->reverse = (attr.value() == "1"); } else if (attr.name() == "sequence") { c->media_type = MEDIA_TYPE_SEQUENCE; @@ -1086,8 +1090,9 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int stream.writeAttribute("b", QString::number(c->color_b)); stream.writeAttribute("autoscale", QString::number(c->autoscale)); - stream.writeAttribute("speed", QString::number(c->speed, 'f', 10)); + stream.writeAttribute("maintainpitch", QString::number(c->maintain_audio_pitch)); + stream.writeAttribute("reverse", QString::number(c->reverse)); stream.writeAttribute("type", QString::number(c->media_type)); switch (c->media_type) { diff --git a/playback/cacher.cpp b/playback/cacher.cpp index 99a84fb9c..8c3fadc00 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -98,7 +98,48 @@ void cache_audio_worker(Clip* c, Clip* nest) { int ret; while ((ret = av_buffersink_get_frame(c->buffersink_ctx, frame)) == AVERROR(EAGAIN)) { - ret = retrieve_next_frame(c, c->frame); + if (c->reverse) { + /* TODO i have a feeling that here we're going to have to: + * - seek to previous frame + * - read it + * - convert it to 16-bit PCM LE + * - reverse it + * + * ...good luck :| + */ + + if (!c->audio_just_reset) { + // get previous frame? + avcodec_flush_buffers(c->codecCtx); + qDebug() << "seeking to:" << (c->frame->pts - 1); + if (av_seek_frame(c->formatCtx, c->stream->index, c->frame->pts - 1, AVSEEK_FLAG_BACKWARD) < 0) { + qDebug() << "SEEK FAILED"; + } + } + + ret = retrieve_next_frame(c, c->frame); + + // reverse it + int frame_bytes = av_samples_get_buffer_size(NULL, c->frame->channels, c->frame->nb_samples, static_cast(c->frame->format), 1); + qDebug() << "frame bytes:" << frame_bytes; + int half_frame_bytes = frame_bytes >> 1; + int sample_size = c->frame->channels*2; + char* temp_chars = new char[sample_size]; + for (int i=0;iframe->data[0][i+j]; + } + for (int j=0;jframe->data[0][i+j] = c->frame->data[0][frame_bytes-i-sample_size+j]; + } + for (int j=0;jframe->data[0][frame_bytes-i-sample_size+j] = temp_chars[j]; + } + } + delete [] temp_chars; + } else { + ret = retrieve_next_frame(c, c->frame); + } if (ret >= 0) { if ((ret = av_buffersrc_add_frame_flags(c->buffersrc_ctx, c->frame, AV_BUFFERSRC_FLAG_KEEP_REF)) < 0) { @@ -107,7 +148,8 @@ void cache_audio_worker(Clip* c, Clip* nest) { } } else { if (ret == AVERROR_EOF) { - c->reached_end = true; + // TODO likewise, I'm not sure if this if statement breaks anything (see equivalent section in cache_video_worker) + if (c->reverse) c->reached_end = true; } else { qDebug() << "[WARNING] Raw audio frame data could not be retrieved." << ret; c->reached_end = true; @@ -321,7 +363,11 @@ void reset_cache(Clip* c, long target_frame) { av_frame_free(&temp); } else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { // seek (target_frame represents timeline timecode in frames, not clip timecode) - av_seek_frame(c->formatCtx, ms->file_index, playhead_to_seconds(c, target_frame) / timebase, AVSEEK_FLAG_BACKWARD); + int64_t timestamp = qRound(playhead_to_seconds(c, target_frame) / timebase); // TODO qRound here might lead to clicking? or might fix it... who knows + if (c->reverse) { + timestamp = c->stream->duration - timestamp - 1; + } + av_seek_frame(c->formatCtx, ms->file_index, timestamp, AVSEEK_FLAG_BACKWARD); c->audio_target_frame = target_frame; c->frame_sample_index = -1; c->audio_just_reset = true; diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 2204fa781..2dcb76e2e 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1656,9 +1656,9 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } } } - if (cursor_contains_clip) { + /*if (cursor_contains_clip) { QToolTip::showText(mapToGlobal(event->pos()), "HOVER OVER CLIP"); - } + }*/ if (found) { setCursor(Qt::SizeHorCursor); } else {