reworked sync detection, now based on convolution etc

pull/5/head
Oona 2013-01-14 23:21:15 +02:00
rodzic 83c10ffd0d
commit 2fccddba62
8 zmienionych plików z 109 dodań i 56 usunięć

Wyświetl plik

@ -58,6 +58,11 @@ double deg2rad (double Deg) {
return (Deg / 180) * M_PI;
}
// Convert radians -> degrees
double rad2deg (double rad) {
return (180 / M_PI) * rad;
}
/*** Gtk+ event handlers ***/
@ -126,3 +131,28 @@ void evt_clearPix() {
gtk_label_set_markup (GTK_LABEL(gui.label_utc), "");
gtk_label_set_markup (GTK_LABEL(gui.label_lastmode), "");
}
// Manual slant adjust
void evt_clickimg(GtkWidget *widget, GdkEventButton* event, GdkWindowEdge edge) {
static double prevx=0,prevy=0;
static bool secondpress=false;
double dx,dy,a;
if (event->type == GDK_BUTTON_PRESS && event->button == 1 && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(gui.tog_setedge))) {
if (secondpress) {
printf(":) %.1f,%.1f -> %.1f,%.1f\n",prevx,prevy,event->x,event->y);
dx = event->x - prevx;
dy = event->y - prevy;
a = rad2deg(M_PI/2 - asin(dx/sqrt(pow(dx,2) + pow(dy,2))));
if (event->y < prevy) a = fabs(a-180);
printf("%.3f\n",a);
secondpress=false;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(gui.tog_setedge),false);
} else {
prevx = event->x;
prevy = event->y;
secondpress = true;
}
}
}

Wyświetl plik

@ -4,6 +4,7 @@
#define MINSLANT 30
#define MAXSLANT 150
#define BUFLEN 4096
#define SYNCPIXLEN 1.5e-3
extern bool Abort;
extern bool Adaptive;
@ -29,7 +30,9 @@ struct _GuiObjs {
GtkWidget *combo_card;
GtkWidget *combo_mode;
GtkWidget *entry_picdir;
GtkWidget *eventbox_img;
GtkWidget *frame_manual;
GtkWidget *frame_slant;
GtkWidget *grid_vu;
GtkWidget *iconview;
GtkWidget *image_devstatus;
@ -118,6 +121,7 @@ void evt_AbortRx ();
void evt_changeDevices ();
void evt_chooseDir ();
void evt_clearPix ();
void evt_clickimg ();
void evt_deletewindow ();
void evt_GetAdaptive ();
void evt_ManualStart ();

8
gui.c
Wyświetl plik

@ -23,7 +23,9 @@ void createGUI() {
gui.combo_card = GTK_WIDGET(gtk_builder_get_object(builder,"combo_card"));
gui.combo_mode = GTK_WIDGET(gtk_builder_get_object(builder,"combo_mode"));
gui.entry_picdir = GTK_WIDGET(gtk_builder_get_object(builder,"entry_picdir"));
gui.eventbox_img = GTK_WIDGET(gtk_builder_get_object(builder,"eventbox_img"));
gui.frame_manual = GTK_WIDGET(gtk_builder_get_object(builder,"frame_manual"));
gui.frame_slant = GTK_WIDGET(gtk_builder_get_object(builder,"frame_slant"));
gui.grid_vu = GTK_WIDGET(gtk_builder_get_object(builder,"grid_vu"));
gui.iconview = GTK_WIDGET(gtk_builder_get_object(builder,"SavedIconView"));
gui.image_devstatus = GTK_WIDGET(gtk_builder_get_object(builder,"image_devstatus"));
@ -51,6 +53,7 @@ void createGUI() {
g_signal_connect (gui.button_clear, "clicked", G_CALLBACK(evt_clearPix), NULL);
g_signal_connect (gui.button_start, "clicked", G_CALLBACK(evt_ManualStart), NULL);
g_signal_connect (gui.combo_card, "changed", G_CALLBACK(evt_changeDevices), NULL);
g_signal_connect (gui.eventbox_img, "button-press-event",G_CALLBACK(evt_clickimg), NULL);
g_signal_connect (gui.menuitem_quit, "activate", G_CALLBACK(evt_deletewindow), NULL);
g_signal_connect (gui.menuitem_about,"activate", G_CALLBACK(evt_show_about), NULL);
g_signal_connect_swapped(gui.tog_adapt, "toggled", G_CALLBACK(evt_GetAdaptive), NULL);
@ -87,7 +90,6 @@ void setVU (short int PcmValue, double SNRdB) {
int PWRdB = (int)round(10 * log10(pow(PcmValue/32767.0,2)));
guchar *pixelsPWR, *pixelsSNR, *pPWR, *pSNR;
unsigned int rowstridePWR,rowstrideSNR;
int SNRdBthresh[10] = {30, 15, 10, 5, 3, 0, -3, -5, -10, -15};
rowstridePWR = gdk_pixbuf_get_rowstride (pixbuf_PWR);
pixelsPWR = gdk_pixbuf_get_pixels (pixbuf_PWR);
@ -101,9 +103,7 @@ void setVU (short int PcmValue, double SNRdB) {
pPWR = pixelsPWR + y * rowstridePWR + (99-x) * 3;
pSNR = pixelsSNR + y * rowstrideSNR + (99-x) * 3;
if (y > 1 && y < 18 &&
x % 10 > 1 && x % 10 < 9 &&
x % 2 == 0 && y % 2 == 0) {
if (y > 1 && y < 18 && x % 2 == 0) {
if (PWRdB >= -0.0075*pow(x,2)-3) {
pPWR[0] = 0x89;

Wyświetl plik

@ -108,7 +108,7 @@ void *Listen() {
}
// Allocate space for sync signal
HasSync = calloc((int)(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight / 1.5e-3 +1), sizeof(bool));
HasSync = calloc((int)(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight / SYNCPIXLEN +1), sizeof(bool));
if (HasSync == NULL) {
perror("Listen: Unable to allocate memory for sync signal");
exit(EXIT_FAILURE);
@ -119,9 +119,11 @@ void *Listen() {
gdk_threads_enter ();
gtk_label_set_text (GTK_LABEL(gui.label_fskid), "");
gtk_widget_set_sensitive (gui.frame_manual, false);
gtk_widget_set_sensitive (gui.frame_slant, false);
gtk_widget_set_sensitive (gui.combo_card, false);
gtk_widget_set_sensitive (gui.button_abort, true);
gtk_widget_set_sensitive (gui.button_clear, false);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(gui.tog_setedge), false);
gtk_statusbar_push (GTK_STATUSBAR(gui.statusbar), 0, "Receiving video..." );
gtk_label_set_markup (GTK_LABEL(gui.label_lastmode), ModeSpec[Mode].Name);
gtk_label_set_markup (GTK_LABEL(gui.label_utc), rctime);
@ -132,8 +134,6 @@ void *Listen() {
gdk_threads_enter ();
gtk_widget_set_sensitive (gui.button_abort, false);
gtk_widget_set_sensitive (gui.frame_manual, true);
gtk_widget_set_sensitive (gui.combo_card, true);
gdk_threads_leave ();
id[0] = '\0';
@ -214,6 +214,12 @@ void *Listen() {
free(StoredLum);
StoredLum = NULL;
gdk_threads_enter ();
gtk_widget_set_sensitive (gui.frame_slant, true);
gtk_widget_set_sensitive (gui.frame_manual, true);
gtk_widget_set_sensitive (gui.combo_card, true);
gdk_threads_leave ();
}
}

Wyświetl plik

@ -8,6 +8,14 @@
<property name="step_increment">10</property>
<property name="page_increment">100</property>
</object>
<object class="GtkListStore" id="savedstore">
<columns>
<!-- column-name GdkPixbuf1 -->
<column type="GdkPixbuf"/>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkWindow" id="window_main">
<property name="can_focus">False</property>
<property name="title" translatable="yes">slowrx</property>
@ -145,12 +153,20 @@
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkImage" id="image_rx">
<property name="width_request">500</property>
<property name="height_request">375</property>
<object class="GtkEventBox" id="eventbox_img">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
<property name="events">GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK</property>
<property name="visible_window">False</property>
<child>
<object class="GtkImage" id="image_rx">
<property name="width_request">500</property>
<property name="height_request">375</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -478,7 +494,7 @@
</child>
<child>
<object class="GtkButton" id="button_clear">
<property name="label" translatable="yes">Clear</property>
<property name="label" translatable="yes">Clear image</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
@ -530,7 +546,6 @@
<child>
<object class="GtkFrame" id="frame_slant">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
@ -1102,12 +1117,4 @@
</object>
</child>
</object>
<object class="GtkListStore" id="savedstore">
<columns>
<!-- column-name GdkPixbuf1 -->
<column type="GdkPixbuf"/>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
</object>
</interface>

51
sync.c
Wyświetl plik

@ -19,25 +19,26 @@
double FindSync (guchar Mode, double Rate, int *Skip) {
int LineWidth = ModeSpec[Mode].LineLen / ModeSpec[Mode].SyncLen * 4;
int x,y,xmid,x0;
int x,y;
int q, d, qMost, dMost, s;
gushort xAcc[700] = {0}, xmax;
gushort xAcc[700] = {0};
gushort lines[600][(MAXSLANT-MINSLANT)*2];
gushort cy, cx, Retries = 0;
bool SyncImg[700][630] = {{false}};
double t=0, slantAngle;
double ConvoFilter[8] = { 1,1,1,1,-1,-1,-1,-1 };
double convd, maxconvd=0;
int xmax=0;
// Repeat until slant < 0.5° or until we give up
while (true) {
// Draw the 2D sync signal at current rate
for (y=0; y<ModeSpec[Mode].ImgHeight; y++) {
for (x=0; x<LineWidth; x++) {
t = (y + 1.0*x/LineWidth) * ModeSpec[Mode].LineLen;
// Center sync pulse horizontally
if (y>0 || x>=LineWidth/2) SyncImg[x][y] = HasSync[ (int)( (t-ModeSpec[Mode].LineLen/2) / 1.5e-3 * Rate/44100) ];
SyncImg[x][y] = HasSync[ (int)( t / SYNCPIXLEN * Rate/44100) ];
}
}
@ -93,35 +94,37 @@ double FindSync (guchar Mode, double Rate, int *Skip) {
Retries ++;
}
// find abscissa at higher resolution
// accumulate a 1-dim array of the position of the sync pulse
memset(xAcc, 0, sizeof(xAcc[0]) * 700);
xmax = 0;
for (y=0; y<ModeSpec[Mode].ImgHeight; y++) {
for (x=0; x<700; x++) {
t = y * ModeSpec[Mode].LineLen + x/700.0 * ModeSpec[Mode].LineLen;
xAcc[x] += HasSync[ (int)(t / 1.5e-3 * Rate/44100) ];
if (xAcc[x] > xAcc[xmax]) xmax = x;
xAcc[x] += HasSync[ (int)(t / SYNCPIXLEN * Rate/44100) ];
}
}
// find center of sync pulse
x0 = -1;
xmid=-1;
for (x=0;x<700;x++) {
if (xAcc[x] >= xAcc[xmax]*0.5 && x0==-1) x0 = x;
if (x0 != -1 && xAcc[x] < xAcc[xmax]*0.5) {
xmid = (x + x0) / 2;
break;
// find falling edge of the sync pulse by 8-point convolution
for (x=0;x<700-8;x++) {
convd = 0;
for (int i=0;i<8;i++) convd += xAcc[x+i] * ConvoFilter[i];
if (convd > maxconvd) {
maxconvd = convd;
xmax = x;
}
}
// skip until the start of the sync pulse
s = (xmid / 700.0 * ModeSpec[Mode].LineLen - ModeSpec[Mode].SyncLen/2) * Rate;
// If pulse is on the right side, it just probably slipped out the left edge
if (xmax > 350) xmax -= 350;
// Scottie modes don't start lines with the sync pulse
if (Mode == S1 || Mode == S2 || Mode == SDX)
s -= 2 * (ModeSpec[Mode].SeparatorLen + ModeSpec[Mode].PixelLen*ModeSpec[Mode].ImgWidth) * Rate;
// Skip until the start of the line.
// (Scottie modes don't start lines with sync)
if (Mode == S1 || Mode == S2 || Mode == SDX) {
s = (xmax / 700.0 * ModeSpec[Mode].LineLen - ModeSpec[Mode].SyncLen -
2*ModeSpec[Mode].SeparatorLen - 2*ModeSpec[Mode].PixelLen*ModeSpec[Mode].ImgWidth)
* Rate;
} else {
s = (xmax / 700.0 * ModeSpec[Mode].LineLen - ModeSpec[Mode].SyncLen) * Rate;
}
*Skip = s;

17
video.c
Wyświetl plik

@ -99,7 +99,7 @@ bool GetVideo(guchar Mode, double Rate, int Skip, bool Redraw) {
Length = ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight * 44100;
SyncTargetBin = GetBin(1200+HedrShift, FFTLen);
LopassBin = GetBin(3000, FFTLen);
LopassBin = GetBin(5000, FFTLen);
Abort = false;
SyncSampleNum = 0;
@ -132,19 +132,22 @@ bool GetVideo(guchar Mode, double Rate, int Skip, bool Redraw) {
fftw_execute(Plan1024);
for (i=0;i<LopassBin;i++) {
Praw += pow(out[i], 2) + pow(out[FFTLen-i], 2);
if (i >= SyncTargetBin-1 && i <= SyncTargetBin+1) Psync += pow(out[i], 2) + pow(out[FFTLen-i], 2);
if (i >= GetBin(1500+HedrShift, FFTLen) && i <= GetBin(2300+HedrShift, FFTLen))
Praw += pow(out[i], 2) + pow(out[FFTLen-i], 2);
if (i >= SyncTargetBin-1 && i <= SyncTargetBin+1)
Psync += (pow(out[i], 2) + pow(out[FFTLen-i], 2)) * (1- .5*abs(SyncTargetBin-i));
}
Praw /= (FFTLen/2.0) * ( LopassBin/(FFTLen/2.0));
Psync /= 3.0;
Praw /= (GetBin(2300+HedrShift, FFTLen) - GetBin(1500+HedrShift, FFTLen));
Psync /= 2.0;
// If there is more than twice the amount of power per Hz in the
// sync band than in the rest of the band, we have a sync signal here
// sync band than in the video band, we have a sync signal here
if (Psync > 2*Praw) HasSync[SyncSampleNum] = true;
else HasSync[SyncSampleNum] = false;
NextSyncTime += 1.5e-3;
NextSyncTime += SYNCPIXLEN;
SyncSampleNum ++;
}

8
vis.c
Wyświetl plik

@ -171,10 +171,10 @@ guchar GetVIS () {
PcmPointer += 20e-3 * 44100;
// In case of Scottie, skip first sync pulse
if (VISmap[VIS] == S1 || VISmap[VIS] == S2 || VISmap[VIS] == SDX) {
readPcm(9e-3 * 44100);
PcmPointer += 9e-3 * 44100;
}
/*if (VISmap[VIS] == S1 || VISmap[VIS] == S2 || VISmap[VIS] == SDX) {
readPcm(ModeSpec[VISmap[VIS]].SyncLen * 44100);
PcmPointer += ModeSpec[VISmap[VIS]].SyncLen * 44100;
}*/
if (VISmap[VIS] != UNKNOWN) return VISmap[VIS];
else printf(" No VIS found\n");