diff --git a/src/Demodulator.cpp b/src/Demodulator.cpp index 792a2f0..3927d2c 100644 --- a/src/Demodulator.cpp +++ b/src/Demodulator.cpp @@ -41,10 +41,12 @@ static int patestCallback(const void *inputBuffer, void *outputBuffer, unsigned Demodulator::Demodulator() { - bandwidth = 800000; + bandwidth = 300000; resample_ratio = (float) (bandwidth) / (float) SRATE; - audio_frequency = 44100; - audio_resample_ratio = (float) (audio_frequency) / (float) bandwidth; + wbfm_frequency = 32000; + wbfm_resample_ratio = (float) (wbfm_frequency) / (float) bandwidth; + audio_frequency = 48000; + audio_resample_ratio = (float) (audio_frequency) / (float) wbfm_frequency; PaError err; err = Pa_Initialize(); @@ -83,7 +85,7 @@ Demodulator::Demodulator() { stream = NULL; - err = Pa_OpenStream(&stream, NULL, &outputParameters, 44100, 256, paClipOff, &patestCallback, this); + err = Pa_OpenStream(&stream, NULL, &outputParameters, audio_frequency, 256, paClipOff, &patestCallback, this); err = Pa_StartStream(stream); if (err != paNoError) { @@ -103,14 +105,22 @@ Demodulator::Demodulator() { fir_filter = firfilt_crcf_create(h, h_len); + h_len = estimate_req_filter_len(ft, As); + liquid_firdes_kaiser(h_len, 0.3f, As, mu, h); + + fir_audio_filter = firfilt_crcf_create(h, h_len); + // create multi-stage arbitrary resampler object resampler = msresamp_crcf_create(resample_ratio, As); msresamp_crcf_print(resampler); + wbfm_resampler = msresamp_crcf_create(wbfm_resample_ratio, As); + msresamp_crcf_print(wbfm_resampler); + audio_resampler = msresamp_crcf_create(audio_resample_ratio, As); msresamp_crcf_print(audio_resampler); - float kf = 0.1f; // modulation factor + float kf = 0.5f; // modulation factor fdem = freqdem_create(kf); freqdem_print(fdem); @@ -166,17 +176,32 @@ void Demodulator::writeBuffer(std::vector *data) { } } - int audio_out_size = ceil((float) (num_written) * audio_resample_ratio); + + int wbfm_out_size = ceil((float) (num_written) * wbfm_resample_ratio); + liquid_float_complex resampled_wbfm_output[wbfm_out_size]; + + unsigned int num_wbfm_written; + msresamp_crcf_execute(wbfm_resampler, resampled_output, num_written, resampled_wbfm_output, &num_wbfm_written); + + + for (int i = 0; i < num_wbfm_written; i++) { + firfilt_crcf_push(fir_audio_filter, resampled_wbfm_output[i]); + firfilt_crcf_execute(fir_audio_filter, &resampled_wbfm_output[i]); + } + + int audio_out_size = ceil((float) (num_wbfm_written) * audio_resample_ratio); liquid_float_complex resampled_audio_output[audio_out_size]; - unsigned int num_audio_written; // number of values written to buffer - msresamp_crcf_execute(audio_resampler, resampled_output, num_written, resampled_audio_output, &num_audio_written); + unsigned int num_audio_written; + msresamp_crcf_execute(audio_resampler, resampled_wbfm_output, num_wbfm_written, resampled_audio_output, &num_audio_written); std::vector *newBuffer = new std::vector; newBuffer->resize(num_audio_written * 2); for (int i = 0; i < num_audio_written; i++) { - (*newBuffer)[i * 2] = resampled_audio_output[i].real; - (*newBuffer)[i * 2 + 1] = resampled_audio_output[i].real; + liquid_float_complex y = resampled_audio_output[i]; + + (*newBuffer)[i * 2] = y.real; + (*newBuffer)[i * 2 + 1] = y.real; } audio_queue.push(newBuffer); diff --git a/src/Demodulator.h b/src/Demodulator.h index 6d085c4..cbf483e 100644 --- a/src/Demodulator.h +++ b/src/Demodulator.h @@ -31,14 +31,22 @@ public: private: firfilt_crcf fir_filter; + firfilt_crcf fir_audio_filter; + + unsigned int bandwidth; msresamp_crcf resampler; - msresamp_crcf audio_resampler; float resample_ratio; - unsigned int bandwidth; - unsigned int audio_frequency; + + msresamp_crcf wbfm_resampler; + float wbfm_resample_ratio; + unsigned int wbfm_frequency; + + msresamp_crcf audio_resampler; float audio_resample_ratio; + unsigned int audio_frequency; + PaStreamParameters outputParameters; PaStream *stream; freqdem fdem; diff --git a/src/PrimaryGLContext.cpp b/src/PrimaryGLContext.cpp index 8ffa11b..a2f55fe 100644 --- a/src/PrimaryGLContext.cpp +++ b/src/PrimaryGLContext.cpp @@ -95,12 +95,25 @@ PrimaryGLContext::PrimaryGLContext(wxGLCanvas *canvas) : CheckGLError(); } -void PrimaryGLContext::Plot(std::vector &points, std::vector &points2, unsigned char *waterfall_tex) { +void PrimaryGLContext::Plot(std::vector &points, std::vector &points2) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + if (points.size()) { + memmove(waterfall_tex + FFT_SIZE, waterfall_tex, (NUM_WATERFALL_LINES - 1) * FFT_SIZE); + + for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) { + float v = points[i*2+1]; + + float wv = v; + if (wv<0.0) wv = 0.0; + if (wv>1.0) wv = 1.0; + waterfall_tex[i] = (unsigned char) floor(wv * 255.0); + } + } + glBindTexture(GL_TEXTURE_2D, waterfall); // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, FFT_SIZE, NUM_WATERFALL_LINES, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, waterfall_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, FFT_SIZE, NUM_WATERFALL_LINES, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *) waterfall_tex); @@ -132,6 +145,7 @@ void PrimaryGLContext::Plot(std::vector &points, std::vector &poin glPopMatrix(); } + glEnable(GL_TEXTURE_2D); // glEnable(GL_COLOR_TABLE); glBindTexture(GL_TEXTURE_2D, waterfall); @@ -184,7 +198,7 @@ void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { PrimaryGLContext& canvas = wxGetApp().GetContext(this); glViewport(0, 0, ClientSize.x, ClientSize.y); - canvas.Plot(spectrum_points, test_demod.waveform_points, waterfall_tex); + canvas.Plot(spectrum_points, test_demod.waveform_points); SwapBuffers(); } @@ -281,16 +295,8 @@ void TestGLCanvas::setData(std::vector *data) { // fftw_execute(plan[1]); - memmove(waterfall_tex + FFT_SIZE, waterfall_tex, (NUM_WATERFALL_LINES - 1) * FFT_SIZE); - for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) { float v = log10(fft_result_maa[i]) / log10(fft_ceil_maa); - - float wv = v; - if (wv<0.0) wv = 0.0; - if (wv>1.0) wv = 1.0; - waterfall_tex[i] = (unsigned char) floor(wv * 255.0); - spectrum_points[i * 2] = ((float) i / (float) iMax); spectrum_points[i * 2 + 1] = v; } diff --git a/src/PrimaryGLContext.h b/src/PrimaryGLContext.h index 8e0aac0..813c459 100644 --- a/src/PrimaryGLContext.h +++ b/src/PrimaryGLContext.h @@ -18,13 +18,14 @@ class PrimaryGLContext: public wxGLContext { public: PrimaryGLContext(wxGLCanvas *canvas); - void Plot(std::vector &points, std::vector &points2, unsigned char *waterfall_tex); + void Plot(std::vector &points, std::vector &points2); private: Gradient grad; GLuint waterfall; + unsigned char waterfall_tex[FFT_SIZE * NUM_WATERFALL_LINES]; }; class TestGLCanvas: public wxGLCanvas { @@ -52,10 +53,6 @@ private: std::vector fft_result_ma; std::vector fft_result_maa; - - unsigned char waterfall_tex[FFT_SIZE * NUM_WATERFALL_LINES]; - - Demodulator test_demod; wxDECLARE_EVENT_TABLE(); };