waterfall optimize, fm demod audio filtering
Moved waterfall increment into rendering to reduce audio processing impact. Added another test filter and resample stage to FM demod experiment to clean up audio and remove high pitch on stereo channels until it can be demodulated.
This commit is contained in:
parent
86dadb8f2c
commit
810533750f
|
@ -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<signed char> *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<float> *newBuffer = new std::vector<float>;
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -95,12 +95,25 @@ PrimaryGLContext::PrimaryGLContext(wxGLCanvas *canvas) :
|
|||
CheckGLError();
|
||||
}
|
||||
|
||||
void PrimaryGLContext::Plot(std::vector<float> &points, std::vector<float> &points2, unsigned char *waterfall_tex) {
|
||||
void PrimaryGLContext::Plot(std::vector<float> &points, std::vector<float> &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<float> &points, std::vector<float> &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<signed char> *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;
|
||||
}
|
||||
|
|
|
@ -18,13 +18,14 @@ class PrimaryGLContext: public wxGLContext {
|
|||
public:
|
||||
PrimaryGLContext(wxGLCanvas *canvas);
|
||||
|
||||
void Plot(std::vector<float> &points, std::vector<float> &points2, unsigned char *waterfall_tex);
|
||||
void Plot(std::vector<float> &points, std::vector<float> &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<float> fft_result_ma;
|
||||
std::vector<float> fft_result_maa;
|
||||
|
||||
|
||||
unsigned char waterfall_tex[FFT_SIZE * NUM_WATERFALL_LINES];
|
||||
|
||||
|
||||
Demodulator test_demod;
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue