Skip to content

Commit

Permalink
PCM-1 manual offset, fixed STC-007 CWD, GUI fixes
Browse files Browse the repository at this point in the history
Added manual vertical data offset control for PCM-1, fixed PCM-1 stray header line processing as audio, fixed STC-007 CWD, added display for STC-007 address code, moved VU-envelope generation into AudioProcessor to reduce GUI lagging, small AudioProcessor rework to support advanced interpolation modes in the future, visualizer optimizations, added new tooltips and translations.
  • Loading branch information
Fagear committed Nov 10, 2022
1 parent 7f335e5 commit e481fe8
Show file tree
Hide file tree
Showing 42 changed files with 4,620 additions and 3,338 deletions.
6 changes: 3 additions & 3 deletions SDVPCMdecoder.pro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
#-------------------------------------------------

QT += core gui winextras
QT += core gui opengl winextras

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets multimedia concurrent

Expand All @@ -28,10 +28,10 @@ QMAKE_CFLAGS_RELEASE += -O3 -march=pentium3m

QMAKE_CXXFLAGS+= -D__STDC_CONSTANT_MACROS -fpermissive

VERSION = 0.99.5
VERSION = 0.99.6
win32: QMAKE_TARGET_COMPANY = Fagear
win32: QMAKE_TARGET_PRODUCT = SD video PCM decoder
win32: QMAKE_TARGET_DESCRIPTION = SD video to digital audio PCM decoder
win32: QMAKE_TARGET_DESCRIPTION = SD video to digital audio decoder
win32: QMAKE_TARGET_COPYRIGHT = (c) Fagear
win32: RC_LANG = 0x0419

Expand Down
1,372 changes: 811 additions & 561 deletions SDVPCMdecoder_en.ts

Large diffs are not rendered by default.

1,373 changes: 807 additions & 566 deletions SDVPCMdecoder_pl.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion about_wnd.ui
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-1&lt;/span&gt; (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-1600&lt;/span&gt; (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-1610&lt;/span&gt; (2 канала, 16 бит, 44056/44100 Гц, NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-1630&lt;/span&gt; (2 канала, 16 бит, 44056/44100 Гц, NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;STC-007&lt;/span&gt; (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;STC-008&lt;/span&gt; (2 канала, 14 бит, 44100 Гц, EIAJ PAL)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-F1&lt;/span&gt; (2 канала, 16 бит, 44056/44100 Гц, NTSC/PAL)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-1&lt;/span&gt; (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-1600&lt;/span&gt; (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-1610&lt;/span&gt; (2 канала, 16 бит, 44056/44100 Гц, NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-1630&lt;/span&gt; (2 канала, 16 бит, 44056/44100 Гц, NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;STC-007&lt;/span&gt; (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;STC-008&lt;/span&gt; (2 канала, 14 бит, 44100 Гц, EIAJ PAL)&lt;br/&gt;+ &lt;span style=&quot; font-weight:600;&quot;&gt;PCM-F1&lt;/span&gt; (2 канала, 16 бит, 44056/44100 Гц, Sony PCM-F1, NTSC/PAL)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
Expand Down
240 changes: 166 additions & 74 deletions audioprocessor.cpp

Large diffs are not rendered by default.

36 changes: 22 additions & 14 deletions audioprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <QString>
#include "config.h"
#include "frametrimset.h"
#include "lookup.h"
#include "pcmsamplepair.h"
#include "samples2audio.h"
#include "samples2wav.h"
Expand Down Expand Up @@ -48,7 +49,7 @@ class AudioProcessor : public QObject
MIN_LONG_INVALID = 16, // Minimum length of invalid region to be count as long.
MAX_STRAY_LEN = 24, // Maximum length of valid region to be count as stray.
MIN_VALID_BEFORE = 3, // Minimum number of valid data points to keep at the start of the buffer.
MAX_RAMP_DOWN = 128, // Length of ramp-down to mute region (in data points).
MAX_RAMP_DOWN = 192, // Length of ramp-down to mute region (in data points).
MAX_RAMP_UP = 32, // Length of ramp-up from mute region (in data points).
CHANNEL_CNT = PCMSamplePair::CH_MAX, // Number of channels for processing.
};
Expand All @@ -75,21 +76,22 @@ class AudioProcessor : public QObject
private:
SamplesToAudio sc_output; // Handler for soundcard operations.
SamplesToWAV wav_output; // Handler for WAV-file operations.
QString file_path;
QString file_name;
std::deque<PCMSamplePair> *in_samples; // Input sample pair queue (shared).
QMutex *mtx_samples; // Mutex for input queue.
QTimer *tim_outflush;
QTimer *tim_outflush; // Timer for dumping output from cache when input stalles.
QTimer *tim_vu_fade; // Timer for VU levels drop off.
std::deque<PCMSamplePair> prebuffer; // Buffer for input data.
std::deque<PCMSample> channel_bufs[CHANNEL_CNT]; // Per-channel buffers for sample processing.
std::deque<CoordinatePair> long_bads[CHANNEL_CNT];
std::deque<CoordinatePair> long_bads[CHANNEL_CNT]; // Per-channel buffers for regions of long invalid samples.
uint8_t log_level; // Level of debug output.
uint8_t mask_mode; // Mode of masking dropouts.
uint16_t min_valid_before;
uint16_t max_ramp_down;
uint16_t max_ramp_up;
uint16_t min_valid_before; // Minimum number of valid data points at the front of the buffer.
uint16_t max_ramp_down; // Length of ramp-down for interpolation from last valid sample into silence (inside invalid region).
uint16_t max_ramp_up; // Length of ramp-up for interpolation from silence (inside invalid region) into first valid sample.
uint64_t sample_index; // Master index for samples for the current file.
uint16_t sample_rate; // Last sample rate.
uint8_t vu_left; // VU-level for the left channel.
uint8_t vu_right; // VU-level for the right channel.
bool file_end; // Detected end of a file.
bool unprocessed; // Are there unprocessed audio samples?
bool remove_stray; // Invalidate stray VALID samples.
Expand All @@ -109,21 +111,25 @@ class AudioProcessor : public QObject
uint16_t setInvalids(std::deque<PCMSample> *samples, CoordinatePair &range);
void fixStraySamples(std::deque<PCMSample> *samples, std::deque<CoordinatePair> *regions);
uint16_t clearInvalids(std::deque<PCMSample> *samples, CoordinatePair &range);
uint16_t performMute(std::deque<PCMSample> *samples, CoordinatePair &range);
uint16_t performLevelHold(std::deque<PCMSample> *samples, CoordinatePair &range);
uint16_t performLinearInterpolation(std::deque<PCMSample> *samples, CoordinatePair &range);
uint16_t sampleMute(std::deque<PCMSample> *samples, int16_t offset);
uint16_t rangeMute(std::deque<PCMSample> *samples, CoordinatePair &range);
uint16_t rangeLevelHold(std::deque<PCMSample> *samples, CoordinatePair &range);
uint16_t rangeLinearInterpolation(std::deque<PCMSample> *samples, CoordinatePair &range);
void fixBadSamples(std::deque<PCMSample> *samples);
void dumpPrebuffer();
void fillBufferForOutput();
void samplesToVU(PCMSamplePair *in_samples);
void outputWordPair(PCMSamplePair *out_samples);
void outputAudio();
bool scanBuffer();
void dumpBuffer();

private slots:
void restartFlushTimer();
void actCloseOutput();
void restartFlushTimer(); // Stop and start flushing timer.
void redirectError(QString); // Receive error message and redirect it.
void actFlushOutput(); // Timer event for flushing buffer.
void livePlayUpdate(bool); // Emit [guiLivePB] signal to report live playback state.
void updateVUMeters(); // Timer event for VU-meters updating and fading.

public slots:
void setLogLevel(uint8_t); // Set logging level.
Expand All @@ -139,9 +145,11 @@ public slots:
signals:
void guiAddMask(uint16_t); // Report new masked samples.
void guiLivePB(bool); // Report live playback state.
void mediaError(QString); // Error while processing audio.
void newSource(); // Report about changed source.
void reqTimerRestart();
void reqTimerRestart(); // Deffered call for [restartFlushTimer()].
void outSamples(PCMSamplePair); // Copy of outputting samples.
void outVULevels(uint8_t, uint8_t); // Report VU-meters.
void stopOutput(); // Report about thread terminating.
void finished();
};
Expand Down
4 changes: 2 additions & 2 deletions binarizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
*
* This module takes one video line (of type [VideoLine]) and performs:
* - AGC (Automatic Gain Control), statistically detecting BLACK and WHITE levels;
* - Automatic reference level detection, detecting the best threshold for binarization;
* - ARLD (Automatic Reference Level Detection), detecting the best threshold for binarization;
* - TBC (Time-Based Correction), detecting horizontal offset of the PCM data in the line;
* - binarization with set mode;
* - Binarization with set mode;
* - Brute force picking bits that were cut off the edge of the video line (for PCM-1 and PCM-16x0).
*
* Binarization itself can be done with different speed/quality ratios,
Expand Down
8 changes: 7 additions & 1 deletion capt_sel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ capt_sel::capt_sel(QWidget *parent) :
capt_dev = NULL;
capture_rate = 100;

//ui->viewport->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
ui->viewport->setOptimizationFlags(QGraphicsView::DontSavePainterState|QGraphicsView::DontAdjustForAntialiasing);

scene = new QGraphicsScene(this);
ui->viewport->setScene(scene);
ui->viewport->setAlignment(Qt::AlignLeft|Qt::AlignTop);
Expand Down Expand Up @@ -42,7 +45,7 @@ capt_sel::capt_sel(QWidget *parent) :
connect(capt_dev, SIGNAL(sigInputClosed()), this, SLOT(captureClosed()));
connect(capt_dev, SIGNAL(sigVideoError(uint32_t)), this, SLOT(captureError(uint32_t)));
connect(capt_dev, SIGNAL(newDeviceList(VCapList)), this, SLOT(refillDevList(VCapList)));
ffmpeg_thread->start();
ffmpeg_thread->start(QThread::HighPriority);

connect(ui->btnClose, SIGNAL(clicked(bool)), this, SLOT(usrClose()));
connect(ui->btnSave, SIGNAL(clicked(bool)), this, SLOT(usrSave()));
Expand Down Expand Up @@ -466,8 +469,10 @@ void capt_sel::redrawPreview(QImage in_image, bool in_double)
return;
}
draw_rate = capt_meas.elapsed();
// Check if this frame contains dropped frames counter.
if(in_image.height()!=FFMPEGWrapper::DUMMY_HEIGTH)
{
// It's normal frame for displaying.
//qDebug()<<"[CSEL] New image";
// Update pixmap.
pixels->setPixmap(QPixmap::fromImage(in_image.copy()));
Expand All @@ -488,6 +493,7 @@ void capt_sel::redrawPreview(QImage in_image, bool in_double)
}
else
{
// It's a dummy, containing dropped frames counter.
qDebug()<<"[CSEL] New dummy image";
// Skip dummy frame and request next one.
pollCapture();
Expand Down
Loading

0 comments on commit e481fe8

Please sign in to comment.