void NarrowbandFMAudio::execute(buffer_c8_t buffer) { /* Called every 2048/3072000 second -- 1500Hz. */ auto decimator_out = decimator.execute(buffer); const buffer_c16_t work_baseband_buffer { (complex16_t*)decimator_out.p, sizeof(*decimator_out.p) * decimator_out.count }; /* 96kHz complex<int16_t>[64] * -> FIR filter, <6kHz (0.063fs) pass, gain 1.0 * -> 48kHz int16_t[32] */ auto channel = channel_filter.execute(decimator_out, work_baseband_buffer); // TODO: Feed channel_stats post-decimation data? feed_channel_stats(channel); feed_channel_spectrum( channel, decimator_out.sampling_rate * channel_filter_taps.pass_frequency_normalized, decimator_out.sampling_rate * channel_filter_taps.stop_frequency_normalized ); const buffer_s16_t work_audio_buffer { (int16_t*)decimator_out.p, sizeof(*decimator_out.p) * decimator_out.count }; /* 48kHz complex<int16_t>[32] * -> FM demodulation * -> 48kHz int16_t[32] */ auto audio = demod.execute(channel, work_audio_buffer); static uint64_t audio_present_history = 0; const auto audio_present_now = squelch.execute(audio); audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); const bool audio_present = (audio_present_history != 0); if( !audio_present ) { // Zero audio buffer. for(size_t i=0; i<audio.count; i++) { audio.p[i] = 0; } } audio_hpf.execute_in_place(audio); fill_audio_buffer(audio); }
void AudioOutput::on_block( const buffer_f32_t& audio ) { const auto audio_present_now = squelch.execute(audio); hpf.execute_in_place(audio); deemph.execute_in_place(audio); audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); const bool audio_present = (audio_present_history != 0); if( !audio_present ) { for(size_t i=0; i<audio.count; i++) { audio.p[i] = 0; } } fill_audio_buffer(audio, audio_present); }
/*--------------------------- sound callback ------------------------------*/ int record_sound ( const void *inputBuffer, unsigned long numSamples, void *userData ) { struct paRecordData *pdata = (struct paRecordData*)userData; __LOCK_MUTEX( __AMUTEX ); gboolean capVid = pdata->capVid; int channels = pdata->channels; int skip_n = pdata->skip_n; __UNLOCK_MUTEX( __AMUTEX ); const SAMPLE *rptr = (const SAMPLE*) inputBuffer; int i; UINT64 numFrames = numSamples / channels; /* buffer ends at timestamp "now", calculate beginning timestamp */ UINT64 nsec_per_frame = G_NSEC_PER_SEC / pdata->samprate; UINT64 ts = ns_time_monotonic() - numFrames * nsec_per_frame; if (skip_n > 0) /*skip audio while were skipping video frames*/ { if(capVid) { __LOCK_MUTEX( __AMUTEX ); pdata->snd_begintime = ns_time_monotonic(); /*reset first time stamp*/ __UNLOCK_MUTEX( __AMUTEX ); return (0); /*still capturing*/ } else { __LOCK_MUTEX( __AMUTEX ); pdata->streaming=FALSE; __LOCK_MUTEX( __AMUTEX ); return (-1); /*capture has stopped*/ } } // __LOCK_MUTEX( __AMUTEX ); // pdata->streaming=TRUE; // __UNLOCK_MUTEX( __AMUTEX ); for( i=0; i<numSamples; i++ ) { pdata->recordedSamples[pdata->sampleIndex] = inputBuffer ? *rptr++ : 0; pdata->sampleIndex++; fill_audio_buffer(pdata, ts); /* increment timestamp accordingly while copying */ if (i % channels == 0) ts += nsec_per_frame; } if(capVid) return (0); /*still capturing*/ else { __LOCK_MUTEX( __AMUTEX ); pdata->streaming=FALSE; /* mark current buffer as ready to process */ pdata->audio_buff_flag[pdata->bw_ind] = AUD_PROCESS; __UNLOCK_MUTEX( __AMUTEX ); } return(-1); /* audio capture stopped*/ }