move from SoX pipe to alsa libs

pull/1/merge
Oona 2011-07-29 23:09:42 +03:00
rodzic 9d608a0aa1
commit ba4ce3ce73
10 zmienionych plików z 118 dodań i 67 usunięć

Wyświetl plik

@ -1,6 +1,6 @@
CC = gcc
CFLAGS = -Wall -Wextra -std=gnu99 -pedantic
CFLAGS = -Wall -Wextra -std=gnu99 -pedantic -g
OFLAGS = -O3
@ -8,7 +8,7 @@ all: slowrx
slowrx: common.h common.c slowrx.c gui.c video.c sync.c vis.c modespec.c
$(CC) $(CFLAGS) $(OFLAGS) common.c modespec.c gui.c video.c vis.c sync.c slowrx.c -o slowrx -lfftw3 -lm `pkg-config --cflags --libs gtk+-2.0` -lgthread-2.0 -lpnglite
$(CC) $(CFLAGS) $(OFLAGS) common.c modespec.c gui.c video.c vis.c sync.c slowrx.c -o slowrx -lfftw3 -lm `pkg-config --cflags --libs gtk+-2.0` -lgthread-2.0 -lpnglite -lasound
clean:
rm -f *.o

Wyświetl plik

@ -3,11 +3,6 @@ slowrx
This program decodes analogue [SSTV](http://en.wikipedia.org/wiki/Slow-scan%20television) images received through the sound card.
Prerequisites
-------------
Needs linux and sox. Depends on libs gtk2, fftw3, and pnglite.
Features
--------
@ -17,6 +12,14 @@ Features
* Noise reduction using adaptive windowing
* Saves received pictures as PNG along with the corresponding raw signals
Libraries
---------
* ALSA
* GTK+ 2.x
* FFTW 3.x
* pnglite
References
----------

Wyświetl plik

@ -1,9 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <math.h>
#include <gtk/gtk.h>
#include <alsa/asoundlib.h>
#include "common.h"
int VISmap[128];
@ -17,6 +18,7 @@ int UseWav = FALSE;
guchar *rgbbuf = NULL;
int maxpwr = 0;
int minpwr = 0;
unsigned int SRate = 44100;
double PowerAcc[2048] = {0};
double MaxPower[2048] = {0};
double *StoredFreq = NULL;
@ -40,6 +42,8 @@ GtkWidget *SNRimage[10] = {NULL};
GtkWidget *vutable = NULL;
GtkWidget *infolabel = NULL;
snd_pcm_t *pcm_handle = NULL;
void ClearPixbuf(GdkPixbuf *pb, unsigned int width, unsigned int height) {
unsigned int x,y,rowstride;
@ -58,7 +62,7 @@ void ClearPixbuf(GdkPixbuf *pb, unsigned int width, unsigned int height) {
// Return the bin index matching the given frequency
unsigned int GetBin (double Freq, int FFTLen) {
return (Freq / 44100.0 * FFTLen);
return (Freq / SRATE * FFTLen);
}
// Clip to [0..255]

Wyświetl plik

@ -3,7 +3,8 @@
#define MINSLANT 30
#define MAXSLANT 150
#define SNRSIZE 2048
#define SNRSIZE 512
#define SRATE 44100
extern int VISmap[128];
@ -16,6 +17,7 @@ extern int UseWav;
extern guchar *rgbbuf;
extern int maxpwr;
extern int minpwr;
extern unsigned int SRate;
extern double PowerAcc[2048];
extern double MaxPower[2048];
extern double *StoredFreq;
@ -39,6 +41,8 @@ extern GtkWidget *SNRimage[10];
extern GtkWidget *vutable;
extern GtkWidget *infolabel;
extern snd_pcm_t *pcm_handle;
enum {
M1, M2, M3, M4,
S1, S2, SDX,

1
gui.c
Wyświetl plik

@ -1,5 +1,6 @@
#include <stdlib.h>
#include <gtk/gtk.h>
#include <alsa/asoundlib.h>
#include "common.h"
void delete_event() {

Wyświetl plik

@ -3,6 +3,7 @@
#include <math.h>
#include <fftw3.h>
#include <gtk/gtk.h>
#include <alsa/asoundlib.h>
#include "common.h"

Wyświetl plik

@ -13,6 +13,8 @@
#include <pthread.h>
#include <pnglite.h>
#include <alsa/asoundlib.h>
#include "common.h"
void wavdemod () {
@ -27,7 +29,7 @@ void populate_recent() {
void *Cam() {
double Rate = 44100;
double Rate = SRATE;
int Skip = 0, i=0;
int Mode = 0;
time_t timet;
@ -41,14 +43,8 @@ void *Cam() {
FILE *LumFile;
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");
if (PcmInStream == NULL) {
perror("Unable to open sox pipe");
exit(EXIT_FAILURE);
}
while (1) {
// Wait for VIS
HedrShift = 0;
@ -69,18 +65,18 @@ void *Cam() {
printf(" \"%s\"\n", pngfilename);
// Allocate space for PCM
PCM = calloc( (int)(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight + 1) * 44100, sizeof(double));
PCM = calloc( (int)(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight + 1) * SRATE, sizeof(double));
if (PCM == NULL) {
perror("Cam: Unable to allocate memory for PCM");
pclose(PcmInStream);
//pclose(PcmInStream);
exit(EXIT_FAILURE);
}
// Allocate space for cached FFT
StoredFreq = calloc( (int)(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight + 1) * 44100, sizeof(double));
StoredFreq = calloc( (int)(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight + 1) * SRATE, sizeof(double));
if (StoredFreq == NULL) {
perror("Cam: Unable to allocate memory for demodulated signal");
pclose(PcmInStream);
//pclose(PcmInStream);
free(PCM);
exit(EXIT_FAILURE);
}
@ -94,15 +90,13 @@ void *Cam() {
gdk_threads_leave();
PcmPointer = 2048;
Sample = 0;
Rate = 44100;
Rate = SRATE;
Skip = 0;
printf(" getvideo @ %.02f Hz, Skip %d, HedrShift %.0f Hz\n", Rate, Skip, HedrShift);
snd_pcm_start(pcm_handle);
GetVideo(Mode, Rate, Skip, TRUE, FALSE);
// Done with the input stream
pclose(PcmInStream);
PcmInStream = 0;
snd_pcm_drop(pcm_handle);
// Fix slant
gdk_threads_enter();
@ -127,12 +121,12 @@ void *Cam() {
gdk_threads_leave();
// Save the raw signal
Lum = malloc( (ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * 44100 );
Lum = malloc( (ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE );
if (Lum == NULL) {
perror("Unable to allocate memory for lum data");
exit(EXIT_FAILURE);
}
for (i=0; i<(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * 44100; i++)
for (i=0; i<(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE; i++)
Lum[i] = clip((StoredFreq[i] - (1500 + HedrShift)) / 3.1372549);
LumFile = fopen(lumfilename,"w");
@ -140,7 +134,7 @@ void *Cam() {
perror("Unable to open luma file for writing");
exit(EXIT_FAILURE);
}
fwrite(Lum,1,(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * 44100,LumFile);
fwrite(Lum,1,(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE,LumFile);
fclose(LumFile);
// Save the received image as PNG
@ -160,6 +154,63 @@ void *Cam() {
}
}
void initPcm() {
snd_pcm_stream_t PcmInStream = SND_PCM_STREAM_CAPTURE;
snd_pcm_hw_params_t *hwparams;
char *pcm_name;
pcm_name = strdup("default");
snd_pcm_hw_params_alloca(&hwparams);
if (snd_pcm_open(&pcm_handle, pcm_name, PcmInStream, 0) < 0) {
fprintf(stderr, "ALSA: Error opening PCM device %s\n", pcm_name);
exit(EXIT_FAILURE);
}
/* Init hwparams with full configuration space */
if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
fprintf(stderr, "ALSA: Can not configure this PCM device.\n");
exit(EXIT_FAILURE);
}
unsigned int exact_rate; /* Sample rate returned by */
/* snd_pcm_hw_params_set_rate_near */
if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
fprintf(stderr, "ALSA: Error setting interleaved access.\n");
exit(EXIT_FAILURE);
}
/* Set sample format */
if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {
fprintf(stderr, "ALSA: Error setting format S16_LE.\n");
exit(EXIT_FAILURE);
}
exact_rate = 44100;
if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0) < 0) {
fprintf(stderr, "ALSA: Error setting sample rate.\n");
exit(EXIT_FAILURE);
}
SRate = exact_rate;
if (exact_rate != 44100) fprintf(stderr, "ALSA: Using %d Hz instead of 44100.\n", exact_rate);
/* Set number of channels */
if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 1) < 0) {
fprintf(stderr, "ALSA: Can't set channels to mono.\n");
exit(EXIT_FAILURE);
}
/* Apply HW parameter settings to */
/* PCM device and prepare device */
if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) {
fprintf(stderr, "ALSA: Error setting HW params.\n");
exit(EXIT_FAILURE);
}
}
/*
* main
*/
@ -171,7 +222,7 @@ int main(int argc, char *argv[]) {
pthread_t thread1;
// Set stdout to be line buffered
setvbuf(stdout, NULL, _IOLBF, 0);
//setvbuf(stdout, NULL, _IOLBF, 0);
for (i=0;i<128;i++) VISmap[i] = UNKNOWN;
@ -207,6 +258,7 @@ int main(int argc, char *argv[]) {
g_thread_init (NULL);
gdk_threads_init ();
initPcm();
createGUI();
pthread_create (&thread1, NULL, Cam, NULL);

25
sync.c
Wyświetl plik

@ -3,6 +3,8 @@
#include <string.h>
#include <fftw3.h>
#include <gtk/gtk.h>
#include <alsa/asoundlib.h>
#include "common.h"
/* Find the horizontal sync signal and adjust sample rate to cancel out any slant.
@ -40,8 +42,6 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
int q, d, qMost, dMost;
unsigned short int Retries = 0;
int maxsy = 0;
FILE *GrayFile;
char PixBuf[1] = {0};
double Pwr[2048];
// FFT plan
@ -147,27 +147,12 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
}
}
// 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<LineWidth; d++)
for (q=MINSLANT*2; q < MAXSLANT * 2; q++)
lines[d][q-MINSLANT*2] = 0;
memset(lines, 0, sizeof(lines[0][0]) * (MAXSLANT-MINSLANT)*2 * LineWidth);
// Find white pixels
for (cy = 0; cy < TotPix / LineWidth; cy++) {
@ -208,8 +193,8 @@ double FindSync (unsigned int Length, int Mode, double Rate, int *Skip) {
break;
} else if (Retries == 3) {
printf(" still slanted; giving up\n");
Rate = 44100;
printf(" -> 44100\n");
Rate = SRATE;
printf(" -> SRATE\n");
break;
} else {
printf(" -> %.2f recalculating\n", Rate);

Wyświetl plik

@ -4,6 +4,7 @@
#include <string.h>
#include <fftw3.h>
#include <gtk/gtk.h>
#include <alsa/asoundlib.h>
#include "common.h"
@ -121,7 +122,7 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
if (!Redraw) StoredFreqRate = Rate;
Length = (ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * 44100;
Length = (ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE;
// Loop through signal
for (Sample = 0; Sample < Length; Sample++) {
@ -142,7 +143,7 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
if (Sample == 0 || Sample >= PcmPointer - 2048) {
if (!PcmInStream || feof (PcmInStream) || PcmPointer > Length-2048) break;
samplesread = fread(PcmBuffer, 2, 2048, PcmInStream);
samplesread = snd_pcm_readi(pcm_handle, PcmBuffer, 2048);
if (samplesread < 2048) break;
for (i = 0; i < 2048; i++) {
@ -267,7 +268,7 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
Freq = MaxBin + (log( Power[MaxBin + 1] / Power[MaxBin - 1] )) /
(2 * log( pow(Power[MaxBin], 2) / (Power[MaxBin + 1] * Power[MaxBin - 1])));
// In Hertz
Freq = Freq / FFTLen * 44100;
Freq = Freq / FFTLen * SRATE;
} else {
// Use last usable freq
}

24
vis.c
Wyświetl plik

@ -3,6 +3,7 @@
#include <fftw3.h>
#include <pthread.h>
#include <gtk/gtk.h>
#include <alsa/asoundlib.h>
#include "common.h"
@ -54,22 +55,22 @@ int GetVIS () {
for (i = 0; i < FFTLen; i++) in[i] = 0;
// Create Hann window
double Hann[882] = {0};
for (i = 0; i < 882; i++) Hann[i] = 0.5 * (1 - cos( (2 * M_PI * (double)i) / 881) );
// Create 20ms Hann window
double Hann[SRATE/50] = {0};
for (i = 0; i < SRATE*20e-3; i++) Hann[i] = 0.5 * (1 - cos( (2 * M_PI * (double)i) / (SRATE*20e-3 -1) ) );
// Allocate space for PCM (1 second)
PCM = calloc(44100, sizeof(double));
PCM = calloc(SRATE, sizeof(double));
if (PCM == NULL) {
perror("GetVIS: Unable to allocate memory for PCM");
pclose(PcmInStream);
exit(EXIT_FAILURE);
}
while ( !feof(PcmInStream) ) {
while ( TRUE ) {
// Read 10 ms from DSP
samplesread = fread(PcmBuffer, 2, 441, PcmInStream);
samplesread = snd_pcm_readi(pcm_handle, PcmBuffer, SRATE*10e-3);
// Move buffer
for (i = 0; i < samplesread; i++) {
@ -81,7 +82,7 @@ int GetVIS () {
}
// Apply Hann window
for (i = 0; i < 882; i++) in[i] = PCM[i] * Hann[i];
for (i = 0; i < SRATE* 20e-3; i++) in[i] = PCM[i] * Hann[i];
// FFT of last 20 ms
fftw_execute(VISPlan);
@ -109,7 +110,7 @@ int GetVIS () {
for (i = 0; i < 50; i++) {
tone[i] = HedrBuf[(HedrPtr + i) % 50];
tone[i] = 1.0 * tone[i] / FFTLen * 44100;
tone[i] = 1.0 * tone[i] / FFTLen * SRATE;
}
// Is there a pattern that looks like (the end of) a calibration header + VIS?
@ -188,10 +189,9 @@ int GetVIS () {
// In case of Scottie, skip 9 ms
if (VISmap[VIS] == S1 || VISmap[VIS] == S2 || VISmap[VIS] == SDX)
samplesread = fread(PcmBuffer, 2, 397, PcmInStream);
samplesread = snd_pcm_readi(pcm_handle, PcmBuffer, SRATE*9e-3);
if (feof(PcmInStream)) perror("unable to read from dsp");
else if (VISmap[VIS] != UNKNOWN) return VISmap[VIS];
else printf(" No VIS found\n");
if (VISmap[VIS] != UNKNOWN) return VISmap[VIS];
else printf(" No VIS found\n");
return -1;
}