kopia lustrzana https://github.com/windytan/slowrx
aspects etc
rodzic
370b29ab72
commit
9a5db6c3b5
|
@ -1,4 +1,4 @@
|
|||
bin_PROGRAMS = slowrx
|
||||
slowrx_CPPFLAGS = -g $(GTKMM_CFLAGS) @SNDFILE_CFLAGS@
|
||||
slowrx_LDADD = $(GTKMM_LIBS) @SNDFILE_LIBS@ -lfftw3
|
||||
slowrx_SOURCES = slowrx.cc common.cc modespec.cc gui.cc pcm.cc vis.cc video.cc
|
||||
slowrx_SOURCES = slowrx.cc common.cc modespec.cc gui.cc dsp.cc vis.cc video.cc
|
||||
|
|
|
@ -16,7 +16,7 @@ Glib::RefPtr<Gdk::Pixbuf> pixbuf_disp;
|
|||
|
||||
Glib::KeyFile config;
|
||||
|
||||
vector<thread> threads(2);
|
||||
std::vector<std::thread> threads(2);
|
||||
|
||||
PicMeta CurrentPic;
|
||||
PcmData pcm;
|
||||
|
@ -41,7 +41,7 @@ double rad2deg (double rad) {
|
|||
return (180 / M_PI) * rad;
|
||||
}
|
||||
|
||||
void ensure_dir_exists(string dir) {
|
||||
void ensure_dir_exists(std::string dir) {
|
||||
struct stat buf;
|
||||
|
||||
int i = stat(dir.c_str(), &buf);
|
||||
|
@ -55,23 +55,23 @@ void ensure_dir_exists(string dir) {
|
|||
|
||||
// Save current picture as PNG
|
||||
void saveCurrentPic() {
|
||||
Glib::RefPtr<Gdk::Pixbuf> scaledpb;
|
||||
/*Glib::RefPtr<Gdk::Pixbuf> scaledpb;
|
||||
|
||||
stringstream ss;
|
||||
string basename = config.get_string("slowrx","rxdir");
|
||||
std::stringstream ss;
|
||||
std::string basename = config.get_std::string("slowrx","rxdir");
|
||||
|
||||
ss << basename << "/" << CurrentPic.timestr << "_" << ModeSpec[CurrentPic.Mode].ShortName;
|
||||
|
||||
string pngfilename = ss.str();
|
||||
std::string pngfilename = ss.str();
|
||||
cout << " Saving to " << pngfilename << "\n";
|
||||
|
||||
scaledpb = pixbuf_rx->scale_simple(ModeSpec[CurrentPic.Mode].ImgWidth,
|
||||
scaledpb = pixbuf_rx->scale_simple(ModeSpec[CurrentPic.Mode].ScanPixels,
|
||||
ModeSpec[CurrentPic.Mode].NumLines * ModeSpec[CurrentPic.Mode].LineHeight, Gdk::INTERP_HYPER);
|
||||
|
||||
ensure_dir_exists(config.get_string("slowrx","rxdir"));
|
||||
ensure_dir_exists(config.get_std::string("slowrx","rxdir"));
|
||||
scaledpb->save(pngfilename, "png");
|
||||
//g_object_unref(scaledpb);
|
||||
//g_string_free(pngfilename, true);
|
||||
//g_std::string_free(pngfilename, true);*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
#include "fftw3.h"
|
||||
#include "gtkmm.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
enum WindowType {
|
||||
WINDOW_HANN47 = 0,
|
||||
WINDOW_HANN63,
|
||||
|
@ -31,12 +29,11 @@ enum WindowType {
|
|||
|
||||
enum SSTVMode {
|
||||
MODE_UNKNOWN=0,
|
||||
MODE_M1, MODE_M2, MODE_M3, MODE_M4,
|
||||
MODE_S1, MODE_S2, MODE_SDX,
|
||||
MODE_R72, MODE_R36, MODE_R24, MODE_R24BW, MODE_R12BW, MODE_R8BW,
|
||||
MODE_PD50, MODE_PD90, MODE_PD120, MODE_PD160, MODE_PD180, MODE_PD240, MODE_PD290,
|
||||
MODE_P3, MODE_P5, MODE_P7,
|
||||
MODE_W2120, MODE_W2180
|
||||
MODE_M1, MODE_M2, MODE_M3, MODE_M4, MODE_S1,
|
||||
MODE_S2, MODE_SDX, MODE_R72, MODE_R36, MODE_R24,
|
||||
MODE_R24BW, MODE_R12BW, MODE_R8BW, MODE_PD50, MODE_PD90,
|
||||
MODE_PD120, MODE_PD160, MODE_PD180, MODE_PD240, MODE_PD290,
|
||||
MODE_P3, MODE_P5, MODE_P7, MODE_W2120, MODE_W2180
|
||||
};
|
||||
|
||||
enum eColorEnc {
|
||||
|
@ -51,7 +48,7 @@ enum eSubSamp {
|
|||
SUBSAMP_444, SUBSAMP_422_YUV, SUBSAMP_420_YUYV, SUBSAMP_440_YUVY
|
||||
};
|
||||
|
||||
extern map<int, SSTVMode> vis2mode;
|
||||
extern std::map<int, SSTVMode> vis2mode;
|
||||
|
||||
typedef struct _FFTStuff FFTStuff;
|
||||
struct _FFTStuff {
|
||||
|
@ -79,18 +76,19 @@ class DSPworker {
|
|||
|
||||
DSPworker();
|
||||
|
||||
void open_audio_file(string);
|
||||
void read_more();
|
||||
void open_audio_file(std::string);
|
||||
double forward(unsigned);
|
||||
double forward();
|
||||
double forward_ms(double);
|
||||
void get_windowed_moment(WindowType, double *);
|
||||
double get_peak_freq (double, double, WindowType);
|
||||
int GetBin (double);
|
||||
double FourierPower (fftw_complex coeff);
|
||||
void getWindowedMoment(WindowType, double *);
|
||||
double getPeakFreq (double, double, WindowType);
|
||||
int getBin (double);
|
||||
double getFourierPower (fftw_complex coeff);
|
||||
bool is_still_listening ();
|
||||
|
||||
vector<short> getsamples(int);
|
||||
std::vector<double> getBandPowerPerHz(std::vector<std::vector<double> >);
|
||||
WindowType getBestWindowFor(SSTVMode, double);
|
||||
WindowType getBestWindowFor(SSTVMode);
|
||||
void readMore();
|
||||
|
||||
static short win_lens_[8];
|
||||
static double window_[8][1024];
|
||||
|
@ -178,19 +176,19 @@ extern PicMeta CurrentPic;
|
|||
|
||||
|
||||
typedef struct ModeSpec {
|
||||
string Name;
|
||||
string ShortName;
|
||||
double tSync;
|
||||
double tPorch;
|
||||
double tSep;
|
||||
double tScan;
|
||||
double tLine;
|
||||
int ImgWidth;
|
||||
int NumLines;
|
||||
int LineHeight;
|
||||
eColorEnc ColorEnc;
|
||||
std::string Name;
|
||||
std::string ShortName;
|
||||
double tSync;
|
||||
double tPorch;
|
||||
double tSep;
|
||||
double tScan;
|
||||
double tLine;
|
||||
int ScanPixels;
|
||||
int NumLines;
|
||||
int HeaderLines;
|
||||
eColorEnc ColorEnc;
|
||||
eSyncOrder SyncOrder;
|
||||
eSubSamp SubSamp;
|
||||
eSubSamp SubSampling;
|
||||
} _ModeSpec;
|
||||
|
||||
extern _ModeSpec ModeSpec[];
|
||||
|
@ -200,8 +198,8 @@ int clip (double a);
|
|||
void createGUI ();
|
||||
double deg2rad (double Deg);
|
||||
double FindSync (SSTVMode Mode, double Rate, int *Skip);
|
||||
string GetFSK ();
|
||||
bool GetVideo (SSTVMode Mode, double Rate, DSPworker *dsp, bool Redraw);
|
||||
std::string GetFSK ();
|
||||
bool GetVideo (SSTVMode Mode, DSPworker *dsp);
|
||||
SSTVMode GetVIS (DSPworker*);
|
||||
int initPcmDevice (std::string);
|
||||
void *Listen ();
|
||||
|
|
|
@ -8,7 +8,7 @@ DSPworker::DSPworker() : Mutex(), please_stop_(false) {
|
|||
for (int i = 0; i < win_lens_[j]; i++)
|
||||
window_[j][i] = 0.5 * (1 - cos( (2 * M_PI * i) / (win_lens_[j] - 1)) );
|
||||
|
||||
vector<double> cheb = {
|
||||
std::vector<double> cheb = {
|
||||
0.0004272315,0.0013212953,0.0032312239,0.0067664313,0.0127521667,0.0222058684,
|
||||
0.0363037629,0.0563165400,0.0835138389,0.1190416120,0.1637810511,0.2182020094,
|
||||
0.2822270091,0.3551233730,0.4354402894,0.5210045495,0.6089834347,0.6960162864,
|
||||
|
@ -44,12 +44,12 @@ DSPworker::DSPworker() : Mutex(), please_stop_(false) {
|
|||
|
||||
printf("DSPworker created\n");
|
||||
|
||||
//open_audio_file("/Users/windy/Audio/sig/sstv/robot72-02.wav");
|
||||
open_audio_file("/Users/windy/Movies/sstv-iss.wav");
|
||||
open_audio_file("/Users/windy/Audio/sig/sstv/scottie2-01-noiseonly.wav");
|
||||
//open_audio_file("/Users/windy/Movies/sstv-iss.wav");
|
||||
//open_audio_file("/Users/windy/Audio/sig/1000Hz-800Hz.wav");
|
||||
}
|
||||
|
||||
void DSPworker::open_audio_file (string fname) {
|
||||
void DSPworker::open_audio_file (std::string fname) {
|
||||
|
||||
file_ = SndfileHandle(fname.c_str()) ;
|
||||
|
||||
|
@ -59,16 +59,14 @@ void DSPworker::open_audio_file (string fname) {
|
|||
|
||||
samplerate_ = file_.samplerate();
|
||||
|
||||
//puts ("") ;
|
||||
|
||||
/* RAII takes care of destroying SndfileHandle object. */
|
||||
}
|
||||
|
||||
int DSPworker::GetBin (double freq) {
|
||||
int DSPworker::getBin (double freq) {
|
||||
return (freq / samplerate_ * fft_len_);
|
||||
}
|
||||
|
||||
double DSPworker::FourierPower (fftw_complex coeff) {
|
||||
double DSPworker::getFourierPower (fftw_complex coeff) {
|
||||
return pow(coeff[0],2) + pow(coeff[1],2);
|
||||
}
|
||||
|
||||
|
@ -76,8 +74,7 @@ bool DSPworker::is_still_listening () {
|
|||
return is_still_listening_;
|
||||
}
|
||||
|
||||
|
||||
void DSPworker::read_more () {
|
||||
void DSPworker::readMore () {
|
||||
short read_buffer[READ_CHUNK_LEN];
|
||||
|
||||
sf_count_t samplesread = file_.read(read_buffer, READ_CHUNK_LEN);
|
||||
|
@ -108,7 +105,7 @@ double DSPworker::forward (unsigned nsamples) {
|
|||
cirbuf_tail_ = (cirbuf_tail_ + 1) % CIRBUF_LEN;
|
||||
cirbuf_fill_count_ -= 1;
|
||||
if (cirbuf_fill_count_ < MOMENT_LEN) {
|
||||
read_more();
|
||||
readMore();
|
||||
}
|
||||
}
|
||||
return (1.0 * nsamples / samplerate_);
|
||||
|
@ -121,7 +118,7 @@ double DSPworker::forward_ms(double ms) {
|
|||
}
|
||||
|
||||
// the current moment, windowed
|
||||
void DSPworker::get_windowed_moment (WindowType win_type, double *result) {
|
||||
void DSPworker::getWindowedMoment (WindowType win_type, double *result) {
|
||||
for (int i = 0; i < MOMENT_LEN; i++) {
|
||||
|
||||
int win_i = i - MOMENT_LEN/2 + win_lens_[win_type]/2 ;
|
||||
|
@ -133,22 +130,22 @@ void DSPworker::get_windowed_moment (WindowType win_type, double *result) {
|
|||
|
||||
}
|
||||
|
||||
double DSPworker::get_peak_freq (double minf, double maxf, WindowType wintype) {
|
||||
double DSPworker::getPeakFreq (double minf, double maxf, WindowType wintype) {
|
||||
|
||||
double windowed[win_lens_[wintype]];
|
||||
double Power[fft_len_];
|
||||
|
||||
get_windowed_moment(wintype, windowed);
|
||||
getWindowedMoment(wintype, windowed);
|
||||
//for (int i=0;i<win_lens_[wintype];i++)
|
||||
// printf("g %f\n",windowed[i]);
|
||||
memset (fft_inbuf_, 0, fft_len_ * sizeof(double));
|
||||
memset(fft_inbuf_, 0, fft_len_ * sizeof(double));
|
||||
memcpy(fft_inbuf_, windowed, win_lens_[wintype] * sizeof(double));
|
||||
fftw_execute(fft_plan_);
|
||||
// Find the bin with most power
|
||||
int MaxBin = 0;
|
||||
for (int i = GetBin(minf)-1; i <= GetBin(maxf)+1; i++) {
|
||||
Power[i] = FourierPower(fft_outbuf_[i]);
|
||||
if ( (i >= GetBin(minf) && i < GetBin(maxf)) &&
|
||||
for (int i = getBin(minf)-1; i <= getBin(maxf)+1; i++) {
|
||||
Power[i] = getFourierPower(fft_outbuf_[i]);
|
||||
if ( (i >= getBin(minf) && i < getBin(maxf)) &&
|
||||
(MaxBin == 0 || Power[i] > Power[MaxBin]))
|
||||
MaxBin = i;
|
||||
}
|
||||
|
@ -164,6 +161,48 @@ double DSPworker::get_peak_freq (double minf, double maxf, WindowType wintype) {
|
|||
|
||||
}
|
||||
|
||||
std::vector<double> DSPworker::getBandPowerPerHz(std::vector<std::vector<double> > bands) {
|
||||
double windowed[win_lens_[WINDOW_HANN1023]];
|
||||
|
||||
getWindowedMoment(WINDOW_HANN1023, windowed);
|
||||
memset(fft_inbuf_, 0, fft_len_ * sizeof(double));
|
||||
memcpy(fft_inbuf_, windowed, win_lens_[WINDOW_HANN1023] * sizeof(double));
|
||||
fftw_execute(fft_plan_);
|
||||
|
||||
std::vector<double> result;
|
||||
for (std::vector<double> band : bands) {
|
||||
double P = 0;
|
||||
int nbins = 0;
|
||||
for (int i = getBin(band[0]); i <= getBin(band[1]); i++) {
|
||||
P += getFourierPower(fft_outbuf_[i]);
|
||||
nbins++;
|
||||
}
|
||||
P = P/nbins;
|
||||
result.push_back(P);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
WindowType DSPworker::getBestWindowFor(SSTVMode Mode, double SNR) {
|
||||
WindowType WinType;
|
||||
|
||||
if (SNR >= 20) WinType = WINDOW_CHEB47;
|
||||
else if (SNR >= 10) WinType = WINDOW_HANN63;
|
||||
else if (SNR >= 9) WinType = WINDOW_HANN95;
|
||||
else if (SNR >= 3) WinType = WINDOW_HANN127;
|
||||
else if (SNR >= -5) WinType = WINDOW_HANN255;
|
||||
else if (SNR >= -10) WinType = WINDOW_HANN511;
|
||||
else WinType = WINDOW_HANN1023;
|
||||
|
||||
// Minimum winlength can be doubled for Scottie DX
|
||||
//if (Mode == MODE_SDX && WinType < WINDOW_HANN511) WinType++;
|
||||
|
||||
return WinType;
|
||||
}
|
||||
WindowType DSPworker::getBestWindowFor(SSTVMode Mode) {
|
||||
return getBestWindowFor(Mode, 99);
|
||||
}
|
||||
|
||||
/*
|
||||
// Capture fresh PCM data to buffer
|
||||
void readPcm(int numsamples) {
|
||||
|
@ -247,7 +286,7 @@ void populateDeviceList() {
|
|||
// 0 = opened ok
|
||||
// -1 = opened, but suboptimal
|
||||
// -2 = couldn't be opened
|
||||
int initPcmDevice(string wanted_dev_name) {
|
||||
int initPcmDevice(std::string wanted_dev_name) {
|
||||
|
||||
//snd_pcm_hw_params_t *hwparams;
|
||||
void *hwparams;
|
54
src/fsk.cc
54
src/fsk.cc
|
@ -1,4 +1,4 @@
|
|||
#include "common.h"
|
||||
#include "common.hh"
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -10,23 +10,15 @@
|
|||
*
|
||||
*/
|
||||
|
||||
vector<double> WindowHann (int len) {
|
||||
vector<double> result(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
result[i] = 0.5 * (1 - cos( 2 * M_PI * i / (1.0*len-1) ) );
|
||||
return result;
|
||||
}
|
||||
string GetFSK (DSPworker *dsp) {
|
||||
|
||||
string GetFSK () {
|
||||
|
||||
guint fft_len = 2048, i=0, lo_bin, hi_bin, mid_bin, test_num=0, test_ptr=0;
|
||||
char *dest;
|
||||
guint i=0, test_num=0, test_ptr=0;
|
||||
guchar bit = 0, ascii_byte = 0, byte_ptr = 0, test_bits[24] = {0}, bit_ptr=0;
|
||||
double hi_pow,lo_pow
|
||||
vector<double> Hann;
|
||||
bool is_in_sync = false;
|
||||
|
||||
// bit-reversion lookup table
|
||||
static const guchar bit_rev[] = {
|
||||
static const guint8 bit_rev[] = {
|
||||
0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38,
|
||||
0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c,
|
||||
0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a,
|
||||
|
@ -36,43 +28,11 @@ string GetFSK () {
|
|||
0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b,
|
||||
0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f };
|
||||
|
||||
for (i = 0; i < fft_len; i++) fft.in[i] = 0;
|
||||
|
||||
// Create 22ms Hann window
|
||||
Hann = WindowHann(970);
|
||||
//for (i = 0; i < 970; i++) Hann[i] = 0.5 * (1 - cos( 2 * M_PI * i / 969.0 ) );
|
||||
|
||||
while ( true ) {
|
||||
|
||||
// Read data from DSP
|
||||
readPcm(is_in_sync ? 970: 485);
|
||||
|
||||
if (pcm.WindowPtr < 485) {
|
||||
pcm.WindowPtr += (is_in_sync ? 970 : 485);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Apply Hann window
|
||||
for (i = 0; i < 970; i++) fft.in[i] = pcm.Buffer[pcm.WindowPtr+i- 485] * Hann[i];
|
||||
vector<double> bands = dsp->getBandPowerPerHz({{1850,1950},{2050,2150}});
|
||||
|
||||
pcm.WindowPtr += (is_in_sync ? 970 : 485);
|
||||
|
||||
// FFT of last 22 ms
|
||||
fftw_execute(fft.Plan2048);
|
||||
|
||||
lo_bin = GetBin(1900+CurrentPic.HedrShift, fft_len)-1;
|
||||
mid_bin = GetBin(2000+CurrentPic.HedrShift, fft_len);
|
||||
hi_bin = GetBin(2100+CurrentPic.HedrShift, fft_len)+1;
|
||||
|
||||
lo_pow = 0;
|
||||
hi_pow = 0;
|
||||
|
||||
for (i = lo_bin; i <= hi_bin; i++) {
|
||||
if (i < mid_bin) lo_pow += power(fft.out[i]);
|
||||
else hi_pow += power(fft.out[i]);
|
||||
}
|
||||
|
||||
bit = (lo_pow > hi_pow) ? 1 : 0;
|
||||
bit = (bands[0] > bands[1]) ? 1 : 0;
|
||||
|
||||
if (!is_in_sync) {
|
||||
|
||||
|
|
724
src/modespec.cc
724
src/modespec.cc
|
@ -4,19 +4,19 @@
|
|||
* SSTV mode specifications
|
||||
* ========================
|
||||
*
|
||||
* Name Full human-readable name
|
||||
* ShortName Abbreviation used in filenames
|
||||
* ImgWidth Pixels per scanline
|
||||
* NumLines Number of scanlines
|
||||
* LineHeight Height of one scanline in pixels (1 or 2)
|
||||
* Name Full human-readable mode identifier
|
||||
* ShortName Abbreviation to be used in filenames
|
||||
* NumLines Total number of scanlines
|
||||
* HeaderLines Number of lines reserved for header, excluded from 4:3 ratio
|
||||
* ScanPixels Pixel samples per scanline and channel
|
||||
* tSync Duration of horizontal sync pulse
|
||||
* tPorch Duration of sync porch pulse
|
||||
* tSep Duration of channel separator pulse (+ separator porch)
|
||||
* tScan Duration of visible part of a channel scan (or Y if YUV)
|
||||
* tScan Duration of visible part of a channel scan (or Y scan if YUV)
|
||||
* tLine Time from the beginning of a sync pulse to the beginning
|
||||
* of the next one
|
||||
* SyncOrder Positioning of sync pulse (SYNC_SIMPLE, SYNC_SCOTTIE)
|
||||
* SubSamp Chroma subsampling mode for YUV (SUBSAMP_444, SUBSAMP_2121,
|
||||
* SubSampling Chroma subsampling mode for YUV (SUBSAMP_444, SUBSAMP_2121,
|
||||
* SUBSAMP_2112, SUBSAMP_211)
|
||||
* ColorEnc Color format (COLOR_GBR, COLOR_RGB, COLOR_YUV, COLOR_MONO)
|
||||
*
|
||||
|
@ -30,396 +30,398 @@
|
|||
*
|
||||
* Dave Jones KB4YZ (1999): "SSTV modes - line timing".
|
||||
* <http://www.tima.com/~djones/line.txt>
|
||||
*
|
||||
* Dave Jones KB4YZ (1998): "List of SSTV Modes with VIS Codes".
|
||||
* <http://www.tima.com/~djones/vis.txt>
|
||||
*/
|
||||
|
||||
_ModeSpec ModeSpec[] = {
|
||||
_ModeSpec ModeSpec[] = {
|
||||
|
||||
[MODE_M1] = { // N7CXI, 2000
|
||||
.Name = "Martin M1",
|
||||
.ShortName = "M1",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tSync = 4.862e-3,
|
||||
.tPorch = 0.572e-3,
|
||||
.tSep = 0.572e-3,
|
||||
.tScan = 146.432e-3,
|
||||
.tLine = 446.446e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
[MODE_M1] = { // N7CXI, 2000
|
||||
.Name = "Martin M1",
|
||||
.ShortName = "M1",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tSync = 4.862e-3,
|
||||
.tPorch = 0.572e-3,
|
||||
.tSep = 0.572e-3,
|
||||
.tScan = 146.432e-3,
|
||||
.tLine = 446.446e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
|
||||
[MODE_M2] = { // N7CXI, 2000
|
||||
.Name = "Martin M2",
|
||||
.ShortName = "M2",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tScan = 73.216e-3,
|
||||
.tLine = 226.7986e-3,
|
||||
.tSync = 4.862e-3,
|
||||
.tPorch = 0.572e-3,
|
||||
.tSep = 0.572e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
[MODE_M2] = { // N7CXI, 2000
|
||||
.Name = "Martin M2",
|
||||
.ShortName = "M2",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 73.216e-3,
|
||||
.tLine = 226.7986e-3,
|
||||
.tSync = 4.862e-3,
|
||||
.tPorch = 0.572e-3,
|
||||
.tSep = 0.572e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
|
||||
[MODE_M3] = { // KB4YZ, 1999
|
||||
.Name = "Martin M3",
|
||||
.ShortName = "M3",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 128,
|
||||
.LineHeight = 2,
|
||||
.tScan = 73.216e-3,
|
||||
.tLine = 446.446e-3,
|
||||
.tSync = 4.862e-3,
|
||||
.tPorch = 0.572e-3,
|
||||
.tSep = 0.572e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
[MODE_M3] = { // KB4YZ, 1999
|
||||
.Name = "Martin M3",
|
||||
.ShortName = "M3",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 128,
|
||||
.HeaderLines = 8,
|
||||
.tScan = 73.216e-3,
|
||||
.tLine = 446.446e-3,
|
||||
.tSync = 4.862e-3,
|
||||
.tPorch = 0.572e-3,
|
||||
.tSep = 0.572e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
|
||||
[MODE_M4] = { // KB4YZ, 1999
|
||||
.Name = "Martin M4",
|
||||
.ShortName = "M4",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 128,
|
||||
.LineHeight = 2,
|
||||
.tScan = 73.216e-3,
|
||||
.tLine = 226.7986e-3,
|
||||
.tSync = 4.862e-3,
|
||||
.tPorch = 0.572e-3,
|
||||
.tSep = 0.572e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
[MODE_M4] = { // KB4YZ, 1999
|
||||
.Name = "Martin M4",
|
||||
.ShortName = "M4",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 128,
|
||||
.HeaderLines = 8,
|
||||
.tScan = 73.216e-3,
|
||||
.tLine = 226.7986e-3,
|
||||
.tSync = 4.862e-3,
|
||||
.tPorch = 0.572e-3,
|
||||
.tSep = 0.572e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
|
||||
[MODE_S1] = { // N7CXI, 2000
|
||||
.Name = "Scottie S1",
|
||||
.ShortName = "S1",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 1.5e-3,
|
||||
.tSep = 1.5e-3,
|
||||
.tScan = 138.24e-3,
|
||||
.tLine = 428.22e-3,
|
||||
.SyncOrder = SYNC_SCOTTIE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
[MODE_S1] = { // N7CXI, 2000
|
||||
.Name = "Scottie S1",
|
||||
.ShortName = "S1",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 1.5e-3,
|
||||
.tSep = 1.5e-3,
|
||||
.tScan = 138.24e-3,
|
||||
.tLine = 428.22e-3,
|
||||
.SyncOrder = SYNC_SCOTTIE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
|
||||
[MODE_S2] = { // N7CXI, 2000
|
||||
.Name = "Scottie S2",
|
||||
.ShortName = "S2",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tScan = 88.064e-3,
|
||||
.tLine = 277.692e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 1.5e-3,
|
||||
.tSep = 1.5e-3,
|
||||
.SyncOrder = SYNC_SCOTTIE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
[MODE_S2] = { // N7CXI, 2000
|
||||
.Name = "Scottie S2",
|
||||
.ShortName = "S2",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 88.064e-3,
|
||||
.tLine = 277.692e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 1.5e-3,
|
||||
.tSep = 1.5e-3,
|
||||
.SyncOrder = SYNC_SCOTTIE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
|
||||
[MODE_SDX] = { // N7CXI, 2000
|
||||
.Name = "Scottie DX",
|
||||
.ShortName = "SDX",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tScan = 345.6e-3,
|
||||
.tLine = 1050.3e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 1.5e-3,
|
||||
.tSep = 1.5e-3,
|
||||
.SyncOrder = SYNC_SCOTTIE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
[MODE_SDX] = { // N7CXI, 2000
|
||||
.Name = "Scottie DX",
|
||||
.ShortName = "SDX",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 345.6e-3,
|
||||
.tLine = 1050.3e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 1.5e-3,
|
||||
.tSep = 1.5e-3,
|
||||
.SyncOrder = SYNC_SCOTTIE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_GBR },
|
||||
|
||||
[MODE_R72] = { // N7CXI, 2000
|
||||
.Name = "Robot 72",
|
||||
.ShortName = "R72",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 240,
|
||||
.LineHeight = 1,
|
||||
.tScan = 138e-3,
|
||||
.tLine = 300e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 3e-3,
|
||||
.tSep = 6e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_422_YUV,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_R72] = { // N7CXI, 2000
|
||||
.Name = "Robot 72",
|
||||
.ShortName = "R72",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 240,
|
||||
.HeaderLines = 0,
|
||||
.tScan = 138e-3,
|
||||
.tLine = 300e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 3e-3,
|
||||
.tSep = 6e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_422_YUV,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_R36] = { // N7CXI, 2000
|
||||
.Name = "Robot 36",
|
||||
.ShortName = "R36",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 240,
|
||||
.LineHeight = 1,
|
||||
.tScan = 88e-3,
|
||||
.tLine = 150e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 3e-3,
|
||||
.tSep = 6e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_420_YUYV,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_R36] = { // N7CXI, 2000
|
||||
.Name = "Robot 36",
|
||||
.ShortName = "R36",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 240,
|
||||
.HeaderLines = 0,
|
||||
.tScan = 88e-3,
|
||||
.tLine = 150e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 3e-3,
|
||||
.tSep = 6e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_420_YUYV,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_R24] = { // KB4YZ, 1999
|
||||
.Name = "Robot 24",
|
||||
.ShortName = "R24",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 240,
|
||||
.LineHeight = 1,
|
||||
.tScan = 66e-3,
|
||||
.tLine = 150e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 3e-3,
|
||||
.tSep = 6e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_420_YUYV,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_R24] = { // KB4YZ, 1999
|
||||
.Name = "Robot 24",
|
||||
.ShortName = "R24",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 240,
|
||||
.HeaderLines = 0,
|
||||
.tScan = 66e-3,
|
||||
.tLine = 150e-3,
|
||||
.tSync = 9e-3,
|
||||
.tPorch = 3e-3,
|
||||
.tSep = 6e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_420_YUYV,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_R24BW] = { // KB4YZ, 1999
|
||||
.Name = "Robot 24 B/W",
|
||||
.ShortName = "R24BW",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 240,
|
||||
.LineHeight = 1,
|
||||
.tScan = 66e-3,
|
||||
.tLine = 100e-3,
|
||||
.tSync = 7e-3,
|
||||
.tPorch = 0,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_MONO },
|
||||
[MODE_R24BW] = { // KB4YZ, 1999
|
||||
.Name = "Robot 24 B/W",
|
||||
.ShortName = "R24BW",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 240,
|
||||
.HeaderLines = 0,
|
||||
.tScan = 66e-3,
|
||||
.tLine = 100e-3,
|
||||
.tSync = 7e-3,
|
||||
.tPorch = 0,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_MONO },
|
||||
|
||||
[MODE_R12BW] = { // KB4YZ, 1999
|
||||
.Name = "Robot 12 B/W",
|
||||
.ShortName = "R12BW",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 120,
|
||||
.LineHeight = 2,
|
||||
.tScan = 66e-3,
|
||||
.tLine = 100e-3,
|
||||
.tSync = 7e-3,
|
||||
.tPorch = 0,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_MONO },
|
||||
[MODE_R12BW] = { // KB4YZ, 1999
|
||||
.Name = "Robot 12 B/W",
|
||||
.ShortName = "R12BW",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 120,
|
||||
.HeaderLines = 0,
|
||||
.tScan = 66e-3,
|
||||
.tLine = 100e-3,
|
||||
.tSync = 7e-3,
|
||||
.tPorch = 0,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_MONO },
|
||||
|
||||
[MODE_R8BW] = { // KB4YZ, 1999
|
||||
.Name = "Robot 8 B/W",
|
||||
.ShortName = "R8BW",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 120,
|
||||
.LineHeight = 2,
|
||||
.tScan = 60e-3,
|
||||
.tLine = 67e-3,
|
||||
.tSync = 7e-3,
|
||||
.tPorch = 0,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_MONO },
|
||||
[MODE_R8BW] = { // KB4YZ, 1999
|
||||
.Name = "Robot 8 B/W",
|
||||
.ShortName = "R8BW",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 120,
|
||||
.HeaderLines = 0,
|
||||
.tScan = 60e-3,
|
||||
.tLine = 67e-3,
|
||||
.tSync = 7e-3,
|
||||
.tPorch = 0,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_MONO },
|
||||
|
||||
[MODE_W2120] = { // KB4YZ, 1999
|
||||
.Name = "Wraase SC-2 120",
|
||||
.ShortName = "W2120",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tScan = 156.5025e-3,
|
||||
.tLine = 475.530018e-3,
|
||||
.tSync = 5.5225e-3,
|
||||
.tPorch = 0.5e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB },
|
||||
[MODE_W2120] = { // KB4YZ, 1999
|
||||
.Name = "Wraase SC-2 120",
|
||||
.ShortName = "W2120",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 156.5025e-3,
|
||||
.tLine = 475.530018e-3,
|
||||
.tSync = 5.5225e-3,
|
||||
.tPorch = 0.5e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB },
|
||||
|
||||
[MODE_W2180] = { // N7CXI, 2000
|
||||
.Name = "Wraase SC-2 180",
|
||||
.ShortName = "W2180",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tScan = 235e-3,
|
||||
.tLine = 711.0225e-3,
|
||||
.tSync = 5.5225e-3,
|
||||
.tPorch = 0.5e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB },
|
||||
[MODE_W2180] = { // N7CXI, 2000
|
||||
.Name = "Wraase SC-2 180",
|
||||
.ShortName = "W2180",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 235e-3,
|
||||
.tLine = 711.0225e-3,
|
||||
.tSync = 5.5225e-3,
|
||||
.tPorch = 0.5e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB },
|
||||
|
||||
[MODE_PD50] = { // N7CXI, 2000
|
||||
.Name = "PD-50",
|
||||
.ShortName = "PD50",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tScan = 91.52e-3,
|
||||
.tLine = 388.16e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_PD50] = { // N7CXI, 2000
|
||||
.Name = "PD-50",
|
||||
.ShortName = "PD50",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 91.52e-3,
|
||||
.tLine = 388.16e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_PD90] = { // N7CXI, 2000
|
||||
.Name = "PD-90",
|
||||
.ShortName = "PD90",
|
||||
.ImgWidth = 320,
|
||||
.NumLines = 256,
|
||||
.LineHeight = 1,
|
||||
.tScan = 170.240e-3,
|
||||
.tLine = 703.04e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_PD90] = { // N7CXI, 2000
|
||||
.Name = "PD-90",
|
||||
.ShortName = "PD90",
|
||||
.ScanPixels = 320,
|
||||
.NumLines = 256,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 170.240e-3,
|
||||
.tLine = 703.04e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_PD120] = { // N7CXI, 2000
|
||||
.Name = "PD-120",
|
||||
.ShortName = "PD120",
|
||||
.ImgWidth = 640,
|
||||
.NumLines = 496,
|
||||
.LineHeight = 1,
|
||||
.tScan = 121.6e-3,
|
||||
.tLine = 508.48e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_PD120] = { // N7CXI, 2000
|
||||
.Name = "PD-120",
|
||||
.ShortName = "PD120",
|
||||
.ScanPixels = 640,
|
||||
.NumLines = 496,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 121.6e-3,
|
||||
.tLine = 508.48e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_PD160] = { // N7CXI, 2000
|
||||
.Name = "PD-160",
|
||||
.ShortName = "PD160",
|
||||
.ImgWidth = 512,
|
||||
.NumLines = 400,
|
||||
.LineHeight = 1,
|
||||
.tScan = 195.584e-3,
|
||||
.tLine = 804.416e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_PD160] = { // N7CXI, 2000
|
||||
.Name = "PD-160",
|
||||
.ShortName = "PD160",
|
||||
.ScanPixels = 512,
|
||||
.NumLines = 400,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 195.584e-3,
|
||||
.tLine = 804.416e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_PD180] = { // N7CXI, 2000
|
||||
.Name = "PD-180",
|
||||
.ShortName = "PD180",
|
||||
.ImgWidth = 640,
|
||||
.NumLines = 496,
|
||||
.LineHeight = 1,
|
||||
.tScan = 183.04e-3,
|
||||
.tLine = 754.24e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_PD180] = { // N7CXI, 2000
|
||||
.Name = "PD-180",
|
||||
.ShortName = "PD180",
|
||||
.ScanPixels = 640,
|
||||
.NumLines = 496,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 183.04e-3,
|
||||
.tLine = 754.24e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_PD240] = { // N7CXI, 2000
|
||||
.Name = "PD-240",
|
||||
.ShortName = "PD240",
|
||||
.ImgWidth = 640,
|
||||
.NumLines = 496,
|
||||
.LineHeight = 1,
|
||||
.tScan = 244.48e-3,
|
||||
.tLine = 1000e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_PD240] = { // N7CXI, 2000
|
||||
.Name = "PD-240",
|
||||
.ShortName = "PD240",
|
||||
.ScanPixels = 640,
|
||||
.NumLines = 496,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 244.48e-3,
|
||||
.tLine = 1000e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_PD290] = { // N7CXI, 2000
|
||||
.Name = "PD-290",
|
||||
.ShortName = "PD290",
|
||||
.ImgWidth = 800,
|
||||
.NumLines = 616,
|
||||
.LineHeight = 1,
|
||||
.tScan = 228.8e-3,
|
||||
.tLine = 937.28e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
[MODE_PD290] = { // N7CXI, 2000
|
||||
.Name = "PD-290",
|
||||
.ShortName = "PD290",
|
||||
.ScanPixels = 800,
|
||||
.NumLines = 616,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 228.8e-3,
|
||||
.tLine = 937.28e-3,
|
||||
.tSync = 20e-3,
|
||||
.tPorch = 2.08e-3,
|
||||
.tSep = 0,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_440_YUVY,
|
||||
.ColorEnc = COLOR_YUV },
|
||||
|
||||
[MODE_P3] = { // N7CXI, 2000
|
||||
.Name = "Pasokon P3",
|
||||
.ShortName = "P3",
|
||||
.ImgWidth = 640,
|
||||
.NumLines = 496,
|
||||
.LineHeight = 1,
|
||||
.tScan = 133.333e-3,
|
||||
.tLine = 409.375e-3,
|
||||
.tSync = 5.208e-3,
|
||||
.tPorch = 1.042e-3,
|
||||
.tSep = 1.042e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB },
|
||||
[MODE_P3] = { // N7CXI, 2000
|
||||
.Name = "Pasokon P3",
|
||||
.ShortName = "P3",
|
||||
.ScanPixels = 640,
|
||||
.NumLines = 496,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 133.333e-3,
|
||||
.tLine = 409.375e-3,
|
||||
.tSync = 5.208e-3,
|
||||
.tPorch = 1.042e-3,
|
||||
.tSep = 1.042e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB },
|
||||
|
||||
[MODE_P5] = { // N7CXI, 2000
|
||||
.Name = "Pasokon P5",
|
||||
.ShortName = "P5",
|
||||
.ImgWidth = 640,
|
||||
.NumLines = 496,
|
||||
.LineHeight = 1,
|
||||
.tScan = 200e-3,
|
||||
.tLine = 614.065e-3,
|
||||
.tSync = 7.813e-3,
|
||||
.tPorch = 1.563e-3,
|
||||
.tSep = 1.563e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB },
|
||||
[MODE_P5] = { // N7CXI, 2000
|
||||
.Name = "Pasokon P5",
|
||||
.ShortName = "P5",
|
||||
.ScanPixels = 640,
|
||||
.NumLines = 496,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 200e-3,
|
||||
.tLine = 614.065e-3,
|
||||
.tSync = 7.813e-3,
|
||||
.tPorch = 1.563e-3,
|
||||
.tSep = 1.563e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB },
|
||||
|
||||
[MODE_P7] = { // N7CXI, 2000
|
||||
.Name = "Pasokon P7",
|
||||
.ShortName = "P7",
|
||||
.ImgWidth = 640,
|
||||
.NumLines = 496,
|
||||
.LineHeight = 1,
|
||||
.tScan = 266.666e-3,
|
||||
.tLine = 818.747e-3,
|
||||
.tSync = 10.417e-3,
|
||||
.tPorch = 2.083e-3,
|
||||
.tSep = 2.083e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSamp = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB }
|
||||
[MODE_P7] = { // N7CXI, 2000
|
||||
.Name = "Pasokon P7",
|
||||
.ShortName = "P7",
|
||||
.ScanPixels = 640,
|
||||
.NumLines = 496,
|
||||
.HeaderLines = 16,
|
||||
.tScan = 266.666e-3,
|
||||
.tLine = 818.747e-3,
|
||||
.tSync = 10.417e-3,
|
||||
.tPorch = 2.083e-3,
|
||||
.tSep = 2.083e-3,
|
||||
.SyncOrder = SYNC_SIMPLE,
|
||||
.SubSampling = SUBSAMP_444,
|
||||
.ColorEnc = COLOR_RGB }
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Mapping of 7-bit VIS codes to modes
|
||||
*
|
||||
* Reference: Dave Jones KB4YZ (1998): "List of SSTV Modes with VIS Codes".
|
||||
* http://www.tima.com/~djones/vis.txt
|
||||
* KB4YZ, 1998
|
||||
*
|
||||
*/
|
||||
|
||||
map<int, SSTVMode> vis2mode = {
|
||||
std::map<int, SSTVMode> vis2mode = {
|
||||
{0x02,MODE_R8BW}, {0x04,MODE_R24}, {0x06,MODE_R12BW}, {0x08,MODE_R36},
|
||||
{0x0A,MODE_R24BW},{0x0C,MODE_R72}, {0x20,MODE_M4}, {0x24,MODE_M3},
|
||||
{0x28,MODE_M2}, {0x2C,MODE_M1}, {0x37,MODE_W2180}, {0x38,MODE_S2},
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
string confpath(string(getenv("HOME")) + "/.config/slowrx/slowrx.ini");
|
||||
std::string confpath(std::string(getenv("HOME")) + "/.config/slowrx/slowrx.ini");
|
||||
config.load_from_file(confpath);
|
||||
|
||||
DSPworker dsp;
|
||||
|
||||
GetVideo(GetVIS(&dsp), 44100, &dsp, false);
|
||||
GetVideo(GetVIS(&dsp), &dsp);
|
||||
|
||||
//SlowGUI gui = SlowGUI();
|
||||
return 0;
|
||||
|
|
275
src/video.cc
275
src/video.cc
|
@ -5,16 +5,17 @@ typedef struct {
|
|||
int Y;
|
||||
int Channel;
|
||||
double Time;
|
||||
} _Pixel;
|
||||
} PixelSample;
|
||||
|
||||
bool sortPixelTime(_Pixel a, _Pixel b) { return a.Time < b.Time; }
|
||||
bool sortPixelSamples(PixelSample a, PixelSample b) { return a.Time < b.Time; }
|
||||
|
||||
// Map to RGB & store in pixbuf
|
||||
void toPixbufRGB(guint8 Image[800][800][3], Glib::RefPtr<Gdk::Pixbuf> pixbuf, SSTVMode Mode) {
|
||||
guint8 *p;
|
||||
guint8 *pixels;
|
||||
pixels = pixbuf->get_pixels();
|
||||
int rowstride = pixbuf->get_rowstride();
|
||||
for (int x = 0; x < ModeSpec[Mode].ImgWidth; x++) {
|
||||
for (int x = 0; x < ModeSpec[Mode].ScanPixels; x++) {
|
||||
for (int y = 0; y < ModeSpec[Mode].NumLines; y++) {
|
||||
p = pixels + y * rowstride + x * 3;
|
||||
|
||||
|
@ -49,36 +50,21 @@ void toPixbufRGB(guint8 Image[800][800][3], Glib::RefPtr<Gdk::Pixbuf> pixbuf, SS
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Demodulate the video signal & store all kinds of stuff for later stages
|
||||
* Mode: M1, M2, S1, S2, R72, R36...
|
||||
* Rate: exact sampling rate used
|
||||
* Skip: number of PCM samples to skip at the beginning (for sync phase adjustment)
|
||||
* Redraw: false = Apply windowing and FFT to the signal, true = Redraw from cached FFT data
|
||||
* returns: true when finished, false when aborted
|
||||
*/
|
||||
bool GetVideo(SSTVMode Mode, double Rate, DSPworker* dsp, bool Redraw) {
|
||||
|
||||
printf("receive %s\n",ModeSpec[Mode].Name.c_str());
|
||||
|
||||
vector<_Pixel> PixelGrid;
|
||||
|
||||
// Time instants for all pixels
|
||||
std::vector<PixelSample> getPixelSamplingPoints(SSTVMode Mode) {
|
||||
_ModeSpec s = ModeSpec[Mode];
|
||||
|
||||
guint8 Image[800][800][3];
|
||||
|
||||
// Time instants for all pixels
|
||||
std::vector<PixelSample> PixelGrid;
|
||||
for (int y=0; y<s.NumLines; y++) {
|
||||
for (int x=0; x<s.ImgWidth; x++) {
|
||||
for (int x=0; x<s.ScanPixels; x++) {
|
||||
for (int Chan=0; Chan < (s.ColorEnc == COLOR_MONO ? 1 : 3); Chan++) {
|
||||
_Pixel px;
|
||||
PixelSample px;
|
||||
px.X = x;
|
||||
px.Y = y;
|
||||
px.Channel = Chan;
|
||||
switch(s.SubSamp) {
|
||||
switch(s.SubSampling) {
|
||||
|
||||
case (SUBSAMP_444):
|
||||
px.Time = y*(s.tLine) + (x+0.5)/s.ImgWidth * s.tScan;
|
||||
px.Time = y*(s.tLine) + (x+0.5)/s.ScanPixels * s.tScan;
|
||||
|
||||
switch (s.SyncOrder) {
|
||||
|
||||
|
@ -98,15 +84,18 @@ bool GetVideo(SSTVMode Mode, double Rate, DSPworker* dsp, bool Redraw) {
|
|||
switch (Chan) {
|
||||
|
||||
case (0):
|
||||
px.Time = y*(s.tLine) + s.tSync + s.tPorch + (x+.5)/s.ImgWidth * s.tScan;
|
||||
px.Time = y*(s.tLine) + s.tSync + s.tPorch +
|
||||
(x+.5)/s.ScanPixels * s.tScan;
|
||||
break;
|
||||
|
||||
case (1):
|
||||
px.Time = (y-(y % 2)) * (s.tLine) + s.tSync + s.tPorch + s.tScan + s.tSep + 0.5*(x+0.5)/s.ImgWidth * s.tScan;
|
||||
px.Time = (y-(y % 2)) * (s.tLine) + s.tSync + s.tPorch +
|
||||
s.tScan + s.tSep + 0.5*(x+0.5)/s.ScanPixels * s.tScan;
|
||||
break;
|
||||
|
||||
case (2):
|
||||
px.Time = (y+1-(y % 2)) * (s.tLine) + s.tSync + s.tPorch + s.tScan + s.tSep + 0.5*(x+0.5)/s.ImgWidth * s.tScan;
|
||||
px.Time = (y+1-(y % 2)) * (s.tLine) + s.tSync + s.tPorch +
|
||||
s.tScan + s.tSep + 0.5*(x+0.5)/s.ScanPixels * s.tScan;
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -116,17 +105,19 @@ bool GetVideo(SSTVMode Mode, double Rate, DSPworker* dsp, bool Redraw) {
|
|||
switch (Chan) {
|
||||
|
||||
case (0):
|
||||
px.Time = y*(s.tLine) + s.tSync + s.tPorch + (x+.5)/s.ImgWidth * s.tScan;
|
||||
px.Time = y*(s.tLine) + s.tSync + s.tPorch +
|
||||
(x+.5)/s.ScanPixels * s.tScan;
|
||||
break;
|
||||
|
||||
case (1):
|
||||
px.Time = y*(s.tLine) + s.tSync + s.tPorch + s.tScan
|
||||
+ s.tSep + (x+.5)/s.ImgWidth * s.tScan/2;
|
||||
+ s.tSep + (x+.5)/s.ScanPixels * s.tScan/2;
|
||||
break;
|
||||
|
||||
case (2):
|
||||
px.Time = y*(s.tLine) + s.tSync + s.tPorch + s.tScan
|
||||
+ s.tSep + s.tScan/2 + s.tSep + (x+.5)/s.ImgWidth * s.tScan/2;
|
||||
+ s.tSep + s.tScan/2 + s.tSep + (x+.5)/s.ScanPixels *
|
||||
s.tScan/2;
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -137,17 +128,18 @@ bool GetVideo(SSTVMode Mode, double Rate, DSPworker* dsp, bool Redraw) {
|
|||
|
||||
case (0):
|
||||
px.Time = (y/2)*(s.tLine) + s.tSync + s.tPorch +
|
||||
((y%2 == 1 ? s.ImgWidth*3 : 0)+x+.5)/s.ImgWidth * s.tScan;
|
||||
((y%2 == 1 ? s.ScanPixels*3 : 0)+x+.5)/s.ScanPixels *
|
||||
s.tScan;
|
||||
break;
|
||||
|
||||
case (1):
|
||||
px.Time = (y/2)*(s.tLine) + s.tSync + s.tPorch +
|
||||
(s.ImgWidth+x+.5)/s.ImgWidth * s.tScan;
|
||||
(s.ScanPixels+x+.5)/s.ScanPixels * s.tScan;
|
||||
break;
|
||||
|
||||
case (2):
|
||||
px.Time = (y/2)*(s.tLine) + s.tSync + s.tPorch +
|
||||
(s.ImgWidth*2+x+.5)/s.ImgWidth * s.tScan;
|
||||
(s.ScanPixels*2+x+.5)/s.ScanPixels * s.tScan;
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -158,12 +150,29 @@ bool GetVideo(SSTVMode Mode, double Rate, DSPworker* dsp, bool Redraw) {
|
|||
}
|
||||
}
|
||||
|
||||
std::sort(PixelGrid.begin(), PixelGrid.end(), sortPixelTime);
|
||||
std::sort(PixelGrid.begin(), PixelGrid.end(), sortPixelSamples);
|
||||
|
||||
Glib::RefPtr<Gtk::Application> app =
|
||||
Gtk::Application::create("com.windytan.slowrx");
|
||||
return PixelGrid;
|
||||
}
|
||||
|
||||
/* Demodulate the video signal & store all kinds of stuff for later stages
|
||||
* Mode: M1, M2, S1, S2, R72, R36...
|
||||
* Rate: exact sampling rate used
|
||||
* Skip: number of PCM samples to skip at the beginning (for sync phase adjustment)
|
||||
* Redraw: false = Apply windowing and FFT to the signal, true = Redraw from cached FFT data
|
||||
* returns: true when finished, false when aborted
|
||||
*/
|
||||
bool GetVideo(SSTVMode Mode, DSPworker* dsp) {
|
||||
|
||||
printf("receive %s\n",ModeSpec[Mode].Name.c_str());
|
||||
|
||||
_ModeSpec s = ModeSpec[Mode];
|
||||
|
||||
guint8 Image[800][800][3];
|
||||
|
||||
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create("com.windytan.slowrx");
|
||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf_rx;
|
||||
pixbuf_rx = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, 8, s.ImgWidth, s.NumLines);
|
||||
pixbuf_rx = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, 8, s.ScanPixels, s.NumLines);
|
||||
pixbuf_rx->fill(0x000000ff);
|
||||
|
||||
// Initialize pixbuffer
|
||||
|
@ -173,11 +182,7 @@ bool GetVideo(SSTVMode Mode, double Rate, DSPworker* dsp, bool Redraw) {
|
|||
gdk_pixbuf_fill(pixbuf_rx, 0);
|
||||
}*/
|
||||
|
||||
/*int rowstride = gdk_pixbuf_get_rowstride (pixbuf_rx);
|
||||
guchar *pixels, *p;
|
||||
pixels = gdk_pixbuf_get_pixels(pixbuf_rx);
|
||||
|
||||
g_object_unref(pixbuf_disp);
|
||||
/*g_object_unref(pixbuf_disp);
|
||||
pixbuf_disp = gdk_pixbuf_scale_simple(pixbuf_rx, 500,
|
||||
500.0/ModeSpec[Mode].ImgWidth * ModeSpec[Mode].NumLines * ModeSpec[Mode].LineHeight, GDK_INTERP_BILINEAR);
|
||||
*/
|
||||
|
@ -189,127 +194,127 @@ bool GetVideo(SSTVMode Mode, double Rate, DSPworker* dsp, bool Redraw) {
|
|||
SyncSampleNum = 0;*/
|
||||
|
||||
// Loop through signal
|
||||
std::vector<PixelSample> PixelGrid = getPixelSamplingPoints(Mode);
|
||||
double t = 0;
|
||||
for (int PixelIdx = 0; PixelIdx < PixelGrid.size(); PixelIdx++) {
|
||||
|
||||
double Lum = 0;
|
||||
|
||||
if (!Redraw) {
|
||||
while (t < PixelGrid[PixelIdx].Time && dsp->is_still_listening()) {
|
||||
t += dsp->forward();
|
||||
}
|
||||
|
||||
while (t < PixelGrid[PixelIdx].Time && dsp->is_still_listening()) {
|
||||
t += dsp->forward();
|
||||
}
|
||||
/*** Store the sync band for later adjustments ***/
|
||||
|
||||
/*** Store the sync band for later adjustments ***/
|
||||
/*if (SampleNum == NextSyncTime) {
|
||||
|
||||
/*if (SampleNum == NextSyncTime) {
|
||||
|
||||
Praw = Psync = 0;
|
||||
Praw = Psync = 0;
|
||||
|
||||
memset(fft.in, 0, sizeof(double)*FFTLen);
|
||||
|
||||
// Hann window
|
||||
for (i = 0; i < 64; i++) fft.in[i] = pcm.Buffer[pcm.WindowPtr+i-32] / 32768.0 * Hann[1][i];
|
||||
memset(fft.in, 0, sizeof(double)*FFTLen);
|
||||
|
||||
// Hann window
|
||||
for (i = 0; i < 64; i++) fft.in[i] = pcm.Buffer[pcm.WindowPtr+i-32] / 32768.0 * Hann[1][i];
|
||||
|
||||
fftw_execute(fft.Plan1024);
|
||||
fftw_execute(fft.Plan1024);
|
||||
|
||||
for (i=GetBin(1500+CurrentPic.HedrShift,FFTLen); i<=GetBin(2300+CurrentPic.HedrShift, FFTLen); i++)
|
||||
Praw += power(fft.out[i]);
|
||||
for (i=GetBin(1500+CurrentPic.HedrShift,FFTLen); i<=GetBin(2300+CurrentPic.HedrShift, FFTLen); i++)
|
||||
Praw += power(fft.out[i]);
|
||||
|
||||
for (i=SyncTargetBin-1; i<=SyncTargetBin+1; i++)
|
||||
Psync += power(fft.out[i]) * (1- .5*abs(SyncTargetBin-i));
|
||||
for (i=SyncTargetBin-1; i<=SyncTargetBin+1; i++)
|
||||
Psync += power(fft.out[i]) * (1- .5*abs(SyncTargetBin-i));
|
||||
|
||||
Praw /= (GetBin(2300+CurrentPic.HedrShift, FFTLen) - GetBin(1500+CurrentPic.HedrShift, FFTLen));
|
||||
Psync /= 2.0;
|
||||
Praw /= (GetBin(2300+CurrentPic.HedrShift, FFTLen) - GetBin(1500+CurrentPic.HedrShift, FFTLen));
|
||||
Psync /= 2.0;
|
||||
|
||||
// If there is more than twice the amount of power per Hz in the
|
||||
// sync band than in the video band, we have a sync signal here
|
||||
HasSync[SyncSampleNum] = (Psync > 2*Praw);
|
||||
// If there is more than twice the amount of power per Hz in the
|
||||
// sync band than in the video band, we have a sync signal here
|
||||
HasSync[SyncSampleNum] = (Psync > 2*Praw);
|
||||
|
||||
NextSyncTime += 13;
|
||||
SyncSampleNum ++;
|
||||
NextSyncTime += 13;
|
||||
SyncSampleNum ++;
|
||||
|
||||
}*/
|
||||
}*/
|
||||
|
||||
/*** Estimate SNR ***/
|
||||
/*** Estimate SNR ***/
|
||||
|
||||
/*if (SampleNum == NextSNRtime) {
|
||||
|
||||
memset(fft.in, 0, sizeof(double)*FFTLen);
|
||||
double SNR;
|
||||
|
||||
// Apply Hann window
|
||||
for (i = 0; i < FFTLen; i++) fft.in[i] = pcm.Buffer[pcm.WindowPtr + i - FFTLen/2] / 32768.0 * Hann[6][i];
|
||||
if (PixelIdx == 0 || PixelGrid[PixelIdx].X == s.ScanPixels/2) {
|
||||
std::vector<double> bands = dsp->getBandPowerPerHz({{400,800}, {1500,2300}, {2700, 3400}});
|
||||
double Pvideo_plus_noise = bands[1];
|
||||
double Pnoise_only = (bands[0] + bands[2]) / 2;
|
||||
double Psignal = Pvideo_plus_noise - Pnoise_only;
|
||||
|
||||
fftw_execute(fft.Plan1024);
|
||||
SNR = ((Psignal / Pnoise_only < .01) ? -20 : 10 * log10(Psignal / Pnoise_only));
|
||||
|
||||
// Calculate video-plus-noise power (1500-2300 Hz)
|
||||
printf("SNR = %f\n",SNR);
|
||||
|
||||
Pvideo_plus_noise = 0;
|
||||
for (n = GetBin(1500+CurrentPic.HedrShift, FFTLen); n <= GetBin(2300+CurrentPic.HedrShift, FFTLen); n++)
|
||||
Pvideo_plus_noise += power(fft.out[n]);
|
||||
}
|
||||
|
||||
// Calculate noise-only power (400-800 Hz + 2700-3400 Hz)
|
||||
|
||||
Pnoise_only = 0;
|
||||
for (n = GetBin(400+CurrentPic.HedrShift, FFTLen); n <= GetBin(800+CurrentPic.HedrShift, FFTLen); n++)
|
||||
Pnoise_only += power(fft.out[n]);
|
||||
|
||||
for (n = GetBin(2700+CurrentPic.HedrShift, FFTLen); n <= GetBin(3400+CurrentPic.HedrShift, FFTLen); n++)
|
||||
Pnoise_only += power(fft.out[n]);
|
||||
|
||||
// Bandwidths
|
||||
VideoPlusNoiseBins = GetBin(2300, FFTLen) - GetBin(1500, FFTLen) + 1;
|
||||
|
||||
NoiseOnlyBins = GetBin(800, FFTLen) - GetBin(400, FFTLen) + 1 +
|
||||
GetBin(3400, FFTLen) - GetBin(2700, FFTLen) + 1;
|
||||
|
||||
ReceiverBins = GetBin(3400, FFTLen) - GetBin(400, FFTLen);
|
||||
|
||||
// Eq 15
|
||||
Pnoise = Pnoise_only * (1.0 * ReceiverBins / NoiseOnlyBins);
|
||||
Psignal = Pvideo_plus_noise - Pnoise_only * (1.0 * VideoPlusNoiseBins / NoiseOnlyBins);
|
||||
|
||||
// Lower bound to -20 dB
|
||||
SNR = ((Psignal / Pnoise < .01) ? -20 : 10 * log10(Psignal / Pnoise));
|
||||
|
||||
NextSNRtime += 256;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/*** FM demodulation ***/
|
||||
|
||||
//PrevFreq = Freq;
|
||||
|
||||
// Adapt window size to SNR
|
||||
WindowType WinType;
|
||||
double SNR = 10;
|
||||
bool Adaptive = true;
|
||||
|
||||
if (!Adaptive) WinType = WINDOW_CHEB47;
|
||||
/*if (SampleNum == NextSNRtime) {
|
||||
|
||||
else if (SNR >= 20) WinType = WINDOW_CHEB47;
|
||||
else if (SNR >= 10) WinType = WINDOW_HANN63;
|
||||
else if (SNR >= 9) WinType = WINDOW_HANN95;
|
||||
else if (SNR >= 3) WinType = WINDOW_HANN127;
|
||||
else if (SNR >= -5) WinType = WINDOW_HANN255;
|
||||
else if (SNR >= -10) WinType = WINDOW_HANN511;
|
||||
else WinType = WINDOW_HANN1023;
|
||||
memset(fft.in, 0, sizeof(double)*FFTLen);
|
||||
|
||||
// Minimum winlength can be doubled for Scottie DX
|
||||
//if (Mode == MODE_SDX && WinType < WINDOW_HANN511) WinType++;
|
||||
// Apply Hann window
|
||||
for (i = 0; i < FFTLen; i++) fft.in[i] = pcm.Buffer[pcm.WindowPtr + i - FFTLen/2] / 32768.0 * Hann[6][i];
|
||||
|
||||
double Freq = dsp->get_peak_freq(1500, 2300, WinType);
|
||||
fftw_execute(fft.Plan1024);
|
||||
|
||||
// Linear interpolation of (chronologically) intermediate frequencies, for redrawing
|
||||
//InterpFreq = PrevFreq + (Freq-PrevFreq) * ... // TODO!
|
||||
// Calculate video-plus-noise power (1500-2300 Hz)
|
||||
|
||||
// Calculate luminency & store for later use
|
||||
Lum = clip((Freq - (1500)) / 3.1372549);
|
||||
measured.push_back({t, Lum});
|
||||
//StoredLum[SampleNum] = clip((Freq - (1500 + CurrentPic.HedrShift)) / 3.1372549);
|
||||
Pvideo_plus_noise = 0;
|
||||
for (n = GetBin(1500+CurrentPic.HedrShift, FFTLen); n <= GetBin(2300+CurrentPic.HedrShift, FFTLen); n++)
|
||||
Pvideo_plus_noise += power(fft.out[n]);
|
||||
|
||||
} /* endif (!Redraw) */
|
||||
// Calculate noise-only power (400-800 Hz + 2700-3400 Hz)
|
||||
|
||||
Pnoise_only = 0;
|
||||
for (n = GetBin(400+CurrentPic.HedrShift, FFTLen); n <= GetBin(800+CurrentPic.HedrShift, FFTLen); n++)
|
||||
Pnoise_only += power(fft.out[n]);
|
||||
|
||||
for (n = GetBin(2700+CurrentPic.HedrShift, FFTLen); n <= GetBin(3400+CurrentPic.HedrShift, FFTLen); n++)
|
||||
Pnoise_only += power(fft.out[n]);
|
||||
|
||||
// Bandwidths
|
||||
VideoPlusNoiseBins = GetBin(2300, FFTLen) - GetBin(1500, FFTLen) + 1;
|
||||
|
||||
NoiseOnlyBins = GetBin(800, FFTLen) - GetBin(400, FFTLen) + 1 +
|
||||
GetBin(3400, FFTLen) - GetBin(2700, FFTLen) + 1;
|
||||
|
||||
ReceiverBins = GetBin(3400, FFTLen) - GetBin(400, FFTLen);
|
||||
|
||||
// Eq 15
|
||||
Pnoise = Pnoise_only * (1.0 * ReceiverBins / NoiseOnlyBins);
|
||||
Psignal = Pvideo_plus_noise - Pnoise_only * (1.0 * VideoPlusNoiseBins / NoiseOnlyBins);
|
||||
|
||||
// Lower bound to -20 dB
|
||||
SNR = ((Psignal / Pnoise < .01) ? -20 : 10 * log10(Psignal / Pnoise));
|
||||
|
||||
NextSNRtime += 256;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/*** FM demodulation ***/
|
||||
|
||||
//PrevFreq = Freq;
|
||||
|
||||
// Adapt window size to SNR
|
||||
bool Adaptive = true;
|
||||
WindowType WinType;
|
||||
|
||||
if (Adaptive) WinType = dsp->getBestWindowFor(Mode, SNR);
|
||||
else WinType = dsp->getBestWindowFor(Mode);
|
||||
|
||||
double Freq = dsp->getPeakFreq(1500, 2300, WinType);
|
||||
|
||||
// Linear interpolation of (chronologically) intermediate frequencies, for redrawing
|
||||
//InterpFreq = PrevFreq + (Freq-PrevFreq) * ... // TODO!
|
||||
|
||||
// Calculate luminency & store for later use
|
||||
Lum = clip((Freq - (1500)) / 3.1372549);
|
||||
//measured.push_back({t, Lum});
|
||||
//StoredLum[SampleNum] = clip((Freq - (1500 + CurrentPic.HedrShift)) / 3.1372549);
|
||||
|
||||
int x = PixelGrid[PixelIdx].X;
|
||||
int y = PixelGrid[PixelIdx].Y;
|
||||
|
|
|
@ -30,7 +30,7 @@ SSTVMode GetVIS (DSPworker *dsp) {
|
|||
|
||||
//if (Abort || ManualResync) return(0);
|
||||
|
||||
HedrBuf[HedrPtr] = dsp->get_peak_freq(500, 3300, WINDOW_HANN1023);
|
||||
HedrBuf[HedrPtr] = dsp->getPeakFreq(500, 3300, WINDOW_HANN1023);
|
||||
dsp->forward_ms(10);
|
||||
|
||||
// Header buffer holds 45 * 10 msec = 450 msec
|
||||
|
@ -123,13 +123,9 @@ SSTVMode GetVIS (DSPworker *dsp) {
|
|||
ptr = 0;
|
||||
}*/
|
||||
|
||||
//pcm.WindowPtr += 441;
|
||||
}
|
||||
|
||||
// Skip the rest of the stop bit
|
||||
//readPcm(20e-3 * 44100);
|
||||
//pcm.WindowPtr += 20e-3 * 44100;
|
||||
|
||||
dsp->forward_ms(12); // TODO hack
|
||||
|
||||
if (vis2mode.find(vis) != vis2mode.end()) {
|
||||
|
|
Ładowanie…
Reference in New Issue