extracted wavewrite from convenience, improved rtl_fm

* rtl_fm using rtlsdr_set_tuner_band_center
* rtl_fm recording to .wav.tmp, renaming it when finished

Signed-off-by: hayati ayguen <h_ayguen@web.de>
development
hayati ayguen 2019-07-18 23:25:32 +00:00
parent 7ef5e11b0b
commit 3f3fefc9e4
8 changed files with 393 additions and 186 deletions

View File

@ -102,7 +102,7 @@ endif()
# Setup libraries used in executables
########################################################################
add_library(convenience_static STATIC
convenience/convenience.c
convenience/convenience.c convenience/wavewrite.c
)
if(WIN32)

View File

@ -401,150 +401,4 @@ void executeInBackground( char * file, char * args, char * searchStr[], char * r
#endif
#pragma pack(push)
#pragma pack(1)
typedef struct {
uint16_t wYear; /* 1601 through 30827 */
uint16_t wMonth; /* 1..12 */
uint16_t wDayOfWeek; /* 0 .. 6: 0 == Sunday, .., 6 == Saturday */
uint16_t wDay; /* 1 .. 31 */
uint16_t wHour; /* 0 .. 23 */
uint16_t wMinute; /* 0 .. 59 */
uint16_t wSecond; /* 0 .. 59 */
uint16_t wMilliseconds; /* 0 .. 999 */
} Wind_SystemTime;
typedef struct
{
/* RIFF header */
char riffID[4]; /* "RIFF" string */
uint32_t riffSize; /* full filesize - 8 bytes (maybe with some byte missing...) */
char waveID[4]; /* "WAVE" string */
/* FMT header */
char fmtID[4]; /* = "FMT " */
uint32_t fmtSize;
int16_t wFormatTag;
int16_t nChannels;
int32_t nSamplesPerSec;
int32_t nAvgBytesPerSec;
int16_t nBlockAlign;
int16_t nBitsPerSample;
/* auxi header - used by SpectraVue / rfspace / HDSDR / .. */
char auxiID[4]; /* ="auxi" (chunk rfspace) */
uint32_t auxiSize;
Wind_SystemTime StartTime;
Wind_SystemTime StopTime;
uint32_t centerFreq; /* receiver center frequency */
uint32_t ADsamplerate; /* A/D sample frequency before downsampling */
uint32_t IFFrequency; /* IF freq if an external down converter is used */
uint32_t Bandwidth; /* displayable BW if you want to limit the display to less than Nyquist band */
int32_t IQOffset; /* DC offset of the I and Q channels in 1/1000's of a count */
int32_t Unused2;
int32_t Unused3;
int32_t Unused4;
int32_t Unused5;
/* DATA header */
char dataID[4];
uint32_t dataSize;
} waveFileHeader;
static waveFileHeader waveHdr;
#pragma pack(pop)
uint32_t waveDataSize = 0;
static int waveHdrStarted = 0;
void waveSetTime(Wind_SystemTime *p)
{
struct timeval tv;
struct tm t;
gettimeofday(&tv, NULL);
p->wMilliseconds = tv.tv_usec / 1000;
#ifdef _WIN32
t = *gmtime(&tv.tv_sec);
#else
gmtime_r(&tv.tv_sec, &t);
#endif
p->wYear = t.tm_year + 1900; /* 1601 through 30827 */
p->wMonth = t.tm_mon + 1; /* 1..12 */
p->wDayOfWeek = t.tm_wday; /* 0 .. 6: 0 == Sunday, .., 6 == Saturday */
p->wDay = t.tm_mday; /* 1 .. 31 */
p->wHour = t.tm_hour; /* 0 .. 23 */
p->wMinute = t.tm_min; /* 0 .. 59 */
p->wSecond = t.tm_sec; /* 0 .. 59 */
}
void wavePrepareHeader(unsigned samplerate, unsigned freq, int bitsPerSample, int numChannels)
{
int bytesPerSample = bitsPerSample / 8;
int bytesPerFrame = bytesPerSample * numChannels;
strncpy( waveHdr.riffID, "RIFF", 4 );
waveHdr.riffSize = sizeof(waveFileHeader) - 8; /* to fix */
strncpy( waveHdr.waveID, "WAVE", 4 );
strncpy( waveHdr.fmtID, "fmt ", 4 );
waveHdr.fmtSize = 16;
waveHdr.wFormatTag = 1; /* PCM */
waveHdr.nChannels = numChannels; /* I and Q channels */
waveHdr.nSamplesPerSec = samplerate;
waveHdr.nAvgBytesPerSec = samplerate * bytesPerFrame;
waveHdr.nBlockAlign = waveHdr.nChannels;
waveHdr.nBitsPerSample = bitsPerSample;
strncpy( waveHdr.auxiID, "auxi", 4 );
waveHdr.auxiSize = 2 * sizeof(Wind_SystemTime) + 9 * sizeof(int32_t); /* = 2 * 16 + 9 * 4 = 68 */
waveSetTime( &waveHdr.StartTime );
waveHdr.StopTime = waveHdr.StartTime; /* to fix */
waveHdr.centerFreq = freq;
waveHdr.ADsamplerate = samplerate;
waveHdr.IFFrequency = 0;
waveHdr.Bandwidth = 0;
waveHdr.IQOffset = 0;
waveHdr.Unused2 = 0;
waveHdr.Unused3 = 0;
waveHdr.Unused4 = 0;
waveHdr.Unused5 = 0;
strncpy( waveHdr.dataID, "data", 4 );
waveHdr.dataSize = 0; /* to fix later */
waveDataSize = 0;
}
void waveWriteHeader(unsigned samplerate, unsigned freq, int bitsPerSample, int numChannels, FILE * f)
{
if (f != stdout) {
assert( !waveHdrStarted );
wavePrepareHeader(samplerate, freq, bitsPerSample, numChannels);
fwrite(&waveHdr, sizeof(waveFileHeader), 1, f);
waveHdrStarted = 1;
}
}
void waveFinalizeHeader(FILE * f)
{
if (f != stdout) {
assert( waveHdrStarted );
waveSetTime( &waveHdr.StopTime );
waveHdr.dataSize = waveDataSize;
waveHdr.riffSize += waveDataSize;
fseek(f, 0, SEEK_SET);
fwrite(&waveHdr, sizeof(waveFileHeader), 1, f);
waveHdrStarted = 0;
}
}
// vim: tabstop=8:softtabstop=8:shiftwidth=8:noexpandtab

View File

@ -164,21 +164,6 @@ int verbose_device_search(char *s);
void executeInBackground( char * file, char * args, char * searchStr[], char * replaceStr[] );
/*!
* helper functions to write and finalize wave headers
* with compatibility to some SDR programs - showing frequency:
* raw sample data still have to be written by caller to FILE*.
* call waveWriteHeader() before writing anything to to file
* and call waveFinalizeHeader() afterwards,
* AND count/increment the written raw size in variable 'waveDataSize'.
* stdout/stdout can't be used, because seek to begin isn't possible.
*
*/
extern uint32_t waveDataSize;
void waveWriteHeader(unsigned samplerate, unsigned freq, int bitsPerSample, int numChannels, FILE * f);
void waveFinalizeHeader(FILE * f);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,240 @@
/*
* Copyright (C) 2019 by Hayati Ayguen <h_ayguen@web.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "wavewrite.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#ifndef _WIN32
#include <unistd.h>
#include <sys/time.h>
#else
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#include <process.h>
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#pragma pack(push)
#pragma pack(1)
typedef struct {
uint16_t wYear; /* 1601 through 30827 */
uint16_t wMonth; /* 1..12 */
uint16_t wDayOfWeek; /* 0 .. 6: 0 == Sunday, .., 6 == Saturday */
uint16_t wDay; /* 1 .. 31 */
uint16_t wHour; /* 0 .. 23 */
uint16_t wMinute; /* 0 .. 59 */
uint16_t wSecond; /* 0 .. 59 */
uint16_t wMilliseconds; /* 0 .. 999 */
} Wind_SystemTime;
typedef struct
{
/* RIFF header */
char riffID[4]; /* "RIFF" string */
uint32_t riffSize; /* full filesize - 8 bytes (maybe with some byte missing...) */
char waveID[4]; /* "WAVE" string */
/* FMT header */
char fmtID[4]; /* = "FMT " */
uint32_t fmtSize;
int16_t wFormatTag;
int16_t nChannels;
int32_t nSamplesPerSec;
int32_t nAvgBytesPerSec;
int16_t nBlockAlign;
int16_t nBitsPerSample;
/* auxi header - used by SpectraVue / rfspace / HDSDR / .. */
char auxiID[4]; /* ="auxi" (chunk rfspace) */
uint32_t auxiSize;
Wind_SystemTime StartTime;
Wind_SystemTime StopTime;
uint32_t centerFreq; /* receiver center frequency */
uint32_t ADsamplerate; /* A/D sample frequency before downsampling */
uint32_t IFFrequency; /* IF freq if an external down converter is used */
uint32_t Bandwidth; /* displayable BW if you want to limit the display to less than Nyquist band */
int32_t IQOffset; /* DC offset of the I and Q channels in 1/1000's of a count */
int32_t Unused2;
int32_t Unused3;
int32_t Unused4;
int32_t Unused5;
/* DATA header */
char dataID[4];
uint32_t dataSize;
} waveFileHeader;
static waveFileHeader waveHdr;
#pragma pack(pop)
static uint32_t waveDataSize = 0;
static int waveHdrStarted = 0;
void waveSetTime(Wind_SystemTime *p)
{
struct timeval tv;
struct tm t;
gettimeofday(&tv, NULL);
p->wMilliseconds = tv.tv_usec / 1000;
#ifdef _WIN32
t = *gmtime(&tv.tv_sec);
#else
gmtime_r(&tv.tv_sec, &t);
#endif
p->wYear = t.tm_year + 1900; /* 1601 through 30827 */
p->wMonth = t.tm_mon + 1; /* 1..12 */
p->wDayOfWeek = t.tm_wday; /* 0 .. 6: 0 == Sunday, .., 6 == Saturday */
p->wDay = t.tm_mday; /* 1 .. 31 */
p->wHour = t.tm_hour; /* 0 .. 23 */
p->wMinute = t.tm_min; /* 0 .. 59 */
p->wSecond = t.tm_sec; /* 0 .. 59 */
}
void wavePrepareHeader(unsigned samplerate, unsigned freq, int bitsPerSample, int numChannels)
{
int bytesPerSample = bitsPerSample / 8;
int bytesPerFrame = bytesPerSample * numChannels;
strncpy( waveHdr.riffID, "RIFF", 4 );
waveHdr.riffSize = sizeof(waveFileHeader) - 8; /* to fix */
strncpy( waveHdr.waveID, "WAVE", 4 );
strncpy( waveHdr.fmtID, "fmt ", 4 );
waveHdr.fmtSize = 16;
waveHdr.wFormatTag = 1; /* PCM */
waveHdr.nChannels = numChannels; /* I and Q channels */
waveHdr.nSamplesPerSec = samplerate;
waveHdr.nAvgBytesPerSec = samplerate * bytesPerFrame;
waveHdr.nBlockAlign = waveHdr.nChannels;
waveHdr.nBitsPerSample = bitsPerSample;
strncpy( waveHdr.auxiID, "auxi", 4 );
waveHdr.auxiSize = 2 * sizeof(Wind_SystemTime) + 9 * sizeof(int32_t); /* = 2 * 16 + 9 * 4 = 68 */
waveSetTime( &waveHdr.StartTime );
waveHdr.StopTime = waveHdr.StartTime; /* to fix */
waveHdr.centerFreq = freq;
waveHdr.ADsamplerate = samplerate;
waveHdr.IFFrequency = 0;
waveHdr.Bandwidth = 0;
waveHdr.IQOffset = 0;
waveHdr.Unused2 = 0;
waveHdr.Unused3 = 0;
waveHdr.Unused4 = 0;
waveHdr.Unused5 = 0;
strncpy( waveHdr.dataID, "data", 4 );
waveHdr.dataSize = 0; /* to fix later */
waveDataSize = 0;
}
void waveWriteHeader(unsigned samplerate, unsigned freq, int bitsPerSample, int numChannels, FILE * f)
{
if (f != stdout) {
assert( !waveHdrStarted );
wavePrepareHeader(samplerate, freq, bitsPerSample, numChannels);
fwrite(&waveHdr, sizeof(waveFileHeader), 1, f);
waveHdrStarted = 1;
}
}
int waveWriteSamples(FILE* f, void * vpData, size_t numSamples, int needCleanData)
{
size_t nw;
switch (waveHdr.nBitsPerSample)
{
case 0:
default:
return 1;
case 8:
/* no endian conversion needed for single bytes */
nw = fwrite(vpData, sizeof(uint8_t), numSamples, f);
waveDataSize += sizeof(uint8_t) * numSamples;
return (nw == numSamples) ? 0 : 1;
case 16:
/* TODO: endian conversion needed */
nw = fwrite(vpData, sizeof(int16_t), numSamples, f);
waveDataSize += sizeof(int16_t) * numSamples;
if ( needCleanData )
{
/* TODO: convert back endianness */
}
return (nw == numSamples) ? 0 : 1;
}
}
int waveWriteFrames(FILE* f, void * vpData, size_t numFrames, int needCleanData)
{
size_t nw;
switch (waveHdr.nBitsPerSample)
{
case 0:
default:
return 1;
case 8:
/* no endian conversion needed for single bytes */
nw = fwrite(vpData, waveHdr.nChannels * sizeof(uint8_t), numFrames, f);
waveDataSize += waveHdr.nChannels * sizeof(uint8_t) * numFrames;
return (nw == numFrames) ? 0 : 1;
case 16:
/* TODO: endian conversion needed */
nw = fwrite(vpData, waveHdr.nChannels * sizeof(int16_t), numFrames, f);
waveDataSize += waveHdr.nChannels * sizeof(int16_t) * numFrames;
if ( needCleanData )
{
/* TODO: convert back endianness */
}
return (nw == numFrames) ? 0 : 1;
}
}
int waveFinalizeHeader(FILE * f)
{
if (f != stdout) {
assert( waveHdrStarted );
waveSetTime( &waveHdr.StopTime );
waveHdr.dataSize = waveDataSize;
waveHdr.riffSize += waveDataSize;
waveHdrStarted = 0;
if ( fseek(f, 0, SEEK_SET) )
return 1;
if ( 1 != fwrite(&waveHdr, sizeof(waveFileHeader), 1, f) )
return 1;
return 0;
}
return 1;
}
// vim: tabstop=8:softtabstop=8:shiftwidth=8:noexpandtab

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2019 by Hayati Ayguen <h_ayguen@web.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WAVEWRITE_H
#define __WAVEWRITE_H
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* helper functions to write and finalize wave headers
* with compatibility to some SDR programs - showing frequency:
* raw sample data still have to be written by caller to FILE*.
* call waveWriteHeader() before writing anything to to file
* and call waveFinalizeHeader() afterwards,
* stdout/stderr can't be used, because seek to begin isn't possible.
*
*/
void waveWriteHeader(unsigned samplerate, unsigned freq, int bitsPerSample, int numChannels, FILE * f);
/* waveWriteFrames() writes (numFrames * numChannels) samples
* waveWriteSamples()
* both return 0, when no errors occured
*/
int waveWriteFrames(FILE* f, void * vpData, size_t numFrames, int needCleanData);
int waveWriteSamples(FILE* f, void * vpData, size_t numSamples, int needCleanData); /* returns 0, when no errors occured */
int waveFinalizeHeader(FILE * f); /* returns 0, when no errors occured */
#ifdef __cplusplus
}
#endif
#endif /*__WAVEWRITE_H*/

View File

@ -83,6 +83,7 @@
#include "rtl-sdr.h"
#include "convenience/convenience.h"
#include "convenience/wavewrite.h"
#define DEFAULT_SAMPLE_RATE 24000
#define DEFAULT_BUF_LENGTH (1 * 16384)
@ -111,6 +112,8 @@ static int printLevelNo = 1;
static int levelMax = 0;
static int levelMaxMax = 0;
static double levelSum = 0.0;
static int32_t prev_if_band_center_freq = 0;
enum trigExpr { crit_IN =0, crit_OUT, crit_LT, crit_GT };
char * aCritStr[] = { "in", "out", "<", ">" };
@ -213,6 +216,7 @@ struct output_state
pthread_t thread;
FILE *file;
char *filename;
char *tempfilename;
int16_t result[MAXIMUM_BUF_LENGTH];
int result_len;
int rate;
@ -1386,13 +1390,23 @@ static void *demod_thread_fn(void *arg)
static void *output_thread_fn(void *arg)
{
struct output_state *s = arg;
while (!do_exit) {
// use timedwait and pad out under runs
safe_cond_wait(&s->ready, &s->ready_m);
pthread_rwlock_rdlock(&s->rw);
fwrite(s->result, 2, s->result_len, s->file);
waveDataSize += 2 * s->result_len;
pthread_rwlock_unlock(&s->rw);
if ( s->file == stdout ) {
while (!do_exit) {
/* use timedwait and pad out under runs */
safe_cond_wait(&s->ready, &s->ready_m);
pthread_rwlock_rdlock(&s->rw);
fwrite(s->result, 2, s->result_len, s->file);
pthread_rwlock_unlock(&s->rw);
}
} else {
while (!do_exit) {
/* use timedwait and pad out under runs */
safe_cond_wait(&s->ready, &s->ready_m);
pthread_rwlock_rdlock(&s->rw);
/* distinguish for endianness: wave requires little endian */
waveWriteSamples(s->file, s->result, s->result_len, 0);
pthread_rwlock_unlock(&s->rw);
}
}
return 0;
}
@ -1442,6 +1456,7 @@ static void *controller_thread_fn(void *arg)
// thoughts for multiple dongles
// might be no good using a controller thread if retune/rate blocks
int i, r, execWaitHop = 1;
int32_t if_band_center_freq = 0;
struct controller_state *s = arg;
struct cmd_state *c = s->cmd;
@ -1485,6 +1500,20 @@ static void *controller_thread_fn(void *arg)
verbose_set_sample_rate(dongle.dev, dongle.rate);
fprintf(stderr, "Output at %u Hz.\n", demod.rate_in/demod.post_downsample);
if ( dongle.bandwidth ) {
if_band_center_freq = dongle.userFreq - dongle.freq;
if ( prev_if_band_center_freq != if_band_center_freq ) {
r = rtlsdr_set_tuner_band_center(dongle.dev, if_band_center_freq );
if (r)
fprintf(stderr, "WARNING: Failed to set band center.\n");
else {
prev_if_band_center_freq = if_band_center_freq;
if (verbosity)
fprintf(stderr, "rtlsdr_set_tuner_band_center(%.0f Hz) successful\n", (double)if_band_center_freq);
}
}
}
while (!do_exit) {
if (execWaitHop)
safe_cond_wait(&s->hop, &s->hop_m);
@ -1497,9 +1526,22 @@ static void *controller_thread_fn(void *arg)
s->freq_now = (s->freq_now + 1) % s->freq_len;
optimal_settings(s->freqs[s->freq_now], demod.rate_in);
rtlsdr_set_center_freq(dongle.dev, dongle.freq);
if ( dongle.bandwidth ) {
if_band_center_freq = dongle.userFreq - dongle.freq;
if ( prev_if_band_center_freq != if_band_center_freq ) {
r = rtlsdr_set_tuner_band_center(dongle.dev, if_band_center_freq );
if (r)
fprintf(stderr, "WARNING: Failed to set band center.\n");
else {
prev_if_band_center_freq = if_band_center_freq;
if (verbosity)
fprintf(stderr, "rtlsdr_set_tuner_band_center(%.0f Hz) successful\n", (double)if_band_center_freq);
}
}
}
dongle.mute = DEFAULT_BUFFER_DUMP;
} else {
dongle.mute = 2 * 3200000; /* over a second - until parametrized the dongle */
dongle.mute = 2 * dongle.rate; /* over a second - until parametrized the dongle */
c->numSummed = 0;
toNextCmdLine(c);
@ -1538,7 +1580,21 @@ static void *controller_thread_fn(void *arg)
if (r < 0)
fprintf(stderr, "WARNING: Failed to set bandwidth.\n");
else
c->prevBandwidth != dongle.bandwidth;
c->prevBandwidth = dongle.bandwidth;
}
/* */
if ( dongle.bandwidth ) {
if_band_center_freq = dongle.userFreq - dongle.freq;
if ( prev_if_band_center_freq != if_band_center_freq ) {
r = rtlsdr_set_tuner_band_center(dongle.dev, if_band_center_freq );
if (r)
fprintf(stderr, "WARNING: Failed to set band center.\n");
else {
prev_if_band_center_freq = if_band_center_freq;
if (verbosity)
fprintf(stderr, "rtlsdr_set_tuner_band_center(%.0f Hz) successful\n", (double)if_band_center_freq);
}
}
}
/* 4- Set ADC samplerate *
r = rtlsdr_set_sample_rate(dongle.dev, dongle.rate);
@ -1972,14 +2028,17 @@ int main(int argc, char **argv)
_setmode(_fileno(output.file), _O_BINARY);
#endif
} else {
output.file = fopen(output.filename, "wb");
output.tempfilename = malloc( strlen(output.filename)+8 );
strcpy(output.tempfilename, output.filename);
strcat(output.tempfilename, ".tmp");
output.file = fopen(output.tempfilename, "wb");
if (!output.file) {
fprintf(stderr, "Failed to open %s\n", output.filename);
fprintf(stderr, "Failed to open %s\n", output.tempfilename);
exit(1);
}
else
{
fprintf(stderr, "Open %s for write\n", output.filename);
fprintf(stderr, "Open %s for write\n", output.tempfilename);
if (writeWav) {
int nChan = (demod.mode_demod == &raw_demod) ? 2 : 1;
int srate = (demod.rate_out2 > 0) ? demod.rate_out2 : demod.rate_out;
@ -2033,10 +2092,16 @@ int main(int argc, char **argv)
}
if (output.file != stdout) {
int r;
if (writeWav) {
waveFinalizeHeader(output.file);
}
fclose(output.file);}
fclose(output.file);
r = rename( output.tempfilename, output.filename ); // #include <stdio.h>
if ( r )
fprintf( stderr, "%s: error %d '%s' renaming'%s' to '%s'\n"
, argv[0], errno, strerror(errno), output.tempfilename, output.filename );
}
rtlsdr_close(dongle.dev);
return r >= 0 ? r : -r;

View File

@ -33,6 +33,7 @@
#include "rtl-sdr.h"
#include "convenience/convenience.h"
#include "convenience/wavewrite.h"
#define DEFAULT_SAMPLE_RATE 2048000
#define DEFAULT_BANDWIDTH 0 /* automatic bandwidth */
@ -97,13 +98,16 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
rtlsdr_cancel_async(dev);
}
if (fwrite(buf, 1, len, (FILE*)ctx) != len) {
fprintf(stderr, "Short write, samples lost, exiting!\n");
rtlsdr_cancel_async(dev);
}
else
{
waveDataSize += len;
if ( (FILE*)ctx == stdout ) {
if (fwrite(buf, 1, len, (FILE*)ctx) != len) {
fprintf(stderr, "Short write, samples lost, exiting!\n");
rtlsdr_cancel_async(dev);
}
} else {
if ( waveWriteSamples((FILE*)ctx, buf, len/2, 0) ) {
fprintf(stderr, "Short write, samples lost, exiting!\n");
rtlsdr_cancel_async(dev);
}
}
if (bytes_to_read > 0)
@ -279,11 +283,17 @@ int main(int argc, char **argv)
do_exit = 1;
}
if (fwrite(buffer, 1, n_read, file) != (size_t)n_read) {
fprintf(stderr, "Short write, samples lost, exiting!\n");
break;
if ( file == stdout) {
if (fwrite(buffer, 1, n_read, file) != (size_t)n_read) {
fprintf(stderr, "Short write, samples lost, exiting!\n");
break;
}
} else {
if ( waveWriteSamples(file, buffer, n_read/2, 0) ) {
fprintf(stderr, "Short write, samples lost, exiting!\n");
break;
}
}
waveDataSize += n_read;
if ((uint32_t)n_read < out_block_size) {
fprintf(stderr, "Short read, samples lost, exiting!\n");

View File

@ -50,6 +50,8 @@ SET( RTLLIBFILES
../src/convenience/convenience.c
../src/convenience/convenience.h
../src/convenience/wavewrite.c
../src/convenience/wavewrite.h
../src/getopt/getopt.c
../src/getopt/getopt.h