fixed seeking with WAV and MP3 files and added mono/stereo recording options
This commit is contained in:
@@ -23,6 +23,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) :
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->recordingComboBox->setCurrentIndex(config.recording_mode - 1);
|
||||
ui->imgSeqFormatEdit->setText(config.img_seq_formats);
|
||||
}
|
||||
|
||||
@@ -75,5 +76,6 @@ void PreferencesDialog::setup_kbd_shortcuts(QMenuBar* menubar) {
|
||||
}
|
||||
|
||||
void PreferencesDialog::on_buttonBox_accepted() {
|
||||
config.recording_mode = ui->recordingComboBox->currentIndex() + 1;
|
||||
config.img_seq_formats = ui->imgSeqFormatEdit->text();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
@@ -34,6 +34,27 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="imgSeqFormatEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Audio Recording:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="recordingComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mono</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Stereo</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
|
||||
+11
-34
@@ -23,7 +23,8 @@ Config::Config()
|
||||
use_custom_title_safe_ratio(false),
|
||||
custom_title_safe_ratio(1),
|
||||
enable_drag_files_to_timeline(false),
|
||||
autoscale_by_default(false)
|
||||
autoscale_by_default(false),
|
||||
recording_mode(2)
|
||||
{}
|
||||
|
||||
void Config::load(QString path) {
|
||||
@@ -81,8 +82,11 @@ void Config::load(QString path) {
|
||||
enable_drag_files_to_timeline = (stream.text() == "1");;
|
||||
} else if (stream.name() == "AutoscaleByDefault") {
|
||||
stream.readNext();
|
||||
autoscale_by_default = (stream.text() == "1");;
|
||||
}
|
||||
autoscale_by_default = (stream.text() == "1");
|
||||
} else if (stream.name() == "RecordingMode") {
|
||||
stream.readNext();
|
||||
recording_mode = stream.text().toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stream.hasError()) {
|
||||
@@ -90,29 +94,7 @@ void Config::load(QString path) {
|
||||
}
|
||||
|
||||
f.close();
|
||||
}
|
||||
/*if (!custom_scale) {
|
||||
#ifdef _WIN32
|
||||
// Get Windows UI scale - TODO may not be compatible with XP
|
||||
HDC screen = GetDC(0);
|
||||
int dpiX = GetDeviceCaps (screen, LOGPIXELSX);
|
||||
//int dpiY = GetDeviceCaps (screen, LOGPIXELSY);
|
||||
|
||||
scale = (float) dpiX / 96;
|
||||
|
||||
ReleaseDC (0, screen);
|
||||
#endif
|
||||
}*/
|
||||
|
||||
// padding *= scale;
|
||||
|
||||
/*DIR* dir = opendir("conf");
|
||||
if (dir) {
|
||||
closedir(dir);
|
||||
} else if (ENOENT == errno) {
|
||||
// no config directory, assume this is the first time opening Olive
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "INFO", "NOTE: This version of Olive is INCOMPLETE and very likely to crash. It comes with NO WARRANTY or guarantee of functionality.\n\nRegardless, thanks for checking out the project and I hope you enjoy using it!", NULL);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
void Config::save(QString path) {
|
||||
@@ -144,14 +126,9 @@ void Config::save(QString path) {
|
||||
stream.writeTextElement("CustomTitleSafeRatio", QString::number(custom_title_safe_ratio));
|
||||
stream.writeTextElement("EnableDragFilesToTimeline", QString::number(enable_drag_files_to_timeline));
|
||||
stream.writeTextElement("AutoscaleByDefault", QString::number(autoscale_by_default));
|
||||
stream.writeTextElement("RecordingMode", QString::number(recording_mode));
|
||||
|
||||
stream.writeEndElement();
|
||||
stream.writeEndElement(); // configuration
|
||||
stream.writeEndDocument(); // doc
|
||||
f.close();
|
||||
/*#ifdef _WIN32
|
||||
_mkdir("conf");
|
||||
#else
|
||||
mkdir("conf", 0777);
|
||||
#endif*/
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#define TIMECODE_NONDROP 1
|
||||
#define TIMECODE_FRAMES 2
|
||||
|
||||
#define RECORD_MODE_MONO 1
|
||||
#define RECORD_MODE_STEREO 2
|
||||
|
||||
struct Config {
|
||||
Config();
|
||||
bool saved_layout;
|
||||
@@ -27,6 +30,7 @@ struct Config {
|
||||
double custom_title_safe_ratio;
|
||||
bool enable_drag_files_to_timeline;
|
||||
bool autoscale_by_default;
|
||||
int recording_mode;
|
||||
|
||||
void load(QString path);
|
||||
void save(QString path);
|
||||
|
||||
+7
-3
@@ -25,6 +25,7 @@
|
||||
#include <QPainter>
|
||||
#include <QMenu>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
long refactor_frame_number(long framenumber, double source_frame_rate, double target_frame_rate) {
|
||||
if (source_frame_rate == target_frame_rate) return framenumber;
|
||||
@@ -1155,7 +1156,10 @@ void Timeline::setScroll(int s) {
|
||||
}
|
||||
|
||||
void Timeline::on_recordButton_clicked() {
|
||||
creating = true;
|
||||
creating_object = ADD_OBJ_AUDIO;
|
||||
//qDebug() << "recording is a" << start_recording();
|
||||
if (project_url.isEmpty()) {
|
||||
QMessageBox::critical(this, "Unsaved Project", "You must save this project before you can record audio in it.", QMessageBox::Ok);
|
||||
} else {
|
||||
creating = true;
|
||||
creating_object = ADD_OBJ_AUDIO;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "project/sequence.h"
|
||||
|
||||
#include "io/config.h"
|
||||
#include "panels/project.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
@@ -211,9 +212,10 @@ void write_wave_header(QFile& f, const QAudioFormat& format) {
|
||||
f.putChar(1);
|
||||
f.putChar(0);
|
||||
|
||||
// 2 byte channel count (2 for stereo)
|
||||
f.putChar(2);
|
||||
f.putChar(0);
|
||||
// 2 byte channel count
|
||||
int32bit = format.channelCount();
|
||||
int32_to_char_array(int32bit, arr);
|
||||
f.write(arr, 2);
|
||||
|
||||
// 4 byte integer for sample rate
|
||||
int32bit = format.sampleRate();
|
||||
@@ -287,6 +289,9 @@ bool start_recording() {
|
||||
}
|
||||
|
||||
QAudioFormat audio_format = audio_output->format();
|
||||
if (config.recording_mode != audio_format.channelCount()) {
|
||||
audio_format.setChannelCount(config.recording_mode);
|
||||
}
|
||||
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
|
||||
if (!info.isFormatSupported(audio_format)) {
|
||||
qDebug() << "[WARNING] Default format not supported, using nearest";
|
||||
|
||||
+7
-6
@@ -183,7 +183,7 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
if ((c->frame->pts >= c->reverse_target) || (ret == AVERROR_EOF)) {
|
||||
/*qDebug() << "time for the end of rev cache" << rev_frame->nb_samples << c->rev_target << c->frame->pts << c->frame->pkt_duration << c->frame->nb_samples;
|
||||
qDebug() << "diff:" << (c->frame->pkt_pts + c->frame->pkt_duration) - c->rev_target;
|
||||
int cutoff = qRound ((((c->frame->pkt_pts + c->frame->pkt_duration) - c->rev_target) * timebase) * c->sequence->audio_frequency);
|
||||
int cutoff = qRound64 ((((c->frame->pkt_pts + c->frame->pkt_duration) - c->rev_target) * timebase) * c->sequence->audio_frequency);
|
||||
if (cutoff > 0) {
|
||||
qDebug() << "cut off" << cutoff << "samples (rate:" << c->sequence->audio_frequency << ")";
|
||||
rev_frame->nb_samples -= cutoff;
|
||||
@@ -192,7 +192,7 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "pre cutoff deets::: rev_frame.pts:" << rev_frame->pts << "rev_frame.nb_samples" << rev_frame->nb_samples << "rev_target:" << c->reverse_target;
|
||||
#endif
|
||||
rev_frame->nb_samples = qRound(static_cast<double>(c->reverse_target - rev_frame->pts) / c->stream->codecpar->sample_rate * c->sequence->audio_frequency);
|
||||
rev_frame->nb_samples = qRound64(static_cast<double>(c->reverse_target - rev_frame->pts) / c->stream->codecpar->sample_rate * c->sequence->audio_frequency);
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "post cutoff deets::" << rev_frame->nb_samples;
|
||||
#endif
|
||||
@@ -250,7 +250,7 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
// get precise sample offset for the elected clip_in from this audio frame
|
||||
double target_sts = playhead_to_clip_seconds(c, c->audio_target_frame);
|
||||
double frame_sts = ((frame->pts - c->stream->start_time) * timebase);
|
||||
int nb_samples = qRound((target_sts - frame_sts)*c->sequence->audio_frequency);
|
||||
int nb_samples = qRound64((target_sts - frame_sts)*c->sequence->audio_frequency);
|
||||
c->frame_sample_index = nb_samples * 4;
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "fsts:" << frame_sts << "tsts:" << target_sts << "nbs:" << nb_samples << "nbb:" << nb_bytes << "rev_targetToSec:" << (c->reverse_target * timebase);
|
||||
@@ -379,7 +379,7 @@ void cache_video_worker(Clip* c, long playhead) {
|
||||
int64_t eighth_second = av_q2d(av_inv_q(c->stream->time_base))*0.125;
|
||||
int64_t smallest_pts = INT64_MAX;
|
||||
if (c->reverse && c->queue.size() > 0) {
|
||||
int64_t quarter_sec = qRound(av_q2d(av_inv_q(c->stream->time_base))) >> 2;
|
||||
int64_t quarter_sec = qRound64(av_q2d(av_inv_q(c->stream->time_base))) >> 2;
|
||||
for (int i=0;i<c->queue.size();i++) {
|
||||
smallest_pts = qMin(smallest_pts, c->queue.at(i)->pts);
|
||||
}
|
||||
@@ -489,7 +489,7 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
// seeks to nearest keyframe (target_frame represents internal clip frame)
|
||||
int64_t target_ts = seconds_to_timestamp(c, playhead_to_clip_seconds(c, target_frame));
|
||||
int64_t seek_ts = target_ts;
|
||||
int64_t timebase_half_second = qRound(av_q2d(av_inv_q(c->stream->time_base)));
|
||||
int64_t timebase_half_second = qRound64(av_q2d(av_inv_q(c->stream->time_base)));
|
||||
if (c->reverse) seek_ts -= timebase_half_second;
|
||||
|
||||
while (true) {
|
||||
@@ -527,6 +527,7 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
// seek (target_frame represents timeline timecode in frames, not clip timecode)
|
||||
|
||||
int64_t timestamp = seconds_to_timestamp(c, playhead_to_clip_seconds(c, target_frame));
|
||||
|
||||
if (c->reverse) {
|
||||
c->reverse_target = timestamp;
|
||||
timestamp -= av_q2d(av_inv_q(c->stream->time_base));
|
||||
@@ -725,7 +726,7 @@ void open_clip_worker(Clip* clip) {
|
||||
avfilter_link(clip->buffersrc_ctx, 0, tempo_filter, 0);
|
||||
avfilter_link(tempo_filter, 0, clip->buffersink_ctx, 0);
|
||||
} else {
|
||||
target_sample_rate = qRound(clip->sequence->audio_frequency / clip->speed);
|
||||
target_sample_rate = qRound64(clip->sequence->audio_frequency / clip->speed);
|
||||
avfilter_link(clip->buffersrc_ctx, 0, clip->buffersink_ctx, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ void get_clip_frame(Clip* c, long playhead) {
|
||||
MediaStream* ms = static_cast<Media*>(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream);
|
||||
|
||||
int64_t target_pts = playhead_to_timestamp(c, playhead);
|
||||
int64_t second_pts = qRound(av_q2d(av_inv_q(c->stream->time_base)));
|
||||
int64_t second_pts = qRound64(av_q2d(av_inv_q(c->stream->time_base)));
|
||||
int64_t quarter_pts = second_pts >> 2;
|
||||
if (ms->video_interlacing != VIDEO_PROGRESSIVE) {
|
||||
target_pts *= 2;
|
||||
@@ -231,7 +231,7 @@ double playhead_to_clip_seconds(Clip* c, long playhead) {
|
||||
}
|
||||
|
||||
int64_t seconds_to_timestamp(Clip* c, double seconds) {
|
||||
return qRound((seconds * c->stream->time_base.den)/c->stream->time_base.num) + c->stream->start_time;
|
||||
return qRound64(seconds * av_q2d(av_inv_q(c->stream->time_base))) + qMax((int64_t) 0, c->stream->start_time);
|
||||
}
|
||||
|
||||
int64_t playhead_to_timestamp(Clip* c, long playhead) {
|
||||
|
||||
@@ -2234,7 +2234,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
if (!panel_sequence_viewer->playing) {
|
||||
int rec_marker_size = 8;
|
||||
int rec_marker_size = 6;
|
||||
int rec_track_midY = rec_track_y + (rec_track_height >> 1);
|
||||
p.setBrush(Qt::white);
|
||||
QPoint cue_marker[3] = {
|
||||
|
||||
Reference in New Issue
Block a user