我一直在使用RTLSDR,特别是rtl_fm,为Raspberry Pi开发一个项目。源代码为here。通常,rtl_fm的使用是rtl_fm -M wbfm -f
。要寻找,您需要通过发送中断来结束该过程,然后以新频率再次运行它。为了避免这种情况,并且还允许它接受套接字命令(例如SEEK_UP等),我决定修改rtl_fm,并使用ALSA直接播放声音。 <frequency in hertz>
| aplay -r 32000 -f S16_LE -c 1
但我会说实话,我的音频编程技巧仅限于这个项目。我设法让它播放音频,但它不断口吃。 afaik,它不是由欠载引起的(我没有得到-EPIPE错误),并且相同的代码减去我的修改在管道播放时工作正常。
通常,它通过以下方式将音频输出到STDOUT:
rtl_fm.c
<frequency in hertz>
我把它修改为:
rtl_fm_player.c
pthread_rwlock_rdlock(&s->rw);
fwrite(s->result, 2, s->result_len, s->file);
pthread_rwlock_unlock(&s->rw);
根据以下设置播放器(为简洁起见,省略了错误检查):
rtl_fm_player.c
pthread_rwlock_rdlock(&s->rw);
if ((p->pcm_error = snd_pcm_writei(p->pcm_handle, s->result, s->result_len)) == -EPIPE)
{
snd_pcm_prepare(p->pcm_handle);
}
else if (p->pcm_error < 0)
{
printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(p->pcm_error));
}
pthread_rwlock_unlock(&s->rw);
播放器状态是存储速率,通道,output_size等的结构.rate = 32000,channels = 1.当前output_size未使用。
完整代码在这里,如果这有助于https://bitbucket.org/ab6393/rtl_fm-player。
如果这也有帮助,当rtl_fm被传送给它时,详细记录aplay,假设我错过了设置一些hw参数。
void player_setup(struct player_state * o)
{
snd_pcm_hw_params_t *params;
/* Open the PCM device in playback mode */
o->pcm_error = snd_pcm_open(&(o->pcm_handle), PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)
/* Allocate parameters object and fill it with default values*/
//alloca puts params on the stack, no need to free it.
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(o->pcm_handle, params);
/* Update relevant parameters to new values */
//interleaved
o->pcm_error = snd_pcm_hw_params_set_access(o->pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)
//16 bit little endian raw data
o->pcm_error = snd_pcm_hw_params_set_format(o->pcm_handle, params, SND_PCM_FORMAT_S16_LE)
//channels
o->pcm_error = snd_pcm_hw_params_set_channels(o->pcm_handle, params, o->channels)
//sample rate
o->pcm_error = snd_pcm_hw_params_set_rate_near(o->pcm_handle, params, &(o->rate), 0)
/* Write parameters to pcm_handler */
o->pcm_error = snd_pcm_hw_params(o->pcm_handle, params)
//snd_pcm_hw_params_get_buffer_size(params, &(o->bufferSize));
fifo_init(o->fifo, o->output_size * 8);
o->setup = true;
}
据我所知,该设置与运行aplay相同,但结果不同。如果有人能告诉我我搞砸了什么,那就非常感激了。