From 3f3fefc9e45f901d013fa578d860a9364cddd074 Mon Sep 17 00:00:00 2001 From: hayati ayguen Date: Thu, 18 Jul 2019 23:25:32 +0000 Subject: [PATCH] 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 --- src/CMakeLists.txt | 2 +- src/convenience/convenience.c | 146 -------------------- src/convenience/convenience.h | 15 --- src/convenience/wavewrite.c | 240 +++++++++++++++++++++++++++++++++ src/convenience/wavewrite.h | 51 +++++++ src/rtl_fm.c | 91 +++++++++++-- src/rtl_sdr.c | 32 +++-- win32-qtcreator/CMakeLists.txt | 2 + 8 files changed, 393 insertions(+), 186 deletions(-) create mode 100755 src/convenience/wavewrite.c create mode 100644 src/convenience/wavewrite.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b742752..a79fd70 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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) diff --git a/src/convenience/convenience.c b/src/convenience/convenience.c index 69e4a94..872503e 100755 --- a/src/convenience/convenience.c +++ b/src/convenience/convenience.c @@ -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 diff --git a/src/convenience/convenience.h b/src/convenience/convenience.h index 5554d0a..7d1934f 100644 --- a/src/convenience/convenience.h +++ b/src/convenience/convenience.h @@ -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 diff --git a/src/convenience/wavewrite.c b/src/convenience/wavewrite.c new file mode 100755 index 0000000..ffb2786 --- /dev/null +++ b/src/convenience/wavewrite.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2019 by Hayati Ayguen + * + * 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 . + */ + +#include "wavewrite.h" + +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#endif + +#include + +#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 diff --git a/src/convenience/wavewrite.h b/src/convenience/wavewrite.h new file mode 100644 index 0000000..86098db --- /dev/null +++ b/src/convenience/wavewrite.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 by Hayati Ayguen + * + * 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 . + */ +#ifndef __WAVEWRITE_H +#define __WAVEWRITE_H + +#include +#include + +#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*/ diff --git a/src/rtl_fm.c b/src/rtl_fm.c index e713cb8..696c113 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -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 + 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; diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index d8c63b9..cbcb410 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -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"); diff --git a/win32-qtcreator/CMakeLists.txt b/win32-qtcreator/CMakeLists.txt index cb18210..df3c4ff 100644 --- a/win32-qtcreator/CMakeLists.txt +++ b/win32-qtcreator/CMakeLists.txt @@ -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