added basic audio recording functionality
This commit is contained in:
@@ -43,5 +43,7 @@
|
||||
<file>clock.png</file>
|
||||
<file>sequence.png</file>
|
||||
<file>folder.png</file>
|
||||
<file>record.png</file>
|
||||
<file>record-disabled.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -193,6 +193,7 @@ void Timeline::update_sequence() {
|
||||
ui->snappingButton->setEnabled(!null_sequence);
|
||||
ui->pushButton_4->setEnabled(!null_sequence);
|
||||
ui->pushButton_5->setEnabled(!null_sequence);
|
||||
ui->recordButton->setEnabled(!null_sequence);
|
||||
ui->addButton->setEnabled(!null_sequence);
|
||||
ui->headers->setEnabled(!null_sequence);
|
||||
|
||||
@@ -1152,3 +1153,7 @@ void Timeline::setScroll(int s) {
|
||||
ui->headers->set_scroll(s);
|
||||
repaint_timeline();
|
||||
}
|
||||
|
||||
void Timeline::on_recordButton_clicked() {
|
||||
qDebug() << "recording is a" << start_recording();
|
||||
}
|
||||
|
||||
@@ -194,6 +194,8 @@ private slots:
|
||||
|
||||
void setScroll(int);
|
||||
|
||||
void on_recordButton_clicked();
|
||||
|
||||
private:
|
||||
QVector<QPushButton*> tool_buttons;
|
||||
void decheck_tool_buttons(QObject* sender);
|
||||
|
||||
@@ -245,6 +245,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="recordButton">
|
||||
<property name="toolTip">
|
||||
<string>Record audio</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normalon>:/icons/record.png</normalon>
|
||||
<disabledon>:/icons/record-disabled.png</disabledon>
|
||||
</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addButton">
|
||||
<property name="toolTip">
|
||||
|
||||
@@ -263,6 +263,7 @@ void Viewer::pause() {
|
||||
playing = false;
|
||||
set_playpause_icon(true);
|
||||
playback_updater.stop();
|
||||
stop_recording();
|
||||
}
|
||||
|
||||
void Viewer::update_playhead_timecode(long p) {
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#include "ui_timeline.h"
|
||||
|
||||
#include <QAudioOutput>
|
||||
#include <QAudioInput>
|
||||
#include <QtMath>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
||||
extern "C" {
|
||||
@@ -19,6 +21,9 @@ QAudioOutput* audio_output;
|
||||
QIODevice* audio_io_device;
|
||||
bool audio_device_set = false;
|
||||
QMutex audio_write_lock;
|
||||
QAudioInput* audio_input = NULL;
|
||||
QFile output_recording;
|
||||
bool recording = false;
|
||||
|
||||
qint8 audio_ibuffer[audio_ibuffer_size];
|
||||
int audio_ibuffer_read = 0;
|
||||
@@ -177,3 +182,121 @@ int AudioSenderThread::send_audio_to_output(int offset, int max) {
|
||||
|
||||
return actual_write;
|
||||
}
|
||||
|
||||
void int32_to_char_array(qint32 i, char* array) {
|
||||
memcpy(array, &i, 4);
|
||||
}
|
||||
|
||||
void write_wave_header(QFile& f, const QAudioFormat& format) {
|
||||
qint32 int32bit;
|
||||
char arr[4];
|
||||
|
||||
// 4 byte riff header
|
||||
f.write("RIFF");
|
||||
|
||||
// 4 byte file size, filled in later
|
||||
for (int i=0;i<4;i++) f.putChar(0);
|
||||
|
||||
// 4 byte file type header + 4 byte format chunk marker
|
||||
f.write("WAVEfmt");
|
||||
f.putChar(0x20);
|
||||
|
||||
// 4 byte length of the above format data (always 16 bytes)
|
||||
f.putChar(16);
|
||||
for (int i=0;i<3;i++) f.putChar(0);
|
||||
|
||||
// 2 byte type format (1 is PCM)
|
||||
f.putChar(1);
|
||||
f.putChar(0);
|
||||
|
||||
// 2 byte channel count (2 for stereo)
|
||||
f.putChar(2);
|
||||
f.putChar(0);
|
||||
|
||||
// 4 byte integer for sample rate
|
||||
int32bit = format.sampleRate();
|
||||
int32_to_char_array(int32bit, arr);
|
||||
f.write(arr, 4);
|
||||
|
||||
// 4 byte integer for bytes per second
|
||||
int32bit = (format.sampleRate() * format.sampleSize() * format.channelCount()) / 8;
|
||||
int32_to_char_array(int32bit, arr);
|
||||
f.write(arr, 4);
|
||||
|
||||
// 2 byte integer for bytes per sample per channel
|
||||
int32bit = (format.sampleSize() * format.channelCount()) / 8;
|
||||
int32_to_char_array(int32bit, arr);
|
||||
f.write(arr, 2);
|
||||
|
||||
// 2 byte integer for bits per sample (16)
|
||||
int32bit = format.sampleSize();
|
||||
int32_to_char_array(int32bit, arr);
|
||||
f.write(arr, 2);
|
||||
|
||||
// data chunk header
|
||||
f.write("data");
|
||||
|
||||
// 4 byte integer for data chunk size (filled in later)?
|
||||
for (int i=0;i<4;i++) f.putChar(0);
|
||||
}
|
||||
|
||||
void write_wave_trailer(QFile& f) {
|
||||
char arr[4];
|
||||
|
||||
f.seek(4);
|
||||
|
||||
// 4 bytes for total file size - 8 bytes
|
||||
qint32 file_size = f.size() - 8;
|
||||
int32_to_char_array(file_size, arr);
|
||||
f.write(arr, 4);
|
||||
|
||||
f.seek(40);
|
||||
|
||||
// 4 bytes for data chunk size (file size - header)
|
||||
file_size = f.size() - 44;
|
||||
int32_to_char_array(file_size, arr);
|
||||
f.write(arr, 4);
|
||||
}
|
||||
|
||||
bool start_recording() {
|
||||
if (sequence == NULL) {
|
||||
qDebug() << "[ERROR] No active sequence to record into";
|
||||
return false;
|
||||
}
|
||||
output_recording.setFileName("C:/Users/Matt/output.wav");
|
||||
if (!output_recording.open(QFile::WriteOnly)) {
|
||||
qDebug() << "[ERROR] Failed to open output file. Does Olive have permission to write to this directory?";
|
||||
return false;
|
||||
}
|
||||
|
||||
QAudioFormat audio_format = audio_output->format();
|
||||
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
|
||||
if (!info.isFormatSupported(audio_format)) {
|
||||
qDebug() << "[WARNING] Default format not supported, using nearest";
|
||||
audio_format = info.nearestFormat(audio_format);
|
||||
}
|
||||
write_wave_header(output_recording, audio_format);
|
||||
audio_input = new QAudioInput(audio_format);
|
||||
audio_input->start(&output_recording);
|
||||
recording = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void stop_recording() {
|
||||
if (recording) {
|
||||
audio_input->stop();
|
||||
|
||||
/*if (audio_input->state() == QAudio::ActiveState) {
|
||||
|
||||
}*/
|
||||
|
||||
write_wave_trailer(output_recording);
|
||||
|
||||
output_recording.close();
|
||||
|
||||
delete audio_input;
|
||||
audio_input = NULL;
|
||||
}
|
||||
recording = false;
|
||||
}
|
||||
|
||||
@@ -46,4 +46,8 @@ void init_audio(Sequence *s);
|
||||
void stop_audio();
|
||||
int get_buffer_offset_from_frame(Sequence *s, long frame);
|
||||
|
||||
bool start_recording();
|
||||
void stop_recording();
|
||||
extern bool recording;
|
||||
|
||||
#endif // AUDIO_H
|
||||
|
||||
+2
-1
@@ -529,7 +529,8 @@ void ViewerWidget::paintGL() {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
} while (loop);
|
||||
|
||||
if (viewer->playing
|
||||
if (!recording
|
||||
&& viewer->playing
|
||||
&& (viewer->seq->playhead == viewer->seq->getEndFrame() || (viewer->seq->using_workarea && viewer->seq->playhead >= viewer->seq->workarea_out))) {
|
||||
viewer->pause();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user