sync improvements ... and a lot more

pull/1/merge
Oona 2011-07-26 01:41:04 +03:00
rodzic c3248524ba
commit f60ec21e6b
6 zmienionych plików z 86 dodań i 157 usunięć

Wyświetl plik

@ -3,7 +3,7 @@
#define MINSLANT 30
#define MAXSLANT 150
#define SYNCW 350
#define SYNCW 400
#define SNRSIZE 2048
extern int VISmap[128];

Wyświetl plik

@ -92,7 +92,7 @@ ModeSpecDef ModeSpec[] = {
.ShortName = "S1",
.SyncLen = 9e-3,
.PorchLen = 1.5e-3,
.SeparatorLen = 1.7e-3,
.SeparatorLen = 1.5e-3,
.PixelLen = 0.4320e-3,
.LineLen = 428.38e-3,
.ImgWidth = 320,

Wyświetl plik

@ -44,7 +44,7 @@ void *Cam() {
while (1) {
//PcmInStream = popen( "sox -q -t alsa hw:0 -t .raw -b 16 -c 1 -e signed-integer -r 44100 -L - 2>/dev/null", "r");
PcmInStream = popen( "sox -q iss.ogg -t raw -b 16 -c 1 -e signed-integer -r 44100 -L - 2>/dev/null", "r");
PcmInStream = popen( "sox -q iss2.ogg -t raw -b 16 -c 1 -e signed-integer -r 44100 -L - 2>/dev/null", "r");
if (PcmInStream == NULL) {
perror("Unable to open sox pipe");
@ -93,7 +93,7 @@ void *Cam() {
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Receiving video" );
gtk_label_set_markup(GTK_LABEL(infolabel), infostr);
gdk_threads_leave();
PcmPointer = 0;
PcmPointer = 2048;
Sample = 0;
Rate = 44100;
Skip = 0;
@ -116,15 +116,13 @@ void *Cam() {
free(PCM);
PCM = NULL;
if (Rate != 44100) {
// Final image
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Redrawing" );
gdk_threads_leave();
printf(" getvideo @ %.02f Hz, Skip %d, HedrShift %.0f Hz\n", Rate, Skip, HedrShift);
GetVideo(Mode, Rate, Skip, TRUE, TRUE);
}
// Final image
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Redrawing" );
gdk_threads_leave();
printf(" getvideo @ %.02f Hz, Skip %d, HedrShift %.0f Hz\n", Rate, Skip, HedrShift);
GetVideo(Mode, Rate, Skip, TRUE, TRUE);
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Saving" );
gdk_threads_leave();

106
sync.c
Wyświetl plik

@ -14,10 +14,14 @@
*/
double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
int LineWidth = ModeSpec[Mode].LineLen / ModeSpec[Mode].SyncLen * 4;
printf("LineWidth %d\n",LineWidth);
unsigned int i, s, TotPix;
double NextImgSample;
double t=0, slantAngle;
unsigned char SyncImg[SYNCW][630];
unsigned char SyncImg[450][630];
int x,y;
double Praw, Psync;
@ -27,8 +31,9 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
perror("FindSync: Unable to allocate memory for sync signal");
exit(EXIT_FAILURE);
}
memset(HasSync,0,Length * sizeof(char));
unsigned short int lines[SYNCW+SYNCW/4][(MAXSLANT-MINSLANT)*2];
unsigned short int lines[600][(MAXSLANT-MINSLANT)*2];
unsigned short int cy, cx;
int q, d, qMost, dMost;
@ -36,9 +41,6 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
int maxsy = 0;
FILE *GrayFile;
char PixBuf[1] = {0};
unsigned short int xAcc[SYNCW] = {0};
unsigned short int xMax = 0;
unsigned short int Leftmost;
double Pwr[2048];
// FFT plan
@ -74,6 +76,7 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
printf("power est.\n");
// Power estimation
for (s = 0; s < Length; s+=50) {
// Hann window
@ -97,8 +100,8 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
// 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
if (Psync > 2*Praw) HasSync[s] = TRUE;
else HasSync[s] = FALSE;
if (Psync > 2*Praw) HasSync[s] = TRUE;
else HasSync[s] = FALSE;
for (i = 0; i < 50; i++) {
if (s+i >= Length) break;
@ -112,19 +115,13 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
// Repeat until slant < 0.5° or until we give up
while (1) {
/*GrayFile = fopen("sync.gray","w");
if (GrayFile == NULL) {
perror("Unable to open sync.gray for writing");
exit(EXIT_FAILURE);
}*/
TotPix = 0;
TotPix = LineWidth/2; // Start at the middle of the picture
NextImgSample = 0;
t = 0;
maxsy = 0;
memset(SyncImg, 0, sizeof(SyncImg[0][0]) * SYNCW * 500);
memset(SyncImg, 0, sizeof(SyncImg[0][0]) * LineWidth * 500);
// Draw the sync signal into memory
for (s = 0; s < Length; s++) {
@ -133,42 +130,52 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
if (t >= NextImgSample) {
x = TotPix % SYNCW;
y = TotPix / SYNCW;
x = TotPix % LineWidth;
y = TotPix / LineWidth;
SyncImg[x][y] = HasSync[s];
if (y > maxsy) maxsy = y;
//PixBuf[0] = (SyncImg[x][y] ? 255 : 0);
//fwrite(PixBuf, 1, 1, GrayFile);
TotPix++;
NextImgSample += ModeSpec[Mode].LineLen / (1.0 * SYNCW);
NextImgSample += ModeSpec[Mode].LineLen / (1.0 * LineWidth);
}
}
//fclose(GrayFile);
// write sync.gray
GrayFile = fopen("sync.gray","w");
if (GrayFile == NULL) {
perror("Unable to open sync.gray for writing");
exit(EXIT_FAILURE);
}
for (y=0;y<maxsy;y++) {
for (x=0;x<LineWidth;x++) {
PixBuf[0] = (SyncImg[x][y] ? 255 : 0);
fwrite(PixBuf, 1, 1, GrayFile);
}
}
fclose(GrayFile);
/** Linear Hough transform **/
// zero arrays
dMost = qMost = 0;
for (d=0; d<SYNCW+SYNCW/4; d++)
for (d=0; d<LineWidth+LineWidth/4; d++)
for (q=MINSLANT*2; q < MAXSLANT * 2; q++)
lines[d][q-MINSLANT*2] = 0;
// Find white pixels
for (cy = 0; cy < TotPix / SYNCW; cy++) {
for (cx = 0; cx < SYNCW; cx++) {
for (cy = 0; cy < TotPix / LineWidth; cy++) {
for (cx = 0; cx < LineWidth; cx++) {
if (SyncImg[cx][cy]) {
// Slant angles to consider
for (q = MINSLANT*2; q < MAXSLANT*2; q ++) {
// Line accumulator
d = SYNCW + round( -cx * sin(deg2rad(q/2.0)) + cy * cos(deg2rad(q/2.0)) );
if (d > 0 && d < SYNCW+SYNCW/4) {
d = LineWidth + round( -cx * sin(deg2rad(q/2.0)) + cy * cos(deg2rad(q/2.0)) );
if (d > 0 && d < LineWidth+LineWidth/4) {
lines[d][q-MINSLANT*2] ++;
if (lines[d][q-MINSLANT*2] > lines[dMost][qMost-MINSLANT*2]) {
dMost = d;
@ -188,18 +195,12 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
slantAngle = qMost / 2.0;
//printf(" most (%d occurrences): d=%d q=%f\n", LineAcc[dMost][ (int)(qMost * 10) ], dMost, qMost);
printf(" %.1f° @ %.2f Hz", slantAngle, Rate);
printf(" %.1f° (d=%d) @ %.2f Hz", slantAngle, dMost, Rate);
Rate = Rate + tan(deg2rad(90 - slantAngle)) / (1.0 * SYNCW) * Rate;
if (Rate < 40000 || Rate > 50000) {
printf(" unrealistic receiving conditions; giving up.\n");
Rate = 44100;
break;
}
Rate = Rate + tan(deg2rad(90 - slantAngle)) / (1.0 * LineWidth) * Rate;
if (slantAngle > 89 && slantAngle < 91) {
printf(" -> %.2f slant OK :)\n", Rate);
printf(" slant OK :)\n");
break;
} else if (Retries == 3) {
printf(" still slanted; giving up\n");
@ -212,32 +213,13 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
}
}
printf(" gray = %dx%d\n", SYNCW, maxsy);
printf(" gray = %dx%d\n", LineWidth, maxsy);
// Find the abscissa of the now vertical sync pulse
for (i=0;i<SYNCW;i++) xAcc[i] = 0;
xMax = 0;
for (cy = 0; cy < TotPix / SYNCW; cy++) {
for (cx = 1; cx < SYNCW; cx++) {
if (!SyncImg[cx - 1][cy] && SyncImg[cx][cy]) {
xAcc[cx]++;
if (xAcc[cx] > xAcc[xMax]) xMax = cx;
}
}
}
// Now, find the leftmost one of those vertical lines with the maximum occurrences
Leftmost = SYNCW;
for (i = 0; i < SYNCW; i++)
if (xAcc[i] == xAcc[xMax] && i < Leftmost)
Leftmost = i;
if (Rate == 44100) Leftmost = 0;
printf(" abscissa = %d (%d occurrences)", Leftmost, xAcc[Leftmost]);
Leftmost = Leftmost * (ModeSpec[Mode].LineLen / (1.0 * SYNCW)) * Rate;
printf(" (need to skip %d samples)\n", Leftmost);
*Skip = Leftmost;
//s = (LineWidth/2 - dMost) * (ModeSpec[Mode].LineLen / (1.0 * LineWidth)) * Rate;
//s -= ModeSpec[Mode].SyncLen / 2.0 * Rate;
//*Skip = s;
*Skip = 0;
free(HasSync);
fftw_destroy_plan(Plan);

97
video.c
Wyświetl plik

@ -32,7 +32,7 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
double Pvideo_plus_noise=0, Pnoise_only=0, Pnoise=0, Psignal=0;
double SNR = 0;
double CurLineTime = 0;
double ChanStart[3] = {0}, ChanLen[3] = {0};
double ChanStart[4] = {0}, ChanLen[4] = {0};
unsigned char Lum=0, Image[800][616][3] = {{{0}}};
unsigned char Channel = 0;
fftw_plan Plan, BigPlan, SNRPlan;
@ -75,21 +75,10 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
0.2673747, 0.2122111, 0.1631808, 0.1206692, 0.1569882 };
// Starting times of video channels on every line, counted from beginning of sync pulse
// Starting times of video channels on every line, counted from beginning of line
switch (Mode) {
case R72:
case R24BW:
case R12BW:
case R8BW:
ChanLen[0] = ModeSpec[Mode].PixelLen * ModeSpec[Mode].ImgWidth;
ChanLen[1] = ChanLen[2] = ChanLen[0];
ChanStart[0] = ModeSpec[Mode].SyncLen + ModeSpec[Mode].PorchLen;
ChanStart[1] = ChanStart[0] + ChanLen[0] + ModeSpec[Mode].SeparatorLen;
ChanStart[2] = ChanStart[1] + ChanLen[1] + ModeSpec[Mode].SeparatorLen;
break;
case R36:
case R24:
ChanLen[0] = ModeSpec[Mode].PixelLen * ModeSpec[Mode].ImgWidth * 2;
@ -99,6 +88,15 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
ChanStart[2] = ChanStart[1];
break;
case S1:
case S2:
case SDX:
ChanLen[0] = ChanLen[1] = ChanLen[2] = ModeSpec[Mode].PixelLen * ModeSpec[Mode].ImgWidth;
ChanStart[0] = ModeSpec[Mode].SeparatorLen;
ChanStart[1] = ChanStart[0] + ChanLen[0] + ModeSpec[Mode].SeparatorLen;
ChanStart[2] = ChanStart[1] + ChanLen[1] + ModeSpec[Mode].SyncLen + ModeSpec[Mode].PorchLen;
break;
default:
ChanLen[0] = ChanLen[1] = ChanLen[2] = ModeSpec[Mode].PixelLen * ModeSpec[Mode].ImgWidth;
ChanStart[0] = ModeSpec[Mode].SyncLen + ModeSpec[Mode].PorchLen;
@ -141,7 +139,7 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
} else {
// Read 2048 samples
if (Sample >= PcmPointer - 2048) {
if (Sample == 0 || Sample >= PcmPointer - 2048) {
if (!PcmInStream || feof (PcmInStream) || PcmPointer > Length-2048) break;
samplesread = fread(PcmBuffer, 2, 2048, PcmInStream);
@ -317,7 +315,7 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
case PD180:
case PD240:
case PD290:
if (CurLineTime >= ChanStart[2] + ChanLen[2]) Channel = 4; // ch 0 of even line
if (CurLineTime >= ChanStart[2] + ChanLen[2]) Channel = 3; // ch 0 of even line
else if (CurLineTime >= ChanStart[2]) Channel = 2;
else if (CurLineTime >= ChanStart[1]) Channel = 1;
else Channel = 0;
@ -332,71 +330,18 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
}
// X coordinate of this pixel
switch(Mode) {
case S1:
case S2:
case SDX:
x = fmod(CurLineTime - ModeSpec[Mode].SyncLen - ModeSpec[Mode].PorchLen, ChanLen[Channel] +
ModeSpec[Mode].SeparatorLen) / ChanLen[Channel] * ModeSpec[Mode].ImgWidth;
break;
default:
x = (CurLineTime - ChanStart[Channel]) / ChanLen[Channel] * ModeSpec[Mode].ImgWidth;
break;
}
x = (CurLineTime - ChanStart[Channel]) / ChanLen[Channel] * ModeSpec[Mode].ImgWidth;
// Y coordinate of this pixel
switch(Mode) {
case S1:
case S2:
case SDX:
switch(Channel) {
case 0:
y = LineNum;
Channel = 2;
break;
case 1:
y = LineNum + 1;
Channel = 0;
break;
case 2:
y = LineNum + 1;
Channel = 1;
break;
}
break;
case PD50:
case PD90:
case PD120:
case PD160:
case PD180:
case PD240:
case PD290:
switch(Channel) {
case 4:
y = LineNum + 1;
Channel = 0;
break;
default:
y = LineNum;
break;
}
switch(Channel) {
case 3:
y = LineNum + 1;
Channel = 0;
break;
default:
y = LineNum;
break;
}
// Luminance from frequency
@ -454,9 +399,9 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
}
if (!Redraw || LineNum % 5 == 0 || LineNum == ModeSpec[Mode].ImgHeight-1) {
gdk_threads_enter();
gtk_image_set_from_pixbuf(GTK_IMAGE(CamImage), CamPixbuf);
gdk_threads_leave();
gdk_threads_enter();
gtk_image_set_from_pixbuf(GTK_IMAGE(CamImage), CamPixbuf);
gdk_threads_leave();
}
}
prevline = LineNum;

16
vis.c
Wyświetl plik

@ -83,7 +83,7 @@ int GetVIS () {
// Zero padding, if necessary
for (i = 882; i < FFTLen; i++) in[i] = 0;
// FFT
// FFT of last 20 ms
fftw_execute(VISPlan);
MaxBin = 0;
@ -101,14 +101,14 @@ int GetVIS () {
HedrBuf[HedrPtr] = MaxBin + (log( Power[MaxBin + 1] / Power[MaxBin - 1] )) /
(2 * log( pow(Power[MaxBin], 2) / (Power[MaxBin + 1] * Power[MaxBin - 1])));
} else {
HedrBuf[HedrPtr] = HedrBuf[(HedrPtr-1)%100];
HedrBuf[HedrPtr] = HedrBuf[(HedrPtr-1)%50];
}
// Header buffer holds 50 * 10 = 500 msec
// Header buffer holds 50 * 10 msec = 500 msec
HedrPtr = (HedrPtr + 1) % 50;
for (i = 0; i < 50; i++) {
tone[i] = HedrBuf[(i + HedrPtr) % 50];
tone[i] = HedrBuf[(HedrPtr + i) % 50];
tone[i] = 1.0 * tone[i] / FFTLen * 44100;
}
@ -186,8 +186,12 @@ int GetVIS () {
free(PCM);
// Skip 20 ms
samplesread = fread(PcmBuffer, 2, 441*2, PcmInStream);
// Skip 10 ms
samplesread = fread(PcmBuffer, 2, 441, PcmInStream);
// In case of Scottie, skip another 9 ms
if (VISmap[VIS] == S1 || VISmap[VIS] == S2 || VISmap[VIS] == SDX)
samplesread = fread(PcmBuffer, 2, 397, PcmInStream);
if (feof(PcmInStream)) perror("unable to read from dsp");
else if (VISmap[VIS] != UNKNOWN) return VISmap[VIS];