Merge a0328e9690 into dd2859ac22
This commit is contained in:
commit
0565565af7
|
|
@ -53,7 +53,7 @@ To test stereophonic audio, you can try the file `stereo_44100.wav` provided.
|
|||
The more general syntax for running Pi-FM-RDS is as follows:
|
||||
|
||||
```
|
||||
pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code] [-ps ps_text] [-rt rt_text]
|
||||
pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code] [-ps ps_text] [-rt rt_text] [-cutoff cutoff_freq] [-preemph preemphasis_mode]
|
||||
```
|
||||
|
||||
All arguments are optional:
|
||||
|
|
@ -65,6 +65,8 @@ All arguments are optional:
|
|||
* `-rt` specifies the radiotext (RT) to be transmitted. Limit: 64 characters. Example: `-rt 'Hello, world!'`.
|
||||
* `-ctl` specifies a named pipe (FIFO) to use as a control channel to change PS and RT at run-time (see below).
|
||||
* `-ppm` specifies your Raspberry Pi's oscillator error in parts per million (ppm), see below.
|
||||
* `-cutoff` specifies the cutoff frequency (in Hz, 'compliant' for 15,000Hz or 'quality' for 22,050Hz) used by Pi-FM-RDS' internal lowpass filter. Values greater than 15000 are not compliant. Use carefully.
|
||||
* `-preemph` specifies which preemph should be used, since it differs from location. For Europe choose 'eu', for the US choose 'us'.
|
||||
|
||||
By default the PS changes back and forth between `Pi-FmRds` and a sequence number, starting at `00000000`. The PS changes around one time per second.
|
||||
|
||||
|
|
|
|||
34
src/fm_mpx.c
34
src/fm_mpx.c
|
|
@ -66,6 +66,10 @@ float fir_buffer_stereo[FIR_SIZE] = {0};
|
|||
int fir_index = 0;
|
||||
int channels;
|
||||
|
||||
float *last_buffer_val;
|
||||
float preemphasis_prewarp;
|
||||
float preemphasis_coefficient;
|
||||
|
||||
SNDFILE *inf;
|
||||
|
||||
|
||||
|
|
@ -80,7 +84,7 @@ float *alloc_empty_buffer(size_t length) {
|
|||
}
|
||||
|
||||
|
||||
int fm_mpx_open(char *filename, size_t len) {
|
||||
int fm_mpx_open(char *filename, size_t len, float cutoff_freq, float preemphasis_corner_freq) {
|
||||
length = len;
|
||||
|
||||
if(filename != NULL) {
|
||||
|
|
@ -114,13 +118,19 @@ int fm_mpx_open(char *filename, size_t len) {
|
|||
printf("%d channels, generating stereo multiplex.\n", channels);
|
||||
} else {
|
||||
printf("1 channel, monophonic operation.\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create the preemphasis
|
||||
last_buffer_val = (float*) malloc(sizeof(float)*channels);
|
||||
for(int i=0;i<channels;i++) last_buffer_val[i] = 0;
|
||||
|
||||
preemphasis_prewarp = tan(PI*preemphasis_corner_freq/in_samplerate);
|
||||
preemphasis_coefficient = (1.0 + (1.0 - preemphasis_prewarp)/(1.0 + preemphasis_prewarp))/2.0;
|
||||
printf("Created preemphasis with cutoff at %.1f Hz\n", preemphasis_corner_freq);
|
||||
|
||||
|
||||
// Create the low-pass FIR filter
|
||||
float cutoff_freq = 15000 * .8;
|
||||
if(in_samplerate/2 < cutoff_freq) cutoff_freq = in_samplerate/2 * .8;
|
||||
|
||||
if(in_samplerate/2 < cutoff_freq) cutoff_freq = in_samplerate/2;
|
||||
|
||||
|
||||
low_pass_fir[FIR_HALF_SIZE-1] = 2 * cutoff_freq / 228000 /2;
|
||||
|
|
@ -181,6 +191,18 @@ int fm_mpx_get_samples(float *mpx_buffer) {
|
|||
return -1;
|
||||
}
|
||||
} else {
|
||||
//apply preemphasis
|
||||
int k;
|
||||
int l;
|
||||
float tmp;
|
||||
for(k=0;k<audio_len;k+=channels) {
|
||||
for(l=0;l<channels;l++) {
|
||||
tmp = audio_buffer[k+l];
|
||||
audio_buffer[k+l] = audio_buffer[k+l] - preemphasis_coefficient*last_buffer_val[l];
|
||||
last_buffer_val[l] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,6 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
extern int fm_mpx_open(char *filename, size_t len);
|
||||
extern int fm_mpx_open(char *filename, size_t len, float cutoff_freq, float preemphasis_corner_freq);
|
||||
extern int fm_mpx_get_samples(float *mpx_buffer);
|
||||
extern int fm_mpx_close();
|
||||
|
|
@ -197,7 +197,6 @@
|
|||
// (broadcast radio) and about 3.5 for NBFM (walkie-talkie style radio)
|
||||
#define DEVIATION 25.0
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t info, src, dst, length,
|
||||
stride, next, pad[2];
|
||||
|
|
@ -317,7 +316,7 @@ map_peripheral(uint32_t base, uint32_t len)
|
|||
#define DATA_SIZE 5000
|
||||
|
||||
|
||||
int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, float ppm, char *control_pipe) {
|
||||
int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, float ppm, char *control_pipe, float cutoff, float preemphasis_cutoff) {
|
||||
// Catch all signals possible - it is vital we kill the DMA engine
|
||||
// on process exit!
|
||||
for (int i = 0; i < 64; i++) {
|
||||
|
|
@ -452,7 +451,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
|
|||
int data_index = 0;
|
||||
|
||||
// Initialize the baseband generator
|
||||
if(fm_mpx_open(audio_file, DATA_SIZE) < 0) return 1;
|
||||
if(fm_mpx_open(audio_file, DATA_SIZE, cutoff, preemphasis_cutoff) < 0) return 1;
|
||||
|
||||
// Initialize the RDS modulator
|
||||
char myps[9] = {0};
|
||||
|
|
@ -543,6 +542,11 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define PREEMPHASIS_EU 3185
|
||||
#define PREEMPHASIS_US 2120
|
||||
|
||||
#define CUTOFF_COMPLIANT 15000
|
||||
#define CUTOFF_QUALITY 22050
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *audio_file = NULL;
|
||||
|
|
@ -552,6 +556,8 @@ int main(int argc, char **argv) {
|
|||
char *rt = "PiFmRds: live FM-RDS transmission from the RaspberryPi";
|
||||
uint16_t pi = 0x1234;
|
||||
float ppm = 0;
|
||||
float cutoff = CUTOFF_COMPLIANT;
|
||||
float preemphasis_cutoff = PREEMPHASIS_US;
|
||||
|
||||
|
||||
// Parse command-line arguments
|
||||
|
|
@ -584,6 +590,26 @@ int main(int argc, char **argv) {
|
|||
} else if(strcmp("-ctl", arg)==0 && param != NULL) {
|
||||
i++;
|
||||
control_pipe = param;
|
||||
} else if(strcmp("-preemph", arg)==0 && param != NULL) {
|
||||
i++;
|
||||
if(strcmp("eu", param)==0) {
|
||||
preemphasis_cutoff = PREEMPHASIS_EU;
|
||||
} else if(strcmp("us", param)==0) {
|
||||
preemphasis_cutoff = PREEMPHASIS_US;
|
||||
}
|
||||
else {
|
||||
preemphasis_cutoff = atof(param);
|
||||
}
|
||||
} else if(strcmp("-cutoff", arg)==0 && param != NULL) {
|
||||
i++;
|
||||
if(strcmp("compliant", param)==0) {
|
||||
cutoff = CUTOFF_COMPLIANT;
|
||||
} else if(strcmp("quality", param)==0) {
|
||||
cutoff = CUTOFF_QUALITY;
|
||||
}
|
||||
else {
|
||||
cutoff = atof(param);
|
||||
}
|
||||
} else {
|
||||
fatal("Unrecognised argument: %s.\n"
|
||||
"Syntax: pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code]\n"
|
||||
|
|
@ -591,7 +617,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
int errcode = tx(carrier_freq, audio_file, pi, ps, rt, ppm, control_pipe);
|
||||
int errcode = tx(carrier_freq, audio_file, pi, ps, rt, ppm, control_pipe, cutoff, preemphasis_cutoff);
|
||||
|
||||
terminate(errcode);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue