kopia lustrzana https://github.com/windytan/slowrx
mad rewrite of video timing logic
rodzic
06748fe211
commit
5372b4b97a
2
Makefile
2
Makefile
|
@ -11,7 +11,7 @@ OBJECTS = common.o modespec.o gui.o video.o vis.o sync.o pcm.o fsk.o slowrx.o
|
|||
all: slowrx
|
||||
|
||||
slowrx: $(OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $(OBJECTS) $(GTKLIBS) -lfftw3 -lgthread-2.0 -lpnglite -lasound -lm
|
||||
$(CC) $(CFLAGS) -o $@ $(OBJECTS) $(GTKLIBS) -lfftw3 -lgthread-2.0 -lasound -lm
|
||||
|
||||
%.o: %.c common.h
|
||||
$(CC) $(CFLAGS) $(GTKCFLAGS) $(OFLAGS) -c -o $@ $<
|
||||
|
|
2
common.h
2
common.h
|
@ -132,7 +132,7 @@ void *Listen ();
|
|||
void populateDeviceList ();
|
||||
void readPcm (gint numsamples);
|
||||
void saveCurrentPic();
|
||||
void setVU (short int PcmValue, double SNRdB);
|
||||
void setVU (short int PcmValue, int WinIdx);
|
||||
|
||||
void evt_AbortRx ();
|
||||
void evt_changeDevices ();
|
||||
|
|
13
gui.c
13
gui.c
|
@ -77,16 +77,16 @@ void createGUI() {
|
|||
gtk_entry_set_text(GTK_ENTRY(gui.entry_picdir),g_key_file_get_string(config,"slowrx","rxdir",NULL));
|
||||
}
|
||||
|
||||
setVU(0, -100);
|
||||
setVU(0, 6);
|
||||
|
||||
gtk_widget_show_all (gui.window_main);
|
||||
|
||||
}
|
||||
|
||||
// Draw signal level meters according to given values
|
||||
void setVU (short int PcmValue, double SNRdB) {
|
||||
void setVU (short int PcmValue, int WinIdx) {
|
||||
int x,y;
|
||||
int PWRdB = (int)round(10 * log10(pow(PcmValue/32767.0,2)));
|
||||
int PWRdB;
|
||||
guchar *pixelsPWR, *pixelsSNR, *pPWR, *pSNR;
|
||||
unsigned int rowstridePWR,rowstrideSNR;
|
||||
|
||||
|
@ -96,6 +96,11 @@ void setVU (short int PcmValue, double SNRdB) {
|
|||
rowstrideSNR = gdk_pixbuf_get_rowstride (pixbuf_SNR);
|
||||
pixelsSNR = gdk_pixbuf_get_pixels (pixbuf_SNR);
|
||||
|
||||
if (PcmValue == 0)
|
||||
PWRdB = 0;
|
||||
else
|
||||
PWRdB = (int)round(10 * log10(pow(PcmValue/32767.0,2)));
|
||||
|
||||
for (y=0; y<20; y++) {
|
||||
for (x=0; x<100; x++) {
|
||||
|
||||
|
@ -112,7 +117,7 @@ void setVU (short int PcmValue, double SNRdB) {
|
|||
pPWR[0] = pPWR[1] = pPWR[2] = 0x80;
|
||||
}
|
||||
|
||||
if (SNRdB >= -0.6*x+40) {
|
||||
if ((6-WinIdx)/0.06 > 100-x) {
|
||||
pSNR[0] = 0xef;
|
||||
pSNR[1] = 0xe4;
|
||||
pSNR[2] = 0x34;
|
||||
|
|
1
pcm.c
1
pcm.c
|
@ -183,6 +183,7 @@ int initPcmDevice(char *wanteddevname) {
|
|||
}
|
||||
|
||||
pcm.Buffer = calloc( BUFLEN, sizeof(gint16));
|
||||
memset(pcm.Buffer, 0, BUFLEN);
|
||||
|
||||
if (exact_rate != 44100) {
|
||||
fprintf(stderr, "ALSA: Got %d Hz instead of 44100. Expect artifacts.\n", exact_rate);
|
||||
|
|
8
slowrx.c
8
slowrx.c
|
@ -83,14 +83,14 @@ void *Listen() {
|
|||
|
||||
// Allocate space for cached Lum
|
||||
free(StoredLum);
|
||||
StoredLum = calloc( (int)(ModeSpec[CurrentPic.Mode].LineLen * ModeSpec[CurrentPic.Mode].ImgHeight + 1) * 44100, sizeof(guchar));
|
||||
StoredLum = calloc( (int)((ModeSpec[CurrentPic.Mode].LineLen * ModeSpec[CurrentPic.Mode].ImgHeight + 1) * 44100), sizeof(guchar));
|
||||
if (StoredLum == NULL) {
|
||||
perror("Listen: Unable to allocate memory for Lum");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Allocate space for sync signal
|
||||
HasSync = calloc((int)(ModeSpec[CurrentPic.Mode].LineLen * ModeSpec[CurrentPic.Mode].ImgHeight / SYNCPIXLEN +1), sizeof(gboolean));
|
||||
HasSync = calloc((int)(ModeSpec[CurrentPic.Mode].LineLen * ModeSpec[CurrentPic.Mode].ImgHeight / (13.0/44100) +1), sizeof(gboolean));
|
||||
if (HasSync == NULL) {
|
||||
perror("Listen: Unable to allocate memory for sync signal");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -136,7 +136,7 @@ void *Listen() {
|
|||
if (Finished && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gui.tog_slant))) {
|
||||
|
||||
// Fix slant
|
||||
setVU(0,-100);
|
||||
setVU(0,6);
|
||||
gdk_threads_enter ();
|
||||
gtk_statusbar_push (GTK_STATUSBAR(gui.statusbar), 0, "Calculating slant..." );
|
||||
gtk_widget_set_sensitive (gui.grid_vu, FALSE);
|
||||
|
@ -163,7 +163,7 @@ void *Listen() {
|
|||
// Save PNG
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(gui.tog_save))) {
|
||||
|
||||
setVU(0,-100);
|
||||
setVU(0,6);
|
||||
|
||||
/*ensure_dir_exists("rx-lum");
|
||||
LumFile = fopen(lumfilename,"w");
|
||||
|
|
8
sync.c
8
sync.c
|
@ -23,7 +23,7 @@ double FindSync (guchar Mode, double Rate, int *Skip) {
|
|||
gushort xAcc[700] = {0};
|
||||
gushort lines[600][(MAXSLANT-MINSLANT)*2];
|
||||
gushort cy, cx, Retries = 0;
|
||||
gboolean SyncImg[700][630] = {{FALSE}};
|
||||
gboolean SyncImg[700][630] = {{FALSE}};
|
||||
double t=0, slantAngle, s;
|
||||
double ConvoFilter[8] = { 1,1,1,1,-1,-1,-1,-1 };
|
||||
double convd, maxconvd=0;
|
||||
|
@ -37,7 +37,7 @@ double FindSync (guchar Mode, double Rate, int *Skip) {
|
|||
for (y=0; y<ModeSpec[Mode].ImgHeight; y++) {
|
||||
for (x=0; x<LineWidth; x++) {
|
||||
t = (y + 1.0*x/LineWidth) * ModeSpec[Mode].LineLen;
|
||||
SyncImg[x][y] = HasSync[ (int)( t / SYNCPIXLEN * Rate/44100) ];
|
||||
SyncImg[x][y] = HasSync[ (int)( t * Rate / 13.0) ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ double FindSync (guchar Mode, double Rate, int *Skip) {
|
|||
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 / SYNCPIXLEN * Rate/44100) ];
|
||||
xAcc[x] += HasSync[ (int)(t / (13.0/44100) * Rate/44100) ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,8 @@ double FindSync (guchar Mode, double Rate, int *Skip) {
|
|||
+ ModeSpec[Mode].PorchLen * 2;
|
||||
|
||||
*Skip = s * Rate;
|
||||
|
||||
printf("will return %.2f\n",Rate);
|
||||
|
||||
return (Rate);
|
||||
|
||||
|
|
249
video.c
249
video.c
|
@ -25,20 +25,31 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
guint i=0, j=0;
|
||||
guint FFTLen=1024, WinLength=0;
|
||||
guint LopassBin,SyncTargetBin;
|
||||
int LineNum = 0, SampleNum, Length;
|
||||
int x = 0, y = 0, prevline=0, tx=0;
|
||||
int SampleNum, Length, NumChans;
|
||||
int x = 0, y = 0, tx=0, k=0;
|
||||
double Hann[7][1024] = {{0}};
|
||||
double t=0, Freq = 0, PrevFreq = 0, InterpFreq = 0, NextPixelTime = 0, NextSNRtime = 0;
|
||||
double NextSyncTime = 0;
|
||||
double Freq = 0, PrevFreq = 0, InterpFreq = 0;
|
||||
int NextSNRtime = 0, NextSyncTime = 0;
|
||||
double Praw, Psync;
|
||||
double Power[1024] = {0};
|
||||
double Pvideo_plus_noise=0, Pnoise_only=0, Pnoise=0, Psignal=0;
|
||||
double SNR = 0;
|
||||
double CurLineTime = 0;
|
||||
double ChanStart[4] = {0}, ChanLen[4] = {0};
|
||||
guchar Image[800][616][3] = {{{0}}};
|
||||
guchar Channel = 0, WinIdx = 0;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int X;
|
||||
int Y;
|
||||
int Time;
|
||||
guchar Channel;
|
||||
gboolean Last;
|
||||
} _PixelGrid;
|
||||
|
||||
_PixelGrid *PixelGrid;
|
||||
PixelGrid = calloc( ModeSpec[Mode].ImgWidth * ModeSpec[Mode].ImgHeight * 3, sizeof(_PixelGrid) );
|
||||
|
||||
|
||||
// Initialize Hann windows of different lengths
|
||||
gushort HannLens[7] = { 48, 64, 96, 128, 256, 512, 1024 };
|
||||
for (j = 0; j < 7; j++)
|
||||
|
@ -46,7 +57,6 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
Hann[j][i] = 0.5 * (1 - cos( (2 * M_PI * i) / (HannLens[j] - 1)) );
|
||||
|
||||
// Starting times of video channels on every line, counted from beginning of line
|
||||
|
||||
switch (Mode) {
|
||||
|
||||
case R36:
|
||||
|
@ -76,6 +86,73 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
|
||||
}
|
||||
|
||||
// Number of channels per line
|
||||
switch(Mode) {
|
||||
case R24BW:
|
||||
case R12BW:
|
||||
case R8BW:
|
||||
NumChans = 1;
|
||||
break;
|
||||
case R24:
|
||||
case R36:
|
||||
NumChans = 2;
|
||||
break;
|
||||
default:
|
||||
NumChans = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// Plan ahead the time instants (in samples) at which to take pixels out
|
||||
int PixelIdx = 0;
|
||||
for (y=0; y<ModeSpec[Mode].ImgHeight; y++) {
|
||||
for (Channel=0; Channel<NumChans; Channel++) {
|
||||
for (x=0; x<ModeSpec[Mode].ImgWidth; x++) {
|
||||
|
||||
if (Mode == R36 || Mode == R24) {
|
||||
if (Channel == 1) {
|
||||
if (y % 2 == 0) PixelGrid[PixelIdx].Channel = 1;
|
||||
else PixelGrid[PixelIdx].Channel = 2;
|
||||
} else PixelGrid[PixelIdx].Channel = 0;
|
||||
} else {
|
||||
PixelGrid[PixelIdx].Channel = Channel;
|
||||
}
|
||||
|
||||
PixelGrid[PixelIdx].Time = (int)round(Rate * (y * ModeSpec[Mode].LineLen + ChanStart[Channel] +
|
||||
(1.0*(x-.5)/ModeSpec[Mode].ImgWidth*ChanLen[PixelGrid[PixelIdx].Channel]))) + Skip;
|
||||
|
||||
|
||||
PixelGrid[PixelIdx].X = x;
|
||||
PixelGrid[PixelIdx].Y = y;
|
||||
|
||||
|
||||
PixelGrid[PixelIdx].Last = FALSE;
|
||||
|
||||
PixelIdx ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelGrid[PixelIdx-1].Last = TRUE;
|
||||
|
||||
for (k=0; k<PixelIdx; k++) {
|
||||
if (PixelGrid[k].Time >= 0) {
|
||||
PixelIdx = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*case PD50:
|
||||
case PD90:
|
||||
case PD120:
|
||||
case PD160:
|
||||
case PD180:
|
||||
case PD240:
|
||||
case PD290:
|
||||
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;
|
||||
break;*/
|
||||
|
||||
// Initialize pixbuffer
|
||||
if (!Redraw) {
|
||||
g_object_unref(pixbuf_rx);
|
||||
|
@ -86,7 +163,7 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
int rowstride = gdk_pixbuf_get_rowstride (pixbuf_rx);
|
||||
guchar *pixels, *p;
|
||||
pixels = gdk_pixbuf_get_pixels(pixbuf_rx);
|
||||
|
||||
|
||||
g_object_unref(pixbuf_disp);
|
||||
pixbuf_disp = gdk_pixbuf_scale_simple(pixbuf_rx, 500,
|
||||
500.0/ModeSpec[Mode].ImgWidth * ModeSpec[Mode].ImgHeight * ModeSpec[Mode].YScale, GDK_INTERP_BILINEAR);
|
||||
|
@ -104,10 +181,6 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
// Loop through signal
|
||||
for (SampleNum = 0; SampleNum < Length; SampleNum++) {
|
||||
|
||||
t = (SampleNum - Skip) / Rate;
|
||||
|
||||
CurLineTime = fmod(t, ModeSpec[Mode].LineLen);
|
||||
|
||||
if (!Redraw) {
|
||||
|
||||
/*** Read ahead from sound card ***/
|
||||
|
@ -117,7 +190,7 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
|
||||
/*** Store the sync band for later adjustments ***/
|
||||
|
||||
if (t >= NextSyncTime) {
|
||||
if (SampleNum == NextSyncTime) {
|
||||
|
||||
Praw = Psync = 0;
|
||||
|
||||
|
@ -145,15 +218,19 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
if (Psync > 2*Praw) HasSync[SyncSampleNum] = TRUE;
|
||||
else HasSync[SyncSampleNum] = FALSE;
|
||||
|
||||
NextSyncTime += SYNCPIXLEN;
|
||||
NextSyncTime += 13;
|
||||
SyncSampleNum ++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*** Estimate SNR ***/
|
||||
|
||||
if (t >= NextSNRtime) {
|
||||
if (SampleNum == NextSNRtime) {
|
||||
|
||||
memset(in, 0, sizeof(double)*FFTLen);
|
||||
memset(out, 0, sizeof(double)*FFTLen);
|
||||
|
||||
// Apply Hann window
|
||||
for (i = 0; i < FFTLen; i++) in[i] = pcm.Buffer[pcm.WindowPtr + i - FFTLen/2] / 32768.0 * Hann[6][i];
|
||||
|
@ -191,13 +268,14 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
// Lower bound to -20 dB
|
||||
SNR = ((Psignal / Pnoise < .01) ? -20 : 10 * log10(Psignal / Pnoise));
|
||||
|
||||
NextSNRtime += 8e-3;
|
||||
NextSNRtime += 256;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*** FM demodulation ***/
|
||||
|
||||
if (t >= NextPixelTime) {
|
||||
if (SampleNum % 6 == 0) { // Take FFT every 6 samples
|
||||
|
||||
PrevFreq = Freq;
|
||||
|
||||
|
@ -219,6 +297,7 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
WinLength = HannLens[WinIdx];
|
||||
|
||||
memset(in, 0, sizeof(double)*FFTLen);
|
||||
memset(out, 0, sizeof(double)*FFTLen);
|
||||
|
||||
// Apply window function
|
||||
|
||||
|
@ -242,135 +321,71 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
(2 * log( pow(Power[MaxBin], 2) / (Power[MaxBin + 1] * Power[MaxBin - 1])));
|
||||
// In Hertz
|
||||
Freq = Freq / FFTLen * 44100;
|
||||
InterpFreq = Freq;
|
||||
} else {
|
||||
// Clip if out of bounds
|
||||
Freq = ( (MaxBin > GetBin(1900 + CurrentPic.HedrShift, FFTLen)) ? 2300 : 1500 ) + CurrentPic.HedrShift;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Linear interpolation of (chronologically) intermediate frequencies
|
||||
InterpFreq = PrevFreq + (Freq-PrevFreq) * ((t-(NextPixelTime-ModeSpec[Mode].PixelLen))/ModeSpec[Mode].PixelLen);
|
||||
} /* endif (SampleNum == PixelGrid[PixelIdx].Time) */
|
||||
|
||||
// Linear interpolation of (chronologically) intermediate frequencies, for redrawing
|
||||
//InterpFreq = PrevFreq + (Freq-PrevFreq) * ... // TODO!
|
||||
|
||||
// Calculate luminency & store for later use
|
||||
StoredLum[SampleNum] = clip((InterpFreq - (1500 + CurrentPic.HedrShift)) / 3.1372549);
|
||||
StoredLum[SampleNum] = clip((Freq - (1500 + CurrentPic.HedrShift)) / 3.1372549);
|
||||
|
||||
}
|
||||
} /* endif (!Redraw) */
|
||||
|
||||
|
||||
/*** Are we on a video line, and should we sample a pixel? ***/
|
||||
|
||||
if ( ((CurLineTime >= ChanStart[0] && CurLineTime < ChanStart[0] + ChanLen[0])
|
||||
|| (CurLineTime >= ChanStart[1] && CurLineTime < ChanStart[1] + ChanLen[1])
|
||||
|| (CurLineTime >= ChanStart[2] && CurLineTime < ChanStart[2] + ChanLen[2]) )
|
||||
&& t >= NextPixelTime
|
||||
) {
|
||||
if (SampleNum == PixelGrid[PixelIdx].Time) {
|
||||
|
||||
LineNum = t / ModeSpec[Mode].LineLen;
|
||||
x = PixelGrid[PixelIdx].X;
|
||||
y = PixelGrid[PixelIdx].Y;
|
||||
Channel = PixelGrid[PixelIdx].Channel;
|
||||
|
||||
// Store pixel
|
||||
Image[x][y][Channel] = StoredLum[SampleNum];
|
||||
|
||||
// Which channel is this?
|
||||
switch(Mode) {
|
||||
|
||||
case R24BW:
|
||||
case R12BW:
|
||||
case R8BW:
|
||||
Channel = 0;
|
||||
break;
|
||||
|
||||
case R36:
|
||||
case R24:
|
||||
if (CurLineTime >= ChanStart[1]) {
|
||||
if (LineNum % 2 == 0) Channel = 1;
|
||||
else Channel = 2;
|
||||
} else Channel = 0;
|
||||
break;
|
||||
|
||||
case PD50:
|
||||
case PD90:
|
||||
case PD120:
|
||||
case PD160:
|
||||
case PD180:
|
||||
case PD240:
|
||||
case PD290:
|
||||
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;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (CurLineTime >= ChanStart[2]) Channel = 2;
|
||||
else if (CurLineTime >= ChanStart[1]) Channel = 1;
|
||||
else Channel = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// X coordinate of this pixel
|
||||
x = (CurLineTime - ChanStart[Channel]) / ChanLen[Channel] * ModeSpec[Mode].ImgWidth;
|
||||
|
||||
// Y coordinate of this pixel
|
||||
switch(Channel) {
|
||||
case 3:
|
||||
y = LineNum + 1;
|
||||
Channel = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
y = LineNum;
|
||||
break;
|
||||
}
|
||||
|
||||
// Store pixel
|
||||
if (x >= 0 && y >= 0 && x < ModeSpec[Mode].ImgWidth) {
|
||||
Image[x][y][Channel] = StoredLum[SampleNum];
|
||||
// Some modes have R-Y & B-Y channels that are twice the height of the Y channel
|
||||
if (Channel > 0)
|
||||
switch(Mode) {
|
||||
case R36:
|
||||
case R24:
|
||||
if (y < ModeSpec[Mode].ImgHeight-1) Image[x][y+1][Channel] = StoredLum[SampleNum];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (y > ModeSpec[Mode].ImgHeight-1) break;
|
||||
// Some modes have R-Y & B-Y channels that are twice the height of the Y channel
|
||||
if (Channel > 0 && (Mode == R36 || Mode == R24))
|
||||
Image[x][y+1][Channel] = StoredLum[SampleNum];
|
||||
|
||||
// Calculate and draw pixels to pixbuf on line change
|
||||
if (LineNum != prevline || (LineNum == ModeSpec[Mode].ImgHeight-1 && x == ModeSpec[Mode].ImgWidth-1)) {
|
||||
if (x == ModeSpec[Mode].ImgWidth-1 || PixelGrid[PixelIdx].Last) {
|
||||
for (tx = 0; tx < ModeSpec[Mode].ImgWidth; tx++) {
|
||||
p = pixels + prevline * rowstride + tx * 3;
|
||||
p = pixels + y * rowstride + tx * 3;
|
||||
|
||||
switch(ModeSpec[Mode].ColorEnc) {
|
||||
|
||||
case RGB:
|
||||
p[0] = Image[tx][prevline][0];
|
||||
p[1] = Image[tx][prevline][1];
|
||||
p[2] = Image[tx][prevline][2];
|
||||
p[0] = Image[tx][y][0];
|
||||
p[1] = Image[tx][y][1];
|
||||
p[2] = Image[tx][y][2];
|
||||
break;
|
||||
|
||||
case GBR:
|
||||
p[0] = Image[tx][prevline][2];
|
||||
p[1] = Image[tx][prevline][0];
|
||||
p[2] = Image[tx][prevline][1];
|
||||
p[0] = Image[tx][y][2];
|
||||
p[1] = Image[tx][y][0];
|
||||
p[2] = Image[tx][y][1];
|
||||
break;
|
||||
|
||||
case YUV:
|
||||
p[0] = clip((100 * Image[tx][prevline][0] + 140 * Image[tx][prevline][1] - 17850) / 100.0);
|
||||
p[1] = clip((100 * Image[tx][prevline][0] - 71 * Image[tx][prevline][1] - 33 *
|
||||
Image[tx][prevline][2] + 13260) / 100.0);
|
||||
p[2] = clip((100 * Image[tx][prevline][0] + 178 * Image[tx][prevline][2] - 22695) / 100.0);
|
||||
p[0] = clip((100 * Image[tx][y][0] + 140 * Image[tx][y][1] - 17850) / 100.0);
|
||||
p[1] = clip((100 * Image[tx][y][0] - 71 * Image[tx][y][1] - 33 *
|
||||
Image[tx][y][2] + 13260) / 100.0);
|
||||
p[2] = clip((100 * Image[tx][y][0] + 178 * Image[tx][y][2] - 22695) / 100.0);
|
||||
break;
|
||||
|
||||
case BW:
|
||||
p[0] = p[1] = p[2] = Image[tx][prevline][0];
|
||||
p[0] = p[1] = p[2] = Image[tx][y][0];
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!Redraw || LineNum % 5 == 0 || LineNum == ModeSpec[Mode].ImgHeight-1) {
|
||||
if (!Redraw || y % 5 == 0 || PixelGrid[PixelIdx].Last) {
|
||||
// Scale and update image
|
||||
g_object_unref(pixbuf_disp);
|
||||
pixbuf_disp = gdk_pixbuf_scale_simple(pixbuf_rx, 500,
|
||||
|
@ -382,17 +397,13 @@ gboolean GetVideo(guchar Mode, double Rate, int Skip, gboolean Redraw) {
|
|||
}
|
||||
}
|
||||
|
||||
if (LineNum > prevline)
|
||||
NextPixelTime = t + ModeSpec[Mode].PixelLen/3; // take 3 samples per pixel; to better allow for redraw
|
||||
else
|
||||
NextPixelTime += ModeSpec[Mode].PixelLen/3;
|
||||
PixelIdx ++;
|
||||
|
||||
prevline = LineNum;
|
||||
|
||||
}
|
||||
|
||||
} /* endif (SampleNum == PixelGrid[PixelIdx].Time) */
|
||||
|
||||
if (!Redraw && SampleNum % 8820 == 0) {
|
||||
setVU(pcm.PeakVal, SNR);
|
||||
setVU(pcm.PeakVal, WinIdx);
|
||||
pcm.PeakVal = 0;
|
||||
}
|
||||
|
||||
|
|
11
vis.c
11
vis.c
|
@ -18,12 +18,10 @@
|
|||
guchar GetVIS () {
|
||||
|
||||
int selmode, ptr=0;
|
||||
//int Pointer = 0;
|
||||
int VIS = 0, Parity = 0, HedrPtr = 0;
|
||||
//gushort pcm.PeakVal = 0;
|
||||
guint FFTLen = 2048, i=0, j=0, k=0, MaxBin = 0;
|
||||
double Power[2048] = {0}, HedrBuf[100] = {0}, tone[100] = {0}, Hann[882] = {0};
|
||||
gboolean gotvis = FALSE;
|
||||
gboolean gotvis = FALSE;
|
||||
guchar Bit[8] = {0}, ParityBit = 0;
|
||||
|
||||
for (i = 0; i < FFTLen; i++) in[i] = 0;
|
||||
|
@ -56,11 +54,12 @@ guchar GetVIS () {
|
|||
MaxBin = 0;
|
||||
for (i = GetBin(500, FFTLen); i <= GetBin(3300, FFTLen); i++) {
|
||||
Power[i] = pow(out[i], 2) + pow(out[FFTLen - i], 2);
|
||||
if (Power[i] > Power[MaxBin] || MaxBin == 0) MaxBin = i;
|
||||
if (MaxBin == 0 || Power[i] > Power[MaxBin]) MaxBin = i;
|
||||
}
|
||||
|
||||
// Find the peak frequency by Gaussian interpolation
|
||||
if (MaxBin > GetBin(500, FFTLen) && MaxBin < GetBin(3300, FFTLen))
|
||||
if (MaxBin > GetBin(500, FFTLen) && MaxBin < GetBin(3300, FFTLen) &&
|
||||
Power[MaxBin] > 0 && Power[MaxBin+1] > 0 && Power[MaxBin-1] > 0)
|
||||
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) % 45];
|
||||
|
@ -157,7 +156,7 @@ guchar GetVIS () {
|
|||
}
|
||||
|
||||
if (++ptr == 25) {
|
||||
setVU(pcm.PeakVal, -20);
|
||||
setVU(pcm.PeakVal, 6);
|
||||
pcm.PeakVal = 0;
|
||||
ptr = 0;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue