diff --git a/src/Makefile b/src/Makefile
index d4f5e8f..4125d00 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,8 +4,8 @@ CFLAGS = -Wall -std=gnu99 -c -g -O2
app: rds.o waveforms.o pi_fm_rds.o
$(CC) -o pi_fm_rds rds.o waveforms.o pi_fm_rds.o -lm -lsndfile
-rds_wav: rds.o waveforms.o rds_wav.o
- $(CC) -o rds_wav rds_wav.o rds.o waveforms.o -lsndfile
+rds_wav: rds.o waveforms.o rds_wav.o fm_mpx.o
+ $(CC) -o rds_wav rds_wav.o rds.o waveforms.o fm_mpx.o -lm -lsndfile
rds.o: rds.c waveforms.h
$(CC) $(CFLAGS) rds.c
@@ -19,5 +19,8 @@ pi_fm_rds.o: pi_fm_rds.c
rds_wav.o: rds_wav.c
$(CC) $(CFLAGS) rds_wav.c
+fm_mpx.o: fm_mpx.c fm_mpx.h
+ $(CC) $(CFLAGS) fm_mpx.c
+
clean:
rm *.o
diff --git a/src/fm_mpx.c b/src/fm_mpx.c
new file mode 100644
index 0000000..7fa869c
--- /dev/null
+++ b/src/fm_mpx.c
@@ -0,0 +1,190 @@
+/*
+ PiFmRds - FM/RDS transmitter for the Raspberry Pi
+ Copyright (C) 2014 Christophe Jacquet, F8FTK
+
+ See https://github.com/ChristopheJacquet/PiFmRds
+
+ rds_wav.c is a test program that writes a RDS baseband signal to a WAV
+ file. It requires libsndfile.
+
+ 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 3 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
+#include
+#include
+
+#include "rds.h"
+
+
+#define PI 3.141592654
+
+
+#define FIR_HALF_SIZE 30
+#define FIR_SIZE (2*FIR_HALF_SIZE-1)
+
+#define LENGTH 114000
+// TODO: remove constant
+
+// coefficients of the low-pass FIR filter
+float low_pass_fir[FIR_HALF_SIZE];
+
+
+float carrier_38[] = {0.0, 0.8660254037844386, 0.8660254037844388, 1.2246467991473532e-16, -0.8660254037844384, -0.8660254037844386};
+
+float carrier_19[] = {0.0, 0.5, 0.8660254037844386, 1.0, 0.8660254037844388, 0.5, 1.2246467991473532e-16, -0.5, -0.8660254037844384, -1.0, -0.8660254037844386, -0.5};
+
+int phase_38 = 0;
+int phase_19 = 0;
+
+
+float downsample_factor;
+
+
+float rds_buffer[LENGTH] = {0};
+float audio_buffer[LENGTH] = {0};
+int audio_index = 0;
+int audio_len = 0;
+float audio_pos;
+float out = 0;
+float alpha = .03;
+
+float fir_buffer[FIR_SIZE] = {0};
+int fir_index = 0;
+
+SNDFILE *inf;
+
+
+
+
+int fm_mpx_open(char *filename) {
+ // Open the input file
+ SF_INFO sfinfo;
+ if(! (inf = sf_open(filename, SFM_READ, &sfinfo))) {
+ fprintf(stderr, "Error: could not open input file %s.\n", filename) ;
+ return EXIT_FAILURE; // TODO better error code
+ }
+
+ int in_samplerate = sfinfo.samplerate;
+ downsample_factor = 228000. / in_samplerate;
+
+ printf("Input: %d Hz, upsampling factor: %.2f\n", in_samplerate, downsample_factor);
+
+
+ // Create the low-pass FIR filter
+ float cutoff_freq = 15000 * .8;
+ if(in_samplerate/2 < cutoff_freq) cutoff_freq = in_samplerate/2 * .8;
+
+
+
+ low_pass_fir[FIR_HALF_SIZE-1] = 2 * cutoff_freq / 228000 /2;
+ // Here we divide this coefficient by two because it will be counted twice
+ // when applying the filter
+
+ // Only store half of the filter since it is symmetric
+ for(int i=1; i= downsample_factor) {
+ audio_pos -= downsample_factor;
+
+ if(audio_len == 0) {
+ for(int j=0; j<2; j++) { // one retry
+ audio_len = sf_read_float(inf, audio_buffer, LENGTH);
+ if (audio_len < 0) {
+ fprintf(stderr, "Error reading audio\n");
+ exit(EXIT_FAILURE);
+ }
+ if(audio_len == 0) {
+ sf_seek(inf, 0, SEEK_SET);
+ } else {
+ break;
+ }
+ }
+ audio_index = 0;
+ } else {
+ audio_index++;
+ audio_len--;
+ }
+ }
+
+ // Apply FIR low-pass filter
+ fir_buffer[fir_index] = audio_buffer[audio_index];
+ fir_index++;
+ if(fir_index >= FIR_SIZE) fir_index = 0;
+
+
+ /* As the FIR filter is symmetric, we do not multiply all
+ the coefficients independently, but two-by-two, thus reducing
+ the total number of multiplications by a factor of two
+ */
+ out = 0;
+ int ifbi = fir_index; // ifbi = increasing FIR Buffer Index
+ int dfbi = fir_index; // dfbi = decreasing FIR Buffer Index
+ for(int fi=0; fi= FIR_SIZE) ifbi = 0;
+ }
+ // End of FIR filter
+
+
+ mpx_buffer[i] = (rds_buffer[i] +
+ 4*out /* +
+ 2 * carrier_38[phase_38] * out +
+ .1*carrier_19[phase_19]*/) / 10;
+
+ phase_19++;
+ phase_38++;
+ if(phase_19 >= 12) phase_19 = 0;
+ if(phase_38 >= 6) phase_38 = 0;
+
+ audio_pos++;
+
+ }
+
+ return 0; // TODO
+}
+
+
+int fm_mpx_close() {
+ if(sf_close(inf) ) {
+ fprintf(stderr, "Error closing audio file");
+ }
+ return 0; // TODO
+}
\ No newline at end of file
diff --git a/src/fm_mpx.h b/src/fm_mpx.h
new file mode 100644
index 0000000..c1cc120
--- /dev/null
+++ b/src/fm_mpx.h
@@ -0,0 +1,26 @@
+/*
+ PiFmRds - FM/RDS transmitter for the Raspberry Pi
+ Copyright (C) 2014 Christophe Jacquet, F8FTK
+
+ See https://github.com/ChristopheJacquet/PiFmRds
+
+ rds_wav.c is a test program that writes a RDS baseband signal to a WAV
+ file. It requires libsndfile.
+
+ 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 3 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 .
+*/
+
+extern int fm_mpx_open(char *filename);
+extern int fm_mpx_get_samples(float *mpx_buffer);
+extern int fm_mpx_close();
\ No newline at end of file
diff --git a/src/noise_22050.wav b/src/noise_22050.wav
new file mode 100644
index 0000000..5fb079a
Binary files /dev/null and b/src/noise_22050.wav differ
diff --git a/src/rds.h b/src/rds.h
index 9a2aebc..fa839ef 100644
--- a/src/rds.h
+++ b/src/rds.h
@@ -18,6 +18,9 @@
along with this program. If not, see .
*/
+#ifndef RDS_H
+#define RDS_H
+
#include
@@ -25,3 +28,6 @@ extern void get_rds_samples(float *buffer, int count);
extern void set_rds_pi(uint16_t pi_code);
extern void set_rds_rt(char *rt);
extern void set_rds_ps(char *ps);
+
+
+#endif /* RDS_H */
\ No newline at end of file
diff --git a/src/rds_wav.c b/src/rds_wav.c
index 190b35d..f46ef9a 100644
--- a/src/rds_wav.c
+++ b/src/rds_wav.c
@@ -24,12 +24,16 @@
#include
#include
+#include
#include
#include "rds.h"
+#include "fm_mpx.h"
+
#define LENGTH 114000
+
/* Simple test program */
int main(int argc, char **argv) {
if(argc < 3) {
@@ -42,11 +46,14 @@ int main(int argc, char **argv) {
set_rds_ps(argv[2]);
set_rds_rt(argv[2]);
- float buffer[LENGTH];
+ fm_mpx_open("sound_22050.wav");
+
+
// Set the format of the output file
SNDFILE *outf;
SF_INFO sfinfo;
+
sfinfo.frames = LENGTH;
sfinfo.samplerate = 228000;
sfinfo.channels = 1;
@@ -60,11 +67,12 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
+ float mpx_buffer[LENGTH];
for(int j=0; j<40; j++) {
- get_rds_samples(buffer, LENGTH);
+ fm_mpx_get_samples(mpx_buffer);
- if(sf_write_float(outf, buffer, LENGTH) != LENGTH) {
+ if(sf_write_float(outf, mpx_buffer, LENGTH) != LENGTH) {
fprintf(stderr, "Error: writing to file %s.\n", argv[1]);
return EXIT_FAILURE;
}
@@ -74,5 +82,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error: closing file %s.\n", argv[1]);
}
+ fm_mpx_close();
+
return EXIT_SUCCESS;
}
\ No newline at end of file
diff --git a/src/sound_22050.wav b/src/sound_22050.wav
new file mode 100644
index 0000000..f261265
Binary files /dev/null and b/src/sound_22050.wav differ