diff --git a/src/CubicSDRDefs.h b/src/CubicSDRDefs.h index c61a23d..ed1593c 100644 --- a/src/CubicSDRDefs.h +++ b/src/CubicSDRDefs.h @@ -1,8 +1,8 @@ #pragma once -#define BUF_SIZE (16 * 32 * 128) +#define BUF_SIZE (16 * 32 * 256) #define SRATE 2500000 -#define FFT_SIZE BUF_SIZE / 2 +#define FFT_SIZE 8192 #define DEFAULT_FREQ 107500000 diff --git a/src/Demodulate.h b/src/Demodulate.h index 2a5b8b3..e38cd5e 100644 --- a/src/Demodulate.h +++ b/src/Demodulate.h @@ -48,6 +48,7 @@ void multiply(int ar, int aj, int br, int bj, int *cr, int *cj); int polar_discriminant(int ar, int aj, int br, int bj); int fast_atan2(int y, int x); int polar_disc_fast(int ar, int aj, int br, int bj); +int polar_disc_lut(int ar, int aj, int br, int bj); class Demodulate { diff --git a/src/PrimaryGLContext.cpp b/src/PrimaryGLContext.cpp index c6c1915..47f967f 100644 --- a/src/PrimaryGLContext.cpp +++ b/src/PrimaryGLContext.cpp @@ -108,6 +108,13 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) : wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE), parent(parent) { + + frequency = 170000; + resample_ratio = (float) frequency / (float) SRATE; + audio_frequency = 44000; + audio_resample_ratio = (float) audio_frequency / (float) frequency; + + int in_block_size = BUF_SIZE / 2; int out_block_size = FFT_SIZE; @@ -141,7 +148,7 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) : format = AL_FORMAT_MONO16; for (int i = 0; i < AL_NUM_BUFFERS; i++) { - alBufferData(buffers[i], format, buffer_init, AL_BUFFER_SIZE, demod.output.rate); + alBufferData(buffers[i], format, buffer_init, AL_BUFFER_SIZE, audio_frequency); } if (alGetError() != AL_NO_ERROR) { std::cout << "Error priming :(\n"; @@ -175,7 +182,7 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) : firdespm_run(n, num_bands, bands, des, weights, wtype, btype, h); */ - float fc = 0.5f * (170000 / SRATE); // filter cutoff frequency + float fc = 0.5f * (frequency / SRATE); // filter cutoff frequency float ft = 0.05f; // filter transition float As = 60.0f; // stop-band attenuation [dB] float mu = 0.0f; // fractional timing offset @@ -191,6 +198,23 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) : float slsl = 60.0f; // filter sidelobe suppression level fir_hil = firhilbf_create(m, slsl); + + + // create multi-stage arbitrary resampler object + resampler = msresamp_crcf_create(resample_ratio, As); + msresamp_crcf_print(resampler); + + + + + audio_resampler = msresamp_crcf_create(audio_resample_ratio, As); + msresamp_crcf_print(audio_resampler); + + + float kf = 0.2f; // modulation factor + + fdem = freqdem_create(kf); + freqdem_print(fdem); } TestGLCanvas::~TestGLCanvas() { @@ -219,12 +243,12 @@ void TestGLCanvas::OnKeyDown(wxKeyEvent& event) { switch (event.GetKeyCode()) { case WXK_RIGHT: freq = ((AppFrame*) parent)->getFrequency(); - freq += 100000; + freq += 10000; ((AppFrame*) parent)->setFrequency(freq); break; case WXK_LEFT: freq = ((AppFrame*) parent)->getFrequency(); - freq -= 100000; + freq -= 10000; ((AppFrame*) parent)->setFrequency(freq); break; case WXK_DOWN: @@ -239,8 +263,6 @@ void TestGLCanvas::OnKeyDown(wxKeyEvent& event) { } } - - void multiply2(float ar, float aj, float br, float bj, float *cr, float *cj) { *cr = ar * br - aj * bj; *cj = aj * br + ar * bj; @@ -321,22 +343,33 @@ void TestGLCanvas::setData(std::vector *data) { spectrum_points.resize(FFT_SIZE * 2); } + fftw_execute(plan[0]); + + + liquid_float_complex filtered_input[BUF_SIZE / 2]; + for (int i = 0; i < BUF_SIZE / 2; i++) { liquid_float_complex x; liquid_float_complex y; - x.real = (1 << 8) * (float) (*data)[i * 2] / 127.0f; - x.imag = (1 << 8) * (float) (*data)[i * 2 + 1] / 127.0f; + x.real = (float) (*data)[i * 2] / 127.0f; + x.imag = (float) (*data)[i * 2 + 1] / 127.0f; firfilt_crcf_push(fir_filter, x); // push input sample firfilt_crcf_execute(fir_filter, &y); // compute output - in[i][0] = y.real; - in[i][1] = y.imag; + filtered_input[i] = y; + in[i][0] = x.real; + in[i][1] = x.imag; } - fftw_execute(plan[0]); + int out_size = ceil((float) (BUF_SIZE / 2) * resample_ratio); + + liquid_float_complex resampled_output[out_size]; + + unsigned int num_written; // number of values written to buffer + msresamp_crcf_execute(resampler, filtered_input, (BUF_SIZE / 2), resampled_output, &num_written); double fft_ceil = 0; // fft_floor, @@ -347,13 +380,6 @@ void TestGLCanvas::setData(std::vector *data) { fft_result_maa.resize(FFT_SIZE); } - // for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) { - // if (i>FFT_SIZE/4 && i < FFT_SIZE-FFT_SIZE/4) { - // out[0][i][0] = 0; - // out[0][i][1] = 0; - // } - // } - for (int j = 0; j < 2; j++) { for (int i = 0, iMax = FFT_SIZE / 2; i < iMax; i++) { double a = out[0][i][0]; @@ -364,8 +390,8 @@ void TestGLCanvas::setData(std::vector *data) { double y = out[0][FFT_SIZE / 2 + i][1]; double z = sqrt(x * x + y * y); - fft_result[i] = log10(z); - fft_result[FFT_SIZE / 2 + i] = log10(c); + fft_result[i] = (z); + fft_result[FFT_SIZE / 2 + i] = (c); } } @@ -392,8 +418,8 @@ void TestGLCanvas::setData(std::vector *data) { float waveform_ceil = 0, waveform_floor = 0; - std::vector output_buffer; - output_buffer.resize(BUF_SIZE / 2); +// std::vector output_buffer; +// output_buffer.resize(num_written); // for (int i = 0, iMax = BUF_SIZE / 2; i < iMax; i++) { // liquid_float_complex x; @@ -409,61 +435,94 @@ void TestGLCanvas::setData(std::vector *data) { // } // } - if (waveform_points.size() < BUF_SIZE) { - waveform_points.resize(BUF_SIZE); - } - - int i; + int i; float pcm = 0; float pr = pre_r; float pj = pre_j; - - // std::cout << (in[i][0]) << std::endl; - - for (i = 0; i < BUF_SIZE / 2; i++) { -// liquid_float_complex x; -// x.real = in[i][0]; -// x.imag = in[i][1]; -// float y[2]; -// -// firhilbf_interp_execute(fir_hil, x, y); -// y[0] *= 10000.0; -// y[1] *= 1000.0; - // pcm = polar_disc_fast((int)(in[i][0]*32000.0), (int)(in[i][1]*32000.0), pr, pj); - pcm = polar_discriminant2(in[i][0],in[i][1], pr, pj); + for (i = 0; i < num_written; i++) { + freqdem_demodulate(fdem, resampled_output[i], &pcm); - pr = in[i][0]; - pj = in[i][1]; + resampled_output[i].real = (float) pcm/2.0; + resampled_output[i].imag = 0; - output_buffer[i] = (float)pcm + droop_ofs_maa; - - if (waveform_ceil < output_buffer[i]) { - waveform_ceil = output_buffer[i]; + if (waveform_ceil < resampled_output[i].real) { + waveform_ceil = resampled_output[i].real; } - - if (waveform_floor > output_buffer[i]) { - waveform_floor = output_buffer[i]; + + if (waveform_floor > resampled_output[i].real) { + waveform_floor = resampled_output[i].real; } } - - droop_ofs = -(waveform_ceil+waveform_floor)/2.0; - droop_ofs_ma = droop_ofs_ma + (droop_ofs-droop_ofs_ma)*0.01; - droop_ofs_maa = droop_ofs_maa + (droop_ofs_ma-droop_ofs_maa)*0.01; - - // std::cout << "pr: " << pre_r << std::endl; - // std::cout << "pj: " << pre_j << std::endl; - - // std::cout << "do:" << droop_ofs_maa << std::endl; - + + droop_ofs = -(waveform_ceil + waveform_floor) / 2.0; + droop_ofs_ma = droop_ofs_ma + (droop_ofs - droop_ofs_ma) * 0.01; + droop_ofs_maa = droop_ofs_maa + (droop_ofs_ma - droop_ofs_maa) * 0.01; + pre_r = pr; pre_j = pj; - for (int i = 0, iMax = BUF_SIZE / 2; i < iMax; i++) { - waveform_points[i * 2 + 1] = output_buffer[i]*2.0; + + int audio_out_size = ceil((float) (num_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); + + + if (waveform_points.size() != num_audio_written * 2) { + waveform_points.resize(num_audio_written * 2); + } + + for (int i = 0, iMax = waveform_points.size() / 2; i < iMax; i++) { + waveform_points[i * 2 + 1] = resampled_audio_output[i].real * 0.5f; waveform_points[i * 2] = ((double) i / (double) iMax); } +// std::cout << num_audio_written << std::endl; + + + + + ALint val; + ALuint buffer; + + alGetSourcei(source, AL_SOURCE_STATE, &val); + if (val != AL_PLAYING) { + alSourcePlay(source); + } + + // std::cout << "buffer: " << demod.output_target->len << "@" << frequency << std::endl; + std::vector *newBuffer = new std::vector; + newBuffer->resize(num_audio_written); + for (int i = 0; i < num_audio_written; i++) { + (*newBuffer)[i] = resampled_audio_output[i].real*32767.0; + } + + audio_queue.push(newBuffer); + + while (audio_queue.size() > 8) { + alGetSourcei(source, AL_BUFFERS_PROCESSED, &val); + if (val <= 0) { + break; + } + + std::vector *nextBuffer = audio_queue.front(); + + alSourceUnqueueBuffers(source, 1, &buffer); + alBufferData(buffer, format, &(*nextBuffer)[0], nextBuffer->size() * 2, audio_frequency); + alSourceQueueBuffers(source, 1, &buffer); + + audio_queue.pop(); + + delete nextBuffer; + + if (alGetError() != AL_NO_ERROR) { + std::cout << "Error buffering :(\n"; + } + } } } diff --git a/src/PrimaryGLContext.h b/src/PrimaryGLContext.h index e3a7957..23f79d0 100644 --- a/src/PrimaryGLContext.h +++ b/src/PrimaryGLContext.h @@ -22,7 +22,7 @@ #endif #define AL_NUM_BUFFERS 16 -#define AL_BUFFER_SIZE 4096 +#define AL_BUFFER_SIZE 2048 class PrimaryGLContext: public wxGLContext { public: @@ -63,13 +63,20 @@ private: float pre_j; float droop_ofs, droop_ofs_ma, droop_ofs_maa; + msresamp_crcf resampler; + msresamp_crcf audio_resampler; + float resample_ratio; + + + freqdem fdem; + float fft_ceil_ma, fft_ceil_maa; std::vector fft_result; std::vector fft_result_ma; std::vector fft_result_maa; - std::queue< std::vector * > audio_queue; + std::queue< std::vector * > audio_queue; Demodulate demod; @@ -78,6 +85,8 @@ private: ALuint source, buffers[AL_NUM_BUFFERS]; ALuint frequency; + ALuint audio_frequency; + float audio_resample_ratio; ALenum format; wxDECLARE_EVENT_TABLE();