int mtype::get_meat_chunks_count() const { const float ch = to_gram( weight ) * ( 0.40f - 0.02f * log10f( to_gram( weight ) ) ); const itype *chunk = item::find_type( get_meat_itype() ); return static_cast<int>( ch / to_gram( chunk->weight ) ); }
void AudioInput::encodeAudioFrame() { int iArg; ClientPlayer *p=ClientPlayer::get(g.uiSession); int i; float sum; short max; short *psSource; iFrameCounter++; if (! bRunning) { return; } sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psMic[i] * psMic[i]); dPeakMic=20.0f*log10f(sqrtf(sum / static_cast<float>(iFrameSize)) / 32768.0f); if (dPeakMic < -96.0f) dPeakMic = -96.0f; max = 1; for (i=0;i<iFrameSize;i++) max = static_cast<short>(abs(psMic[i]) > max ? abs(psMic[i]) : max); dMaxMic = max; if (g.bEchoTest) { STACKVAR(float, fft, iFrameSize); STACKVAR(float, power, iFrameSize); float scale = 1.f / static_cast<float>(iFrameSize); for (i=0;i<iFrameSize;i++) fft[i] = static_cast<float>(psMic[i]) * scale; mumble_drft_forward(&fftTable, fft); float mp = 0.0f; int bin = 0; power[0]=power[1]=0.0f; for (i=2;i < iFrameSize / 2;i++) { power[i] = sqrtf(fft[2*i]*fft[2*i]+fft[2*i-1]*fft[2*i-1]); if (power[i] > mp) { bin = i; mp = power[i]; } } for (i=2;i< iFrameSize / 2;i++) { if (power[i] * 2 > mp) { if (i != bin) bin = 0; } } iBestBin = bin * 2; } if (iEchoChannels > 0) { sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psSpeaker[i] * psSpeaker[i]); dPeakSpeaker=20.0f*log10f(sqrtf(sum / static_cast<float>(iFrameSize)) / 32768.0f); if (dPeakSpeaker < -96.0f) dPeakSpeaker = -96.0f; } else { dPeakSpeaker = 0.0; } QMutexLocker l(&qmSpeex); if (bResetProcessor) { if (sppPreprocess) speex_preprocess_state_destroy(sppPreprocess); if (sesEcho) speex_echo_state_destroy(sesEcho); sppPreprocess = speex_preprocess_state_init(iFrameSize, SAMPLE_RATE); iArg = 1; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_VAD, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_DENOISE, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_DEREVERB, &iArg); iArg = 30000; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_TARGET, &iArg); float v = 30000.0f / static_cast<float>(g.s.iMinLoudness); iArg = lroundf(floorf(20.0f * log10f(v))); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &iArg); iArg = g.s.iNoiseSuppress; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &iArg); if (iEchoChannels > 0) { sesEcho = speex_echo_state_init(iFrameSize, iFrameSize*10); iArg = SAMPLE_RATE; speex_echo_ctl(sesEcho, SPEEX_SET_SAMPLING_RATE, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, sesEcho); jitter_buffer_reset(jb); qWarning("AudioInput: ECHO CANCELLER ACTIVE"); } else { sesEcho = NULL; } iFrames = 0; speex_bits_reset(&sbBits); bResetProcessor = false; } int iIsSpeech; if (sesEcho) { speex_echo_cancellation(sesEcho, psMic, psSpeaker, psClean); iIsSpeech=speex_preprocess_run(sppPreprocess, psClean); psSource = psClean; } else { iIsSpeech=speex_preprocess_run(sppPreprocess, psMic); psSource = psMic; } sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psSource[i] * psSource[i]); float micLevel = sqrtf(sum / static_cast<float>(iFrameSize)); dPeakSignal=20.0f*log10f(micLevel / 32768.0f); if (dPeakSignal < -96.0f) dPeakSignal = -96.0f; spx_int32_t prob = 0; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_GET_PROB, &prob); fSpeechProb = static_cast<float>(prob) / 100.0f; float level = (g.s.vsVAD == Settings::SignalToNoise) ? fSpeechProb : (1.0f + dPeakMic / 96.0f); if (level > g.s.fVADmax) iIsSpeech = 1; else if (level > g.s.fVADmin && bPreviousVoice) iIsSpeech = 1; else iIsSpeech = 0; if (! iIsSpeech) { iHoldFrames++; if (iHoldFrames < g.s.iVoiceHold) iIsSpeech=1; } else { iHoldFrames = 0; } if (g.s.atTransmit == Settings::Continous) iIsSpeech = 1; else if (g.s.atTransmit == Settings::PushToTalk) iIsSpeech = g.s.uiDoublePush && ((g.uiDoublePush < g.s.uiDoublePush) || (g.tDoublePush.elapsed() < g.s.uiDoublePush)); iIsSpeech = iIsSpeech || (g.iPushToTalk > 0) || (g.iAltSpeak > 0); if (g.s.bMute || ((g.s.lmLoopMode != Settings::Local) && p && p->bMute) || g.bPushToMute) { iIsSpeech = 0; } if (iIsSpeech) { iSilentFrames = 0; } else { iSilentFrames++; if (iSilentFrames > 200) iFrameCounter = 0; } if (p) p->setTalking(iIsSpeech, (g.iAltSpeak > 0)); if (g.s.bPushClick && (g.s.atTransmit == Settings::PushToTalk)) { AudioOutputPtr ao = g.ao; if (iIsSpeech && ! bPreviousVoice && ao) ao->playSine(400.0f,1200.0f,5); else if (ao && !iIsSpeech && bPreviousVoice && ao) ao->playSine(620.0f,-1200.0f,5); } if (! iIsSpeech && ! bPreviousVoice) { iBitrate = 0; if (g.s.iIdleTime && ! g.s.bMute && ((tIdle.elapsed() / 1000000ULL) > g.s.iIdleTime)) { emit doMute(); tIdle.restart(); } return; } bPreviousVoice = iIsSpeech; tIdle.restart(); if (! iIsSpeech) { memset(psMic, 0, sizeof(short) * iFrameSize); } if (g.s.bTransmitPosition && g.p && ! g.bCenterPosition && (iFrames == 0) && g.p->fetch()) { QByteArray q; QDataStream ds(&q, QIODevice::WriteOnly); ds << g.p->fPosition[0]; ds << g.p->fPosition[1]; ds << g.p->fPosition[2]; speex_bits_pack(&sbBits, 13, 5); speex_bits_pack(&sbBits, q.size(), 4); const unsigned char *d=reinterpret_cast<const unsigned char*>(q.data()); for (i=0;i<q.size();i++) { speex_bits_pack(&sbBits, d[i], 8); } } speex_encode_int(esEncState, psSource, &sbBits); iFrames++; speex_encoder_ctl(esEncState, SPEEX_GET_BITRATE, &iBitrate); flushCheck(); }
int main() { // spectral periodogram options unsigned int nfft=256; // spectral periodogram FFT size unsigned int num_samples = 2001; // number of samples float beta = 10.0f; // Kaiser-Bessel window parameter // allocate memory for data arrays float complex x[num_samples]; // input signal float complex X[nfft]; // output spectrum float psd[nfft]; // power spectral density unsigned int ramp = num_samples/20 < 10 ? 10 : num_samples/20; // create spectral periodogram unsigned int window_size = nfft/2; // spgram window size unsigned int delay = nfft/8; // samples between transforms spgram q = spgram_create_kaiser(nfft, window_size, beta); unsigned int i; // generate signal nco_crcf nco = nco_crcf_create(LIQUID_VCO); for (i=0; i<num_samples; i++) { nco_crcf_set_frequency(nco, 0.1f*(1.2f+sinf(0.007f*i)) ); nco_crcf_cexpf(nco, &x[i]); nco_crcf_step(nco); } nco_crcf_destroy(nco); // add soft ramping functions for (i=0; i<ramp; i++) { x[i] *= 0.5f - 0.5f*cosf(M_PI*(float)i / (float)ramp); x[num_samples-ramp+i-1] *= 0.5f - 0.5f*cosf(M_PI*(float)(ramp-i-1) / (float)ramp); } // // export output file(s) // FILE * fid; // // export time-doman data // fid = fopen(OUTPUT_FILENAME_TIME,"w"); fprintf(fid,"# %s : auto-generated file\n", OUTPUT_FILENAME_TIME); for (i=0; i<num_samples; i++) fprintf(fid,"%12u %12.8f %12.8f\n", i, crealf(x[i]), cimagf(x[i])); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME_TIME); // // export freq-doman data // fid = fopen(OUTPUT_FILENAME_FREQ,"w"); fprintf(fid,"# %s : auto-generated file\n", OUTPUT_FILENAME_FREQ); unsigned int t=0; for (i=0; i<num_samples; i++) { // push sample into periodogram spgram_push(q, &x[i], 1); if ( ((i+1)%delay)==0 ) { // compute spectral periodogram output spgram_execute(q, X); unsigned int k; // compute PSD and FFT shift for (k=0; k<nfft; k++) psd[k] = 20*log10f( cabsf(X[(k+nfft/2)%nfft]) ); #if 1 for (k=0; k<nfft; k++) fprintf(fid,"%12u %12.8f %12.8f\n", t, (float)k/(float)nfft - 0.5f, psd[k]); #else for (k=0; k<nfft; k++) fprintf(fid,"%12.8f ", psd[k]); #endif fprintf(fid,"\n"); t++; } } // destroy spectral periodogram object spgram_destroy(q); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME_FREQ); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // options unsigned int n=512; // number of samples float fc = 0.02; // input signal frequency unsigned int nbits=3; // number of adjacent bits to observe float zeta=1.5f; // slope adjustment multiplier float alpha = 0.95; // pre-/post-filter coefficient int dopt; while ((dopt = getopt(argc,argv,"uhn:f:b:z:a:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'n': n = atoi(optarg); break; case 'f': fc = atof(optarg); break; case 'b': nbits = atoi(optarg); break; case 'z': zeta = atof(optarg); break; case 'a': alpha = atof(optarg); break; default: exit(1); } } // validate input unsigned int i; // data arrays float x[n]; // input time series unsigned char b[n]; // encoded bit pattern float y[n]; // reconstructed time series // create cvsd codecs cvsd cvsd_encoder = cvsd_create(nbits, zeta, alpha); cvsd cvsd_decoder = cvsd_create(nbits, zeta, alpha); cvsd_print(cvsd_encoder); // generate input time series for (i=0; i<n; i++) x[i] = sinf(2.0f*M_PI*fc*i) * hamming(i,n); // encode time series for (i=0; i<n; i++) b[i] = cvsd_encode(cvsd_encoder, x[i]); // compute reconstructed time series, RMS error float rmse=0.0f; for (i=0; i<n; i++) { y[i] = cvsd_decode(cvsd_decoder, b[i]); printf("%1u ", b[i]); if ( ((i+1)%32) == 0 ) printf("\n"); float e = x[i]-y[i]; rmse += e*e; } rmse = sqrtf(rmse/n); printf("\n"); printf("signal/distortion: %8.2f dB\n", -20*log10f(rmse)); // destroy cvsd objects cvsd_destroy(cvsd_encoder); cvsd_destroy(cvsd_decoder); // // export results to file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"n=%u;\n", n); fprintf(fid,"x=zeros(1,n);\n"); fprintf(fid,"y=zeros(1,n);\n"); for (i=0; i<n; i++) { fprintf(fid,"x(%3u) = %12.4e;\n", i+1, x[i]); fprintf(fid,"y(%3u) = %12.4e;\n", i+1, y[i]); } fprintf(fid,"\n\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(1:n,x,1:n,y);\n"); fprintf(fid,"xlabel('time [sample index]');\n"); fprintf(fid,"ylabel('signal');\n"); fprintf(fid,"legend('audio input','cvsd output',1);\n"); // close debug file fclose(fid); printf("results wrtten to %s\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // options unsigned int num_symbols=500; // number of symbols to observe float SNRdB = 30.0f; // signal-to-noise ratio [dB] unsigned int hc_len=5; // channel filter length unsigned int k=2; // matched filter samples/symbol unsigned int m=3; // matched filter delay (symbols) float beta=0.3f; // matched filter excess bandwidth factor unsigned int p=3; // equalizer length (symbols, gr_len = 2*k*p+1) float mu = 0.09f; // LMS learning rate // modulation type/depth modulation_scheme ms = LIQUID_MODEM_QPSK; // plotting options unsigned int nfft = 512; // fft size float gnuplot_version = 4.2; char filename_base[256] = "figures.gen/eqlms_cccf_blind"; int dopt; while ((dopt = getopt(argc,argv,"hf:g:n:s:c:k:m:b:p:u:M:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'f': strncpy(filename_base,optarg,256); break; case 'g': gnuplot_version = atoi(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'c': hc_len = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'p': p = atoi(optarg); break; case 'u': mu = atof(optarg); break; case 'M': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; default: exit(1); } } // validate input if (num_symbols == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero\n", argv[0]); exit(1); } else if (hc_len == 0) { fprintf(stderr,"error: %s, channel must have at least 1 tap\n", argv[0]); exit(1); } else if (k < 2) { fprintf(stderr,"error: %s, samples/symbol must be at least 2\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (beta < 0.0f || beta > 1.0f) { fprintf(stderr,"error: %s, filter excess bandwidth must be in [0,1]\n", argv[0]); exit(1); } else if (p == 0) { fprintf(stderr,"error: %s, equalizer semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (mu < 0.0f || mu > 1.0f) { fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]); exit(1); } // set 'random' seed on options srand( hc_len + p + nfft ); // derived values unsigned int gt_len = 2*k*m+1; // matched filter length unsigned int gr_len = 2*k*p+1; // equalizer filter length unsigned int num_samples = k*num_symbols; // bookkeeping variables float complex sym_tx[num_symbols]; // transmitted data sequence float complex x[num_samples]; // interpolated time series float complex y[num_samples]; // channel output float complex z[num_samples]; // equalized output // least mean-squares (LMS) equalizer float mse[num_symbols]; // equalizer mean-squared error float complex gr[gr_len]; // equalizer filter coefficients unsigned int i; // generate matched filter response float gtf[gt_len]; // matched filter response liquid_firdes_rnyquist(LIQUID_RNYQUIST_RRC, k, m, beta, 0.0f, gtf); // convert to complex coefficients float complex gt[gt_len]; for (i=0; i<gt_len; i++) gt[i] = gtf[i]; //+ 0.1f*(randnf() + _Complex_I*randnf()); // create interpolator interp_cccf interp = interp_cccf_create(k, gt, gt_len); // create the modem objects modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int bps = modem_get_bps(mod); unsigned int M = 1 << bps; // generate channel impulse response, filter #if 0 float complex hc[hc_len]; // channel filter coefficients hc[0] = 1.0f; for (i=1; i<hc_len; i++) hc[i] = 0.09f*(randnf() + randnf()*_Complex_I); #else // use fixed channel hc_len = 8; float complex hc[hc_len]; // channel filter coefficients hc[0] = 1.00000000+ 0.00000000*_Complex_I; hc[1] = 0.08077553+ -0.00247592*_Complex_I; hc[2] = 0.03625883+ -0.09219734*_Complex_I; hc[3] = 0.05764082+ 0.03277601*_Complex_I; hc[4] = -0.04773349+ -0.18766306*_Complex_I; hc[5] = -0.00101735+ -0.00270737*_Complex_I; hc[6] = -0.05796884+ -0.12665297*_Complex_I; hc[7] = 0.03805391+ -0.07609370*_Complex_I; #endif firfilt_cccf fchannel = firfilt_cccf_create(hc, hc_len); firfilt_cccf_print(fchannel); // generate random symbols for (i=0; i<num_symbols; i++) modem_modulate(mod, rand()%M, &sym_tx[i]); // interpolate for (i=0; i<num_symbols; i++) interp_cccf_execute(interp, sym_tx[i], &x[i*k]); // push through channel float nstd = powf(10.0f, -SNRdB/20.0f); for (i=0; i<num_samples; i++) { firfilt_cccf_push(fchannel, x[i]); firfilt_cccf_execute(fchannel, &y[i]); // add noise y[i] += nstd*(randnf() + randnf()*_Complex_I)*M_SQRT1_2; } // push through equalizers float grf[gr_len]; liquid_firdes_rnyquist(LIQUID_RNYQUIST_RRC, k, p, beta, 0.0f, grf); for (i=0; i<gr_len; i++) { gr[i] = grf[i] / (float)k; } // create LMS equalizer eqlms_cccf eq = eqlms_cccf_create(gr, gr_len); eqlms_cccf_set_bw(eq, mu); // filtered error vector magnitude (emperical MSE) //float zeta=0.05f; // smoothing factor (small zeta -> smooth MSE) float complex d_hat = 0.0f; unsigned int num_symbols_rx=0; for (i=0; i<num_samples; i++) { // push samples into equalizers eqlms_cccf_push(eq, y[i]); // compute outputs eqlms_cccf_execute(eq, &d_hat); // store outputs z[i] = d_hat; // check to see if buffer is full if ( i < gr_len) continue; // decimate by k if ( (i%k) != 0 ) continue; // estimate transmitted signal unsigned int sym_out; // output symbol float complex d_prime; // estimated input sample // LMS modem_demodulate(demod, d_hat, &sym_out); modem_get_demodulator_sample(demod, &d_prime); // update equalizers eqlms_cccf_step(eq, d_prime, d_hat); #if 0 // update filtered evm estimate float evm = crealf( (d_prime-d_hat)*conjf(d_prime-d_hat) ); if (num_symbols_rx == 0) { mse[num_symbols_rx] = evm; } else { mse[num_symbols_rx] = mse[num_symbols_rx-1]*(1-zeta) + evm*zeta; } #else // compute ISI for entire system eqlms_cccf_get_weights(eq, gr); mse[num_symbols_rx] = eqlms_cccf_isi(k, gt, gt_len, hc, hc_len, gr, gr_len); #endif // print filtered evm (emperical rms error) if ( ((num_symbols_rx+1)%100) == 0 ) printf("%4u : mse = %12.8f dB\n", num_symbols_rx+1, 20*log10f(mse[num_symbols_rx])); // increment output symbol counter num_symbols_rx++; } // get equalizer weights eqlms_cccf_get_weights(eq, gr); // destroy objects eqlms_cccf_destroy(eq); interp_cccf_destroy(interp); firfilt_cccf_destroy(fchannel); modem_destroy(mod); modem_destroy(demod); // // export output // FILE * fid = NULL; char filename[300]; // // const: constellation // strncpy(filename, filename_base, 256); strcat(filename, "_const.gnu"); fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], filename); return 1; } fprintf(fid,"# %s: auto-generated file\n\n", filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set size ratio 1\n"); fprintf(fid,"set xrange [-1.5:1.5];\n"); fprintf(fid,"set yrange [-1.5:1.5];\n"); fprintf(fid,"set xlabel 'In-phase'\n"); fprintf(fid,"set ylabel 'Quadrature phase'\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' linewidth 1\n",LIQUID_DOC_COLOR_GRID); fprintf(fid,"plot '-' using 1:2 with points pointtype 7 pointsize 0.5 linecolor rgb '%s' title 'first 50%%',\\\n", LIQUID_DOC_COLOR_GRAY); fprintf(fid," '-' using 1:2 with points pointtype 7 pointsize 0.7 linecolor rgb '%s' title 'last 50%%'\n", LIQUID_DOC_COLOR_RED); // first half of symbols for (i=2*p; i<num_symbols/2; i+=k) fprintf(fid," %12.4e %12.4e\n", crealf(y[i]), cimagf(y[i])); fprintf(fid,"e\n"); // second half of symbols for ( ; i<num_symbols; i+=k) fprintf(fid," %12.4e %12.4e\n", crealf(z[i]), cimagf(z[i])); fprintf(fid,"e\n"); fclose(fid); printf("results written to '%s'\n", filename); // // mse : mean-squared error // strncpy(filename, filename_base, 256); strcat(filename, "_mse.gnu"); fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], filename); return 1; } fprintf(fid,"# %s: auto-generated file\n\n", filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set size ratio 0.3\n"); fprintf(fid,"set xrange [0:%u];\n", num_symbols); fprintf(fid,"set yrange [1e-3:1e-1];\n"); fprintf(fid,"set format y '10^{%%L}'\n"); fprintf(fid,"set log y\n"); fprintf(fid,"set xlabel 'symbol index'\n"); fprintf(fid,"set ylabel 'mean-squared error'\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' linewidth 1\n",LIQUID_DOC_COLOR_GRID); fprintf(fid,"plot '-' using 1:2 with lines linewidth 4 linetype 1 linecolor rgb '%s' title 'LMS MSE'\n", LIQUID_DOC_COLOR_RED); // LMS for (i=0; i<num_symbols_rx; i++) fprintf(fid," %4u %16.8e\n", i, mse[i]); fprintf(fid,"e\n"); fclose(fid); printf("results written to '%s'\n", filename); // // psd : power spectral density // // scale transmit filter appropriately for (i=0; i<gt_len; i++) gt[i] /= (float)k; float complex Gt[nfft]; // transmit matched filter float complex Hc[nfft]; // channel response float complex Gr[nfft]; // equalizer response liquid_doc_compute_psdcf(gt, gt_len, Gt, nfft, LIQUID_DOC_PSDWINDOW_NONE, 0); liquid_doc_compute_psdcf(hc, hc_len, Hc, nfft, LIQUID_DOC_PSDWINDOW_NONE, 0); liquid_doc_compute_psdcf(gr, gr_len, Gr, nfft, LIQUID_DOC_PSDWINDOW_NONE, 0); fft_shift(Gt, nfft); fft_shift(Hc, nfft); fft_shift(Gr, nfft); float freq[nfft]; for (i=0; i<nfft; i++) freq[i] = (float)(i) / (float)nfft - 0.5f; strncpy(filename, filename_base, 256); strcat(filename, "_freq.gnu"); fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], filename); return 1; } fprintf(fid,"# %s: auto-generated file\n\n", filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set size ratio 0.6\n"); fprintf(fid,"set xrange [-0.5:0.5];\n"); fprintf(fid,"set yrange [-10:6]\n"); fprintf(fid,"set xlabel 'Normalized Frequency'\n"); fprintf(fid,"set ylabel 'Power Spectral Density [dB]'\n"); fprintf(fid,"set key top right nobox\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n",LIQUID_DOC_COLOR_GRID); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 1.5 linecolor rgb '%s' title 'transmit',\\\n", LIQUID_DOC_COLOR_GRAY); fprintf(fid," '-' using 1:2 with lines linetype 1 linewidth 1.5 linecolor rgb '%s' title 'channel',\\\n", LIQUID_DOC_COLOR_RED); fprintf(fid," '-' using 1:2 with lines linetype 1 linewidth 1.5 linecolor rgb '%s' title 'equalizer',\\\n", LIQUID_DOC_COLOR_GREEN); fprintf(fid," '-' using 1:2 with lines linetype 1 linewidth 4.0 linecolor rgb '%s' title 'composite',\\\n", LIQUID_DOC_COLOR_BLUE); fprintf(fid," '-' using 1:2 with points pointtype 7 pointsize 0.6 linecolor rgb '%s' notitle\n", LIQUID_DOC_COLOR_BLUE); // received signal for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", freq[i], 20*log10f(cabsf(Gt[i])) ); fprintf(fid,"e\n"); // channel for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", freq[i], 20*log10f(cabsf(Hc[i])) ); fprintf(fid,"e\n"); // equalizer for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", freq[i], 20*log10f(cabsf(Gr[i])) ); fprintf(fid,"e\n"); // composite for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", freq[i], 20*log10f( cabsf(Gt[i])*cabsf(Hc[i])*cabsf(Gr[i])) ); fprintf(fid,"e\n"); // composite fprintf(fid,"%12.8f %12.4e\n", -0.5f/(float)k, 20*log10f(0.5f)); fprintf(fid,"%12.8f %12.4e\n", 0.5f/(float)k, 20*log10f(0.5f)); fprintf(fid,"e\n"); fclose(fid); printf("results written to '%s'\n", filename); // // time... // strncpy(filename, filename_base, 256); strcat(filename, "_time.gnu"); fid = fopen(filename,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], filename); return 1; } fprintf(fid,"# %s: auto-generated file\n\n", filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set xrange [0:%u];\n",num_symbols); fprintf(fid,"set yrange [-1.5:1.5]\n"); fprintf(fid,"set size ratio 0.3\n"); fprintf(fid,"set xlabel 'Symbol Index'\n"); fprintf(fid,"set key top right nobox\n"); //fprintf(fid,"set ytics -5,1,5\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set pointsize 0.6\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n", LIQUID_DOC_COLOR_GRID); fprintf(fid,"set multiplot layout 2,1 scale 1.0,1.0\n"); // real fprintf(fid,"# real\n"); fprintf(fid,"set ylabel 'Real'\n"); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 1 linecolor rgb '#999999' notitle,\\\n"); fprintf(fid," '-' using 1:2 with points pointtype 7 linecolor rgb '%s' notitle'\n", LIQUID_DOC_COLOR_BLUE); // for (i=0; i<num_samples; i++) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)k, crealf(z[i])); fprintf(fid,"e\n"); // for (i=0; i<num_samples; i+=k) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)k, crealf(z[i])); fprintf(fid,"e\n"); // imag fprintf(fid,"# imag\n"); fprintf(fid,"set ylabel 'Imag'\n"); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 1 linecolor rgb '#999999' notitle,\\\n"); fprintf(fid," '-' using 1:2 with points pointtype 7 linecolor rgb '%s' notitle'\n", LIQUID_DOC_COLOR_GREEN); // for (i=0; i<num_samples; i++) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)k, cimagf(z[i])); fprintf(fid,"e\n"); // for (i=0; i<num_samples; i+=k) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)k, cimagf(z[i])); fprintf(fid,"e\n"); fprintf(fid,"unset multiplot\n"); // close output file fclose(fid); printf("results written to '%s'\n", filename); return 0; }
static inline void process_drago(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, dt_iop_global_tonemap_data_t *data) { dt_iop_global_tonemap_gui_data_t *g = (dt_iop_global_tonemap_gui_data_t *)self->gui_data; float *in = (float *)ivoid; float *out = (float *)ovoid; const int ch = piece->colors; /* precalcs */ const float eps = 0.0001f; float lwmax; float tmp_lwmax = NAN; // Drago needs the absolute Lmax value of the image. In pixelpipe FULL we can not reliably get this value // as the pixelpipe might only see part of the image (region of interest). Therefore we try to get lwmax from // the PREVIEW pixelpipe which luckily stores it for us. if(self->dev->gui_attached && g && piece->pipe->type == DT_DEV_PIXELPIPE_FULL) { dt_pthread_mutex_lock(&g->lock); const uint64_t hash = g->hash; dt_pthread_mutex_unlock(&g->lock); // note that the case 'hash == 0' on first invocation in a session implies that g->lwmax // is NAN which initiates special handling below to avoid inconsistent results. in all // other cases we make sure that the preview pipe has left us with proper readings for // lwmax. if data are not yet there we need to wait (with timeout). if(hash != 0 && !dt_dev_sync_pixelpipe_hash(self->dev, piece->pipe, 0, self->priority, &g->lock, &g->hash)) dt_control_log(_("inconsistent output")); dt_pthread_mutex_lock(&g->lock); tmp_lwmax = g->lwmax; dt_pthread_mutex_unlock(&g->lock); } // in all other cases we calculate lwmax here if(isnan(tmp_lwmax)) { lwmax = eps; for(size_t k = 0; k < (size_t)roi_out->width * roi_out->height; k++) { float *inp = in + ch * k; lwmax = fmaxf(lwmax, (inp[0] * 0.01f)); } } else { lwmax = tmp_lwmax; } // PREVIEW pixelpipe stores lwmax if(self->dev->gui_attached && g && piece->pipe->type == DT_DEV_PIXELPIPE_PREVIEW) { uint64_t hash = dt_dev_hash_plus(self->dev, piece->pipe, 0, self->priority); dt_pthread_mutex_lock(&g->lock); g->lwmax = lwmax; g->hash = hash; dt_pthread_mutex_unlock(&g->lock); } const float ldc = data->drago.max_light * 0.01 / log10f(lwmax + 1); const float bl = logf(fmaxf(eps, data->drago.bias)) / logf(0.5); #ifdef _OPENMP #pragma omp parallel for default(none) shared(in, out, lwmax) schedule(static) #endif for(size_t k = 0; k < (size_t)roi_out->width * roi_out->height; k++) { float *inp = in + ch * k; float *outp = out + ch * k; float lw = inp[0] * 0.01f; outp[0] = 100.0f * (ldc * logf(fmaxf(eps, lw + 1.0f)) / logf(fmaxf(eps, 2.0f + (powf(lw / lwmax, bl)) * 8.0f))); outp[1] = inp[1]; outp[2] = inp[2]; } }
SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples) { #if defined(SPANDSP_USE_FIXED_POINT) int32_t row_energy[4]; int32_t col_energy[4]; int16_t xamp; float famp; #else float row_energy[4]; float col_energy[4]; float xamp; float famp; #endif float v1; int i; int j; int sample; int best_row; int best_col; int limit; uint8_t hit; hit = 0; for (sample = 0; sample < samples; sample = limit) { /* The block length is optimised to meet the DTMF specs. */ if ((samples - sample) >= (DTMF_SAMPLES_PER_BLOCK - s->current_sample)) limit = sample + (DTMF_SAMPLES_PER_BLOCK - s->current_sample); else limit = samples; /* The following unrolled loop takes only 35% (rough estimate) of the time of a rolled loop on the machine on which it was developed */ for (j = sample; j < limit; j++) { xamp = amp[j]; if (s->filter_dialtone) { famp = xamp; /* Sharp notches applied at 350Hz and 440Hz - the two common dialtone frequencies. These are rather high Q, to achieve the required narrowness, without using lots of sections. */ v1 = 0.98356f*famp + 1.8954426f*s->z350[0] - 0.9691396f*s->z350[1]; famp = v1 - 1.9251480f*s->z350[0] + s->z350[1]; s->z350[1] = s->z350[0]; s->z350[0] = v1; v1 = 0.98456f*famp + 1.8529543f*s->z440[0] - 0.9691396f*s->z440[1]; famp = v1 - 1.8819938f*s->z440[0] + s->z440[1]; s->z440[1] = s->z440[0]; s->z440[0] = v1; xamp = famp; } xamp = goertzel_preadjust_amp(xamp); #if defined(SPANDSP_USE_FIXED_POINT) s->energy += ((int32_t) xamp*xamp); #else s->energy += xamp*xamp; #endif goertzel_samplex(&s->row_out[0], xamp); goertzel_samplex(&s->col_out[0], xamp); goertzel_samplex(&s->row_out[1], xamp); goertzel_samplex(&s->col_out[1], xamp); goertzel_samplex(&s->row_out[2], xamp); goertzel_samplex(&s->col_out[2], xamp); goertzel_samplex(&s->row_out[3], xamp); goertzel_samplex(&s->col_out[3], xamp); } if (s->duration < INT_MAX - (limit - sample)) s->duration += (limit - sample); s->current_sample += (limit - sample); if (s->current_sample < DTMF_SAMPLES_PER_BLOCK) continue; /* We are at the end of a DTMF detection block */ /* Find the peak row and the peak column */ row_energy[0] = goertzel_result(&s->row_out[0]); best_row = 0; col_energy[0] = goertzel_result(&s->col_out[0]); best_col = 0; for (i = 1; i < 4; i++) { row_energy[i] = goertzel_result(&s->row_out[i]); if (row_energy[i] > row_energy[best_row]) best_row = i; col_energy[i] = goertzel_result(&s->col_out[i]); if (col_energy[i] > col_energy[best_col]) best_col = i; } hit = 0; /* Basic signal level test and the twist test */ if (row_energy[best_row] >= s->threshold && col_energy[best_col] >= s->threshold) { if (col_energy[best_col] < row_energy[best_row]*s->reverse_twist && col_energy[best_col]*s->normal_twist > row_energy[best_row]) { /* Relative peak test ... */ for (i = 0; i < 4; i++) { if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { break; } } /* ... and fraction of total energy test */ if (i >= 4 && (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) { /* Got a hit */ hit = dtmf_positions[(best_row << 2) + best_col]; } } if (span_log_test(&s->logging, SPAN_LOG_FLOW)) { /* Log information about the quality of the signal, to aid analysis of detection problems */ /* Logging at this point filters the total no-hoper frames out of the log, and leaves anything which might feasibly be a DTMF digit. The log will then contain a list of the total, row and coloumn power levels for detailed analysis of detection problems. */ span_log(&s->logging, SPAN_LOG_FLOW, "Potentially '%c' - total %.2fdB, row %.2fdB, col %.2fdB - %s\n", dtmf_positions[(best_row << 2) + best_col], log10f(s->energy)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, log10f(row_energy[best_row]/DTMF_TO_TOTAL_ENERGY)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, log10f(col_energy[best_col]/DTMF_TO_TOTAL_ENERGY)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, (hit) ? "hit" : "miss"); } } /* The logic in the next test should ensure the following for different successive hit patterns: -----ABB = start of digit B. ----B-BB = start of digit B ----A-BB = start of digit B BBBBBABB = still in digit B. BBBBBB-- = end of digit B BBBBBBC- = end of digit B BBBBACBB = B ends, then B starts again. BBBBBBCC = B ends, then C starts. BBBBBCDD = B ends, then D starts. This can work with: - Back to back differing digits. Back-to-back digits should not happen. The spec. says there should be a gap between digits. However, many real phones do not impose a gap, and rolling across the keypad can produce little or no gap. - It tolerates nasty phones that give a very wobbly start to a digit. - VoIP can give sample slips. The phase jumps that produces will cause the block it is in to give no detection. This logic will ride over a single missed block, and not falsely declare a second digit. If the hiccup happens in the wrong place on a minimum length digit, however we would still fail to detect that digit. Could anything be done to deal with that? Packet loss is clearly a no-go zone. Note this is only relevant to VoIP using A-law, u-law or similar. Low bit rate codecs scramble DTMF too much for it to be recognised, and often slip in units larger than a sample. */ if (hit != s->in_digit) { if (s->last_hit != s->in_digit) { /* We have two successive indications that something has changed. */ /* To declare digit on, the hits must agree. Otherwise we declare tone off. */ hit = (hit && hit == s->last_hit) ? hit : 0; if (s->realtime_callback) { /* Avoid reporting multiple no digit conditions on flaky hits */ if (s->in_digit || hit) { i = (s->in_digit && !hit) ? -99 : lfastrintf(log10f(s->energy)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER); s->realtime_callback(s->realtime_callback_data, hit, i, s->duration); s->duration = 0; } } else { if (hit) { if (s->current_digits < MAX_DTMF_DIGITS) { s->digits[s->current_digits++] = (char) hit; s->digits[s->current_digits] = '\0'; if (s->digits_callback) { s->digits_callback(s->digits_callback_data, s->digits, s->current_digits); s->current_digits = 0; } } else { s->lost_digits++; } } } s->in_digit = hit; } } s->last_hit = hit; #if defined(SPANDSP_USE_FIXED_POINT) s->energy = 0; #else s->energy = 0.0f; #endif s->current_sample = 0; } if (s->current_digits && s->digits_callback) { s->digits_callback(s->digits_callback_data, s->digits, s->current_digits); s->digits[0] = '\0'; s->current_digits = 0; } return 0; }
int main(int argc, char*argv[]) { // options unsigned int k=4; // samples/symbol unsigned int m=3; // filter delay [symbols] float BT = 0.3f; // bandwidth-time product // read properties from command line int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': BT = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: %s, k must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, m must be at least 1\n", argv[0]); exit(1); } else if (BT <= 0.0f || BT >= 1.0f) { fprintf(stderr,"error: %s, BT must be in (0,1)\n", argv[0]); exit(1); } unsigned int i; // derived values unsigned int h_len = 2*k*m+1; // filter length // arrays float ht[h_len]; // transmit filter coefficients float hr[h_len]; // recieve filter coefficients // design transmit filter liquid_firdes_gmsktx(k,m,BT,0.0f,ht); // print results to screen printf("gmsk transmit filter:\n"); for (i=0; i<h_len; i++) printf(" ht(%3u) = %12.8f;\n", i+1, ht[i]); // // start of filter design procedure // float beta = BT; // prototype filter cut-off float delta = 1e-2f; // filter design correction factor // temporary arrays float h_primef[h_len]; // temporary buffer for real coefficients float g_primef[h_len]; // float complex h_tx[h_len]; // impulse response of transmit filter float complex h_prime[h_len]; // impulse response of 'prototype' filter float complex g_prime[h_len]; // impulse response of 'gain' filter float complex h_hat[h_len]; // impulse response of receive filter float complex H_tx[h_len]; // frequency response of transmit filter float complex H_prime[h_len]; // frequency response of 'prototype' filter float complex G_prime[h_len]; // frequency response of 'gain' filter float complex H_hat[h_len]; // frequency response of receive filter // create 'prototype' matched filter // for now use raised-cosine liquid_firdes_nyquist(LIQUID_FIRFILT_RCOS,k,m,beta,0.0f,h_primef); // create 'gain' filter to improve stop-band rejection float fc = (0.7f + 0.1*beta) / (float)k; float As = 60.0f; liquid_firdes_kaiser(h_len, fc, As, 0.0f, g_primef); // copy to fft input buffer, shifting appropriately for (i=0; i<h_len; i++) { h_prime[i] = h_primef[ (i+k*m)%h_len ]; g_prime[i] = g_primef[ (i+k*m)%h_len ]; h_tx[i] = ht[ (i+k*m)%h_len ]; } // run ffts fft_run(h_len, h_prime, H_prime, LIQUID_FFT_FORWARD, 0); fft_run(h_len, g_prime, G_prime, LIQUID_FFT_FORWARD, 0); fft_run(h_len, h_tx, H_tx, LIQUID_FFT_FORWARD, 0); #if 0 // print results for (i=0; i<h_len; i++) printf("Ht(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(H_tx[i]), cimagf(H_tx[i])); for (i=0; i<h_len; i++) printf("H_prime(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(H_prime[i]), cimagf(H_prime[i])); for (i=0; i<h_len; i++) printf("G_prime(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(G_prime[i]), cimagf(G_prime[i])); #endif // find minimum of reponses float H_tx_min = 0.0f; float H_prime_min = 0.0f; float G_prime_min = 0.0f; for (i=0; i<h_len; i++) { if (i==0 || crealf(H_tx[i]) < H_tx_min) H_tx_min = crealf(H_tx[i]); if (i==0 || crealf(H_prime[i]) < H_prime_min) H_prime_min = crealf(H_prime[i]); if (i==0 || crealf(G_prime[i]) < G_prime_min) G_prime_min = crealf(G_prime[i]); } // compute 'prototype' response, removing minima, and add correction factor for (i=0; i<h_len; i++) { // compute response necessary to yeild prototype response (not exact, but close) H_hat[i] = crealf(H_prime[i] - H_prime_min + delta) / crealf(H_tx[i] - H_tx_min + delta); // include additional term to add stop-band suppression H_hat[i] *= crealf(G_prime[i] - G_prime_min) / crealf(G_prime[0]); } // compute ifft and copy response fft_run(h_len, H_hat, h_hat, LIQUID_FFT_BACKWARD, 0); for (i=0; i<h_len; i++) hr[i] = crealf( h_hat[(i+k*m+1)%h_len] ) / (float)(k*h_len); // // end of filter design procedure // // print results to screen printf("gmsk receive filter:\n"); for (i=0; i<h_len; i++) printf(" hr(%3u) = %12.8f;\n", i+1, hr[i]); // compute isi float rxy0 = liquid_filter_crosscorr(ht,h_len, hr,h_len, 0); float isi_rms = 0.0f; for (i=1; i<2*m; i++) { float e = liquid_filter_crosscorr(ht,h_len, hr,h_len, i*k) / rxy0; isi_rms += e*e; } isi_rms = sqrtf(isi_rms / (float)(2*m-1)); printf("\n"); printf("ISI (RMS) = %12.8f dB\n", 20*log10f(isi_rms)); // // export output file // FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"\n\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"m = %u;\n", m); fprintf(fid,"beta = %f;\n", BT); fprintf(fid,"h_len = 2*k*m+1;\n"); fprintf(fid,"nfft = 1024;\n"); fprintf(fid,"ht = zeros(1,h_len);\n"); fprintf(fid,"hp = zeros(1,h_len);\n"); fprintf(fid,"hr = zeros(1,h_len);\n"); // print results for (i=0; i<h_len; i++) fprintf(fid,"ht(%3u) = %12.4e;\n", i+1, ht[i] / k); for (i=0; i<h_len; i++) fprintf(fid,"hr(%3u) = %12.4e;\n", i+1, hr[i] * k); for (i=0; i<h_len; i++) fprintf(fid,"hp(%3u) = %12.4e;\n", i+1, h_primef[i]); fprintf(fid,"hc = k*conv(ht,hr);\n"); // plot results fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"Ht = 20*log10(abs(fftshift(fft(ht, nfft))));\n"); fprintf(fid,"Hp = 20*log10(abs(fftshift(fft(hp/k,nfft))));\n"); fprintf(fid,"Hr = 20*log10(abs(fftshift(fft(hr, nfft))));\n"); fprintf(fid,"Hc = 20*log10(abs(fftshift(fft(hc/k,nfft))));\n"); fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f,Ht,'LineWidth',1,'Color',[0.00 0.25 0.50],...\n"); fprintf(fid," f,Hp,'LineWidth',1,'Color',[0.80 0.80 0.80],...\n"); fprintf(fid," f,Hr,'LineWidth',1,'Color',[0.00 0.50 0.25],...\n"); fprintf(fid," f,Hc,'LineWidth',2,'Color',[0.50 0.00 0.00],...\n"); fprintf(fid," [-0.5/k 0.5/k], [1 1]*20*log10(0.5),'or');\n"); fprintf(fid,"legend('transmit','prototype','receive','composite','alias points',1);\n"); fprintf(fid,"xlabel('Normalized Frequency');\n"); fprintf(fid,"ylabel('PSD');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-0.5 0.5 -100 20]);\n"); fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"tr = [ -k*m:k*m]/k;\n"); fprintf(fid,"tc = [-2*k*m:2*k*m]/k;\n"); fprintf(fid,"ic = [0:k:(4*k*m)]+1;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(tr,ht,'-x', tr,hr,'-x');\n"); fprintf(fid," legend('transmit','receive',1);\n"); fprintf(fid," xlabel('Time');\n"); fprintf(fid," ylabel('GMSK Tx/Rx Filters');\n"); fprintf(fid," grid on;\n"); fprintf(fid," axis([-2*m 2*m floor(5*min([hr ht]))/5 ceil(5*max([hr ht]))/5]);\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(tc,hc,'-x', tc(ic),hc(ic),'or');\n"); fprintf(fid," xlabel('Time');\n"); fprintf(fid," ylabel('GMSK Composite Response');\n"); fprintf(fid," grid on;\n"); fprintf(fid," axis([-2*m 2*m -0.2 1.2]);\n"); fprintf(fid," axis([-2*m 2*m floor(5*min(hc))/5 ceil(5*max(hc))/5]);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); return 0; }
int main(int argc, char*argv[]) { // options unsigned int num_channels=16; // number of channels unsigned int m = 5; // filter semi-length (symbols) unsigned int num_symbols=25; // number of symbols float As = 80.0f; // filter stop-band attenuation int dopt; while ((dopt = getopt(argc,argv,"hM:m:s:n:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'M': num_channels = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 's': As = atof(optarg); break; case 'n': num_symbols = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (num_channels < 2 || num_channels % 2) { fprintf(stderr,"error: %s, number of channels must be greater than 2 and even\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be greater than zero\n", argv[0]); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero", argv[0]); exit(1); } // derived values unsigned int num_samples = num_channels * num_symbols; // allocate arrays float complex x[num_samples]; float complex y[num_samples]; // generate input signal unsigned int w_len = (unsigned int)(0.4*num_samples); for (i=0; i<num_samples; i++) { //x[i] = (i==0) ? 1.0f : 0.0f; //x[i] = cexpf( (-0.05f + 0.07f*_Complex_I)*i ); // decaying complex exponential x[i] = cexpf( _Complex_I * (1.3f*i - 0.007f*i*i) ); x[i] *= i < w_len ? hamming(i,w_len) : 0.0f; //x[i] = (i==0) ? 1.0f : 0.0f; } // create filterbank objects from prototype firpfbch2_crcf qa = firpfbch2_crcf_create_kaiser(LIQUID_ANALYZER, num_channels, m, As); firpfbch2_crcf qs = firpfbch2_crcf_create_kaiser(LIQUID_SYNTHESIZER, num_channels, m, As); firpfbch2_crcf_print(qa); firpfbch2_crcf_print(qs); // run channelizer float complex Y[num_channels]; for (i=0; i<num_samples; i+=num_channels/2) { // run analysis filterbank firpfbch2_crcf_execute(qa, &x[i], Y); // run synthesis filterbank firpfbch2_crcf_execute(qs, Y, &y[i]); } // destroy fiterbank objects firpfbch2_crcf_destroy(qa); // analysis fitlerbank firpfbch2_crcf_destroy(qs); // synthesis filterbank // print output for (i=0; i<num_samples; i++) printf("%4u : %12.8f + %12.8fj\n", i, crealf(y[i]), cimagf(y[i])); // compute RMSE float rmse = 0.0f; unsigned int delay = 2*num_channels*m - num_channels/2 + 1; for (i=0; i<num_samples; i++) { float complex err = y[i] - (i < delay ? 0.0f : x[i-delay]); rmse += crealf( err*conjf(err) ); } rmse = sqrtf( rmse/(float)num_samples ); printf("rmse : %12.4e\n", rmse); // // EXPORT DATA TO FILES // FILE * fid = NULL; fid = fopen(OUTPUT_FILENAME_TIME,"w"); fprintf(fid,"# %s: auto-generated file\n", OUTPUT_FILENAME_TIME); fprintf(fid,"#\n"); fprintf(fid,"# %8s %12s %12s %12s %12s %12s %12s\n", "time", "real(x)", "imag(x)", "real(y)", "imag(y)", "real(e)", "imag(e)"); // save input and output arrays for (i=0; i<num_samples; i++) { float complex e = (i < delay) ? 0.0f : y[i] - x[i-delay]; fprintf(fid," %8.1f %12.4e %12.4e %12.4e %12.4e %12.4e %12.4e\n", (float)i, crealf(x[i]), cimagf(x[i]), crealf(y[i]), cimagf(y[i]), crealf(e), cimagf(e)); } fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME_TIME); // // export frequency data // unsigned int nfft = 2048; float complex y_time[nfft]; float complex y_freq[nfft]; for (i=0; i<nfft; i++) y_time[i] = i < num_samples ? y[i] : 0.0f; fft_run(nfft, y_time, y_freq, LIQUID_FFT_FORWARD, 0); // filter spectrum unsigned int h_len = 2*num_channels*m+1; float h[h_len]; float fc = 0.5f/(float)num_channels; liquid_firdes_kaiser(h_len, fc, As, 0.0f, h); float complex h_time[nfft]; float complex h_freq[nfft]; for (i=0; i<nfft; i++) h_time[i] = i < h_len ? 2*h[i]*fc : 0.0f; fft_run(nfft, h_time, h_freq, LIQUID_FFT_FORWARD, 0); // error spectrum float complex e_time[nfft]; float complex e_freq[nfft]; for (i=0; i<nfft; i++) e_time[i] = i < delay || i > num_samples ? 0.0f : y[i] - x[i-delay]; fft_run(nfft, e_time, e_freq, LIQUID_FFT_FORWARD, 0); fid = fopen(OUTPUT_FILENAME_FREQ,"w"); fprintf(fid,"# %s: auto-generated file\n", OUTPUT_FILENAME_FREQ); fprintf(fid,"#\n"); fprintf(fid,"# nfft = %u\n", nfft); fprintf(fid,"# %12s %12s %12s %12s\n", "freq", "PSD [dB]", "filter [dB]", "error [dB]"); // save input and output arrays for (i=0; i<nfft; i++) { float f = (float)i/(float)nfft - 0.5f; unsigned int k = (i + nfft/2)%nfft; fprintf(fid," %12.8f %12.8f %12.8f %12.8f\n", f, 20*log10f(cabsf(y_freq[k])), 20*log10f(cabsf(h_freq[k])), 20*log10f(cabsf(e_freq[k]))); } fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME_FREQ); printf("done.\n"); return 0; }
static inline float floatToFrequency(float value) { if (value > 0.97f) return MAXFREQ; if (value < 0.03f) return MINFREQ; value = powf(10.0f, (value + ((0.4f - fabsf(value - 0.4f)) * 0.3f)) * log10f(MAXFREQ - MINFREQ)) + MINFREQ; return value < MAXFREQ ? value : MAXFREQ; }
void LogMmse(LogMMSE* logmmse,float* Y,float* Xest) { int i=nFFT-1,j; int psiNTdB,gammadB; float temp,vk,eivk; float gamma[nFFT],psi[nFFT],psiNT[nFFT],SafetyNetPmin[nFFT],NoiseEst[nFFT],smoothpost[nFFT]; double Speechpresenceprob[nFFT]; //*******Initial Noise variance Estimation assuming 1st 6 frames are noise********// if(framecounter <= 6) { do { logmmse->noiseMu[i]+= sqrt(Y[i]); // Noise mean i--; }while(i>=0); i=nFFT-1; do { logmmse->noiseVar[i] = (float)logmmse->noiseMu[i]*logmmse->noiseMu[i]*2.777777777777778e-02; //(abs(fft)/6)^2 i--; }while(i>=0); } i=nFFT-1; do { gamma[i] = min((Y[i]/logmmse->noiseVar[i]),40); if(framecounter == 1) { psi[i] = 0.98 + 0.02*max((gamma[i]-1),0); psiNT[i] = max((0.98 + 0.02*gamma[i]),0.003162277660168); logmmse->SafetyNetP[i][SafetyNetInd] = 0.9*Y[i]; } else { psi[i] = 0.98*(double)logmmse->X[i]/logmmse->noiseVar[i] + 0.02*max((gamma[i]-1),0); psi[i] = max(psi[i],0.003162277660168); // limiting psi to -25dB psiNT[i] = max((0.98*logmmse->Yprev[i]/logmmse->noiseVar[i]+0.02*gamma[i]),0.003162277660168); if(SafetyNetInd > 0) logmmse->SafetyNetP[i][SafetyNetInd] = 0.1*logmmse->SafetyNetP[i][SafetyNetInd-1]+0.9*Y[i]; else logmmse->SafetyNetP[i][SafetyNetInd] = 0.1*logmmse->SafetyNetP[i][numWinPmin]+0.9*Y[i]; } //*******Setting SafetynetPmin********// temp = logmmse->SafetyNetP[i][0]; j=numWinPmin-1; do{ if(temp>logmmse->SafetyNetP[i][j]) temp = logmmse->SafetyNetP[i][j]; j--; }while(j>=0); SafetyNetPmin[i] = temp; //*******Fetching Noise Estimate********// logmmse->Yprev[i] = Y[i]; psiNTdB = round(max(min(10.0*log10f(psiNT[i]),40),-19))+19; gammadB = round(max(min(10.0*log10f(gamma[i]),40),-30))+30; NoiseEst[i] = GainTable[classdecision][71*psiNTdB+gammadB]*Y[i]; i--; }while(i >= 0); //*******Frequency Smoothing********// smoothpost[0] = (gamma[0]+gamma[1])/2; i = nFFT-2; do { smoothpost[i] = (gamma[i-1]+gamma[i]+gamma[i+1])/3; i--; }while(i>0); smoothpost[nFFT-1] = (gamma[nFFT-1]+gamma[nFFT-2])/2; i=nFFT-1; do { //*******Updating NoiseVariance for next frame********// if(framecounter == 1) Speechpresenceprob[i] = (double)0.9; else Speechpresenceprob[i] = (double)0.1*Speechpresenceprob[i]+(double)0.9*(smoothpost[i]>4); alphas = 0.85 + 0.15 * Speechpresenceprob[i]; logmmse->noiseVar[i] = alphas*logmmse->noiseVar[i] + (1-alphas)*NoiseEst[i]; if((1.5*SafetyNetPmin[i]) > logmmse->noiseVar[i]) { Speechpresenceprob[i] = 0; logmmse->noiseVar[i] = 1.5*SafetyNetPmin[i]; } //*******log MMSE Estimator********// temp = psi[i]/(1+psi[i]); vk = gamma[i]*temp; expint(&vk,&eivk); //Evaluating the exponential integral part Xest[i] = temp*exp(eivk); logmmse->X[i] = Y[i]*Xest[i]*Xest[i]; i--; }while(i>=0); SafetyNetInd = SafetyNetInd+1; if(SafetyNetInd>=numWinPmin) SafetyNetInd = 0; framecounter++; }
static void reinitialize_fft(MF2UI* ui, uint32_t fft_size) { pthread_mutex_lock (&ui->fft_lock); fftx_free(ui->fa); fftx_free(ui->fb); fft_size = MIN(8192, MAX(64, fft_size)); fft_size--; fft_size |= 0x3f; fft_size |= fft_size >> 2; fft_size |= fft_size >> 4; fft_size |= fft_size >> 8; fft_size |= fft_size >> 16; fft_size++; fft_size = MIN(FFT_BINS_MAX, fft_size); ui->fft_bins = fft_size; ui->fa = (struct FFTAnalysis*) malloc(sizeof(struct FFTAnalysis)); ui->fb = (struct FFTAnalysis*) malloc(sizeof(struct FFTAnalysis)); fftx_init(ui->fa, ui->fft_bins * 2, ui->rate, 25); fftx_init(ui->fb, ui->fft_bins * 2, ui->rate, 25); ui->log_rate = (1.0f - 10000.0f / ui->rate) / ((2000.0f / ui->rate) * (2000.0f / ui->rate)); ui->log_base = log10f(1.0f + ui->log_rate); ui->update_grid = true; for (uint32_t i = 0; i < ui->fft_bins; i++) { ui->phase[i] = 0; ui->level[i] = -100; } int band = 0; uint32_t bin = 0; const double f_r = 1000; const double b = ui->fft_bins < 128 ? 6 : 12; const double f2f = pow(2, 1. / (2. * b)); assert(ui->fa->freq_per_bin < f_r); const int b_l = floorf(b * logf(ui->fa->freq_per_bin / f_r) / logf(2)); const int b_u = ceilf(b * logf(.5 * ui->rate / f_r) / logf(2)); ui->freq_bins = b_u - b_l - 1; free(ui->freq_band); ui->freq_band = (uint32_t*) malloc(ui->freq_bins * sizeof(uint32_t)); for (uint32_t i = 0; i < ui->fft_bins; i++) { double f_m = pow(2, (band + b_l) / b) * f_r; double f_2 = f_m * f2f; if (f_2 > i * ui->fa->freq_per_bin) { continue; } while (f_2 < i * ui->fa->freq_per_bin) { band++; f_m = pow(2, (band + b_l) / b) * f_r; f_2 = f_m * f2f; } ui->freq_band[bin++] = i; } ui->freq_band[bin++] = ui->fft_bins; ui->freq_bins = bin; pthread_mutex_unlock (&ui->fft_lock); }
char* stdotpt_(int* I_ptr, int* ITYPE_ptr, float* STPARR, int* NPARR_ptr, float* APPARR, int* lNAPPLE_ptr, float* PROBG_ptr, int which_model) { /* dereference the pointers */ int I = *I_ptr; int ITYPE = *ITYPE_ptr; int lNAPPLE = *lNAPPLE_ptr; float PROBG = *PROBG_ptr; /* renaming used common block variables */ char** flags = tune16_.flags; float XFRAC = eoff_.xfrac; float YFRAC = eoff_.yfrac; short int* EMSUB = estuff_.emsub; float* EMERR = estuff_.emerr; float** EMPAR = estuff_.empar; /* substace of subroutine begins here */ /* Get image shape and area and calc. Fit magnitude: */ static char OUTSTRING[300]; float AREA, AMAJOR, AMINOR, TILT; float FMAG; float APMAG, APERUNC; float XC, YC; float t1, t2, t3, t4; if (ITYPE != 8){ ellipse_(STPARR+4, STPARR+5, STPARR+6, &AREA, &AMAJOR, &AMINOR, &TILT); FMAG = AREA*STPARR[1]; if (FMAG <= 0.0f){ FMAG = 99.999f; } else{ FMAG = -2.5f*log10f(FMAG); } TILT = 57.29578f*TILT; } else{ if (STPARR[5] == -1.0f){ FMAG = 99.999f; } else{ FMAG = -99.999f; } AMAJOR = STPARR[4]; AMINOR = STPARR[6]; TILT = STPARR[5]; // if (STPARR[4] >= STPARR[6]){ // AMAJOR = STPARR[4]; // AMINOR = STPARR[6]; // TILT = 0.0f; // } // else{ // AMAJOR = STPARR[6]; // AMINOR = STPARR[4]; // TILT = 90.0f; // } } /* Convert aperture flux to magnitudes: */ if (APPARR[0] <= 0.0f){ APMAG = 99.999f; } else{ APMAG = -2.5f*log10f(APPARR[0]); } /* If available, get uncertainty in aperture magnitudes: */ APERUNC = 99.999f; if (lNAPPLE >= 5){ APERUNC = APPARR[4]; } /* Fix the co-ordinates so that the center of the first pixel is 0.5 and not 1.0 as in the internal representation */ XC = STPARR[2] - 0.5f; YC = STPARR[3] - 0.5f; /* process the empirical fit data: */ I = I-1; if ((int)(EMSUB[I]) != 0){ t1 = EMPAR[I][0]; t2 = EMPAR[I][1]*10000.0f*AREA; if (t2 <= 0.0f){ t2 = 99.999f; } else{ t2 = -2.5*log10f(t2); } t3 = EMPAR[I][2] + XFRAC - 0.5f; t4 = EMPAR[I][3] + YFRAC - 0.5f; } else{ t1 = EMPAR[I][0]; t2 = -99.999f; t3 = EMPAR[I][2]; t4 = EMPAR[I][3]; } if ((strncmp(flags[0], "PGAUSS", 5) == 0) || (strncmp(flags[0], "GAUSS", 5) == 0)) { sprintf(OUTSTRING," %4d %2d %8.2f %8.2f %8.3f %6.3f %9.2f %9.3f %9.3f %7.2f %10.2E %8.3f %6.3f %9.2f %7.3f %9.2f %8.3f %8.2f %8.2f %6.3f \n", I+1, ITYPE, XC, YC, FMAG, APPARR[3], STPARR[0], AMAJOR, AMINOR, TILT, PROBG, APMAG, APERUNC, APPARR[1], APPARR[2], t1, t2, t3, t4, EMERR[I]); /* Order is: No., obtype, xpos, ypos, fitmag, err_fitmag, fitsky, FWHM_major, FWHM_minor, Tilt, probgal, apmag, err_apmag, apsky, diff_fit_ap */ } if ((strncmp(flags[0], "PGALTMODEL", 5) == 0) || (strncmp(flags[0], "GALTMODEL", 5) == 0)) { sprintf(OUTSTRING," %4d %2d %8.2f %8.2f %8.3f %6.3f %9.2f %9.3f %9.3f %7.2f %10.3E %10.3E %10.3E %10.3E %2d %10.2E %8.3f %6.3f %9.2f %7.3f %9.2f %8.3f %8.2f %8.2f %6.3f \n", I+1, ITYPE, XC, YC, FMAG, APPARR[3], STPARR[0], AMAJOR, AMINOR, TILT, STPARR[7], STPARR[8], STPARR[9], STPARR[10], which_model, PROBG, APMAG, APERUNC, APPARR[1], APPARR[2], t1, t2, t3, t4, EMERR[I]); /* Order is: No., obtype, xpos, ypos, fitmag, err_fitmag, fitsky, FWHM_major, FWHM_minor, Tilt, NEWI1, NEWI2, NEWI3, NEWI4, which_model, probgal, apmag, err_apmag, apsky, diff_fit_ap */ } if (strncmp(flags[0], "SERSIC", 5) == 0){ sprintf(OUTSTRING," %4d %2d %8.2f %8.2f %8.3f %6.3f %9.2f %9.3f %9.3f %7.2f %6.2f %2d %10.2E %8.3f %6.3f %9.2f %7.3f %9.2f %8.3f %8.2f %8.2f %6.3f \n", I+1, ITYPE, XC, YC, FMAG, APPARR[3], STPARR[0], AMAJOR, AMINOR, TILT, STPARR[7], which_model, PROBG, APMAG, APERUNC, APPARR[1], APPARR[2], t1, t2, t3, t4, EMERR[I]); /* Order is: No., obtype, xpos, ypos, fitmag, err_fitmag, fitsky, FWHM_major, FWHM_minor, Tilt, sersic index, which_model, probgal, apmag, err_apmag, apsky, diff_fit_ap */ } if (strncmp(flags[0], "EXTPGAUSS", 5) == 0){ sprintf(OUTSTRING," %4d %2d %8.2f %8.2f %8.3f %6.3f %9.2f %9.3f %9.3f %7.2f %6.2f %6.2f %2d %10.2E %8.3f %6.3f %9.2f %7.3f %9.2f %8.3f %8.2f %8.2f %6.3f \n", I+1, ITYPE, XC, YC, FMAG, APPARR[3], STPARR[0], AMAJOR, AMINOR, TILT, STPARR[7], STPARR[8], which_model, PROBG, APMAG, APERUNC, APPARR[1], APPARR[2], t1, t2, t3, t4, EMERR[I]); /* Order is: No., obtype, xpos, ypos, fitmag, err_fitmag, fitsky, FWHM_major, FWHM_minor, Tilt, b4, which_model, probgal, apmag, err_apmag, apsky, diff_fit_ap */ } return OUTSTRING; }
//------------------------------------------------------------------------------------------------------------------------------------------------------ void Math_CalculateFFT(float *dataR, int numPoints, float *result, float *freq0, float *density0, float *freq1, float *density1, int *y0, int *y1) { float scale = 1.0f / absStepTShift[TBASE] / 1024.0f; float k = 1024.0f / numPoints; *freq0 = scale * set.math.posCur[0] * k; *freq1 = scale * set.math.posCur[1] * k; if (PEACKDET) { *freq0 *= 2; *freq1 *= 2; } for (int i = 0; i < numPoints; i++) { result[i] = 0.0f; } MultiplyToWindow(dataR, numPoints); const int logs[FPGA_NUM_POINTS_SIZE] = {9, 10, 11, 12, 13, 14, 15}; int logN = logs[NumPoints_2_FPGA_NUM_POINTS(numPoints)]; static const float Rcoef[14] = { -1.0000000000000000F, 0.0000000000000000F, 0.7071067811865475F, 0.9238795325112867F, 0.9807852804032304F, 0.9951847266721969F, 0.9987954562051724F, 0.9996988186962042F, 0.9999247018391445F, 0.9999811752826011F, 0.9999952938095761F, 0.9999988234517018F, 0.9999997058628822F, 0.9999999264657178F }; static const float Icoef[14] = { 0.0000000000000000F, -1.0000000000000000F, -0.7071067811865474F, -0.3826834323650897F, -0.1950903220161282F, -0.0980171403295606F, -0.0490676743274180F, -0.0245412285229122F, -0.0122715382857199F, -0.0061358846491544F, -0.0030679567629659F, -0.0015339801862847F, -0.0007669903187427F, -0.0003834951875714F }; int nn = numPoints >> 1; int ie = numPoints; for (int n = 1; n <= logN; n++) { float rw = Rcoef[logN - n]; float iw = Icoef[logN - n]; int in = ie >> 1; float ru = 1.0f; float iu = 0.0f; for (int j = 0; j < in; j++) { for (int i = j; i < numPoints; i += ie) { int io = i + in; float dRi = dataR[i]; float dRio = dataR[io]; float ri = result[i]; float rio = result[io]; dataR[i] = dRi + dRio; result[i] = ri + rio; float rtq = dRi - dRio; float itq = ri - rio; dataR[io] = rtq * ru - itq * iu; result[io] = itq * ru + rtq * iu; } float sr = ru; ru = ru * rw - iu * iw; iu = iu * rw + sr * iw; } ie >>= 1; } for (int j = 1, i = 1; i < numPoints; i++) { if (i < j) { int io = i - 1; int in = j - 1; float rtp = dataR[in]; float itp = result[in]; dataR[in] = dataR[io]; result[in] = result[io]; dataR[io] = rtp; result[io] = itp; } int k = nn; while (k < j) { j = j - k; k >>= 1; } j = j + k; } for (int i = 0; i < 256; i++) { result[i] = sqrtf(dataR[i] * dataR[i] + result[i] * result[i]); } result[0] = 0.0f; // WARN нулевая составляющая мешает постоянно. надо её убрать Normalize(result, 256); if (set.math.scaleFFT == ScaleFFT_Log) { float minDB = sService_MathGetFFTmaxDBabs(); for (int i = 0; i < 256; i++) { #ifdef DEBUG result[i] = 20 * log10f(result[i]); #else result[i] = Log10[(int)(result[i] * 10000)]; #endif if (i == set.math.posCur[0]) { *density0 = result[i]; } else if (i == set.math.posCur[1]) { *density1 = result[i]; } if (result[i] < minDB) { result[i] = minDB; } result[i] = 1.0f - result[i] / minDB; } } else { *density0 = result[set.math.posCur[0]]; *density1 = result[set.math.posCur[1]]; } *y0 = GridMathBottom() - (int)(result[set.math.posCur[0]] * GridMathHeight()); *y1 = GridMathBottom() - (int)(result[set.math.posCur[1]] * GridMathHeight()); }
int main(int argc, char **argv) { struct pcm *pcm; char *pcm_name = "default"; if (argc != 1) pcm_name = argv[1]; if (!open_pcm_read(&pcm, pcm_name)) return 1; info_pcm(pcm); float rate = rate_pcm(pcm); int channels = channels_pcm(pcm); if (channels > 1) fprintf(stderr, "using first of %d channels\n", channels); short *buff = (short *)malloc(sizeof(short) * channels * STEP); float *in = (float *)malloc(sizeof(float) * STEP); float *out = (float *)malloc(sizeof(float) * BINS); fprintf(stderr, "creating stft .."); struct trans *stft = create_stft(BINS); fprintf(stderr, " done.\ncreating cqt, please be patient .."); struct trans *cqt = create_cqt(BINS, rate, 120.0f, rate / 2.0f); fprintf(stderr, " done.\n"); SDL_Init(SDL_INIT_VIDEO); SDL_Surface *screen = SDL_SetVideoMode(1024, BINS, 32, SDL_HWSURFACE|SDL_DOUBLEBUF); if (NULL == screen) exit(1); if (screen->format->BytesPerPixel != 4) exit(1); uint32_t *fbp = (uint32_t *)screen->pixels; int w = screen->w; int h = screen->h; memset(fbp, 0, sizeof(uint32_t) * w * h); for (int i = 0; i < h; i++) { for (int k = 0; k < w / 2; k++) { fbp[w * i + w / 4 + k] = val_rgb((float)i / (float)(h - 1)); } } SDL_WM_SetCaption("Spectrum", "spectrum"); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); float max_hist_seconds = 0.5; int max_hist_size = (max_hist_seconds * rate) / STEP; float *max_hist = (float *)malloc(sizeof(float) * max_hist_size); int max_hist_last = 0; for (int i = 0; i < max_hist_size; i++) max_hist[i] = 0.0; uint64_t cnt = 0; for (;;) { if (cnt++ > rate / (STEP * 50)) { cnt = 0; SDL_Flip(screen); SDL_Delay(10); } handle_events(); if (pause) continue; for (int i = 0; i < h; i++) memmove(fbp + w * i, fbp + w * i + 1, sizeof(uint32_t) * (w - 1)); if (!read_pcm(pcm, buff, STEP)) memset(buff, 0, sizeof(short) * channels * STEP); for (int i = 0; i < STEP; i++) in[i] = (float)buff[((STEP-1)-i) * channels] / 32768.0f; struct trans *trans = stft; if (log_freq) trans = cqt; #if 0 slide_trans(trans, in, STEP); #else slide_trans(stft, in, STEP); slide_trans(cqt, in, STEP); #endif get_trans(trans, out); float max_tmp = 0.0; for (int i = 0; i < max_hist_size; i++) max_tmp = max_tmp > max_hist[i] ? max_tmp : max_hist[i]; float rec_max = 1.0 / (max_tmp ? max_tmp : 1.0); float max_power = 0.0; for (int i = 0; i < BINS; i++) { float power = out[i] * out[i]; max_power = max_power < power ? power : max_power; if (norm_vis) power *= rec_max; float decibel = 10.0f * log10f(fmaxf(0.000001f, power)); float val = power; if (log_power) val = 1.0f + fminf(fmaxf(decibel, -60.0f), 0.0f) / 60.0f; fbp[w * i + w - 1] = val_rgb(val); } max_hist[max_hist_last] = max_power; max_hist_last = (max_hist_last + 1) % max_hist_size; } return 0; }
int main() { // options unsigned int h_len = 7; // filter semi-length (filter delay) float r=1/sqrtf(2); // resampling rate (output/input) float bw=0.25f; // resampling filter bandwidth float As=60.0f; // resampling filter stop-band attenuation [dB] unsigned int npfb=32; // number of filters in bank (timing resolution) unsigned int n=180; // number of input samples // number of input samples (adjusted for filter delay) unsigned int nx = n + h_len; // generate input sequence : windowed sum of complex sinusoids unsigned int i; float complex x[nx]; for (i=0; i<nx; i++) { float complex jphi = _Complex_I*2.0f*M_PI*i; x[i] = cexpf(jphi*0.02f) + 1.4f*cexpf(jphi*0.07f); // window edge size unsigned int t = (unsigned int)(0.1*n); if (i < n) { // edge-rounded window if (i < t) x[i] *= blackmanharris(i,2*t); else if (i >= n-t) x[i] *= blackmanharris(n-i-1,2*t); } else { x[i] = 0.; } } // output buffer with extra padding for good measure unsigned int y_len = (unsigned int) ceilf(1.1*r*nx) + 16; float complex y[y_len]; // create resampler resamp_crcf f = resamp_crcf_create(r,h_len,bw,As,npfb); unsigned int num_written; unsigned int ny=0; for (i=0; i<nx; i++) { // execute resampler, storing in output buffer resamp_crcf_execute(f, x[i], &y[ny], &num_written); ny += num_written; } printf(" %u / %u\n", ny, nx); // clean up allocated objects resamp_crcf_destroy(f); // open/initialize output file FILE*fid = fopen(OUTPUT_FILENAME_TIME,"w"); fprintf(fid,"# %s: auto-generated file\n\n", OUTPUT_FILENAME_TIME); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); //fprintf(fid,"set xrange [0:%u];\n",n); fprintf(fid,"set yrange [-3:3]\n"); fprintf(fid,"set size ratio 0.3\n"); fprintf(fid,"set xlabel 'Input Sample Index'\n"); fprintf(fid,"set key top right nobox\n"); fprintf(fid,"set ytics -5,1,5\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set pointsize 0.6\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n", LIQUID_DOC_COLOR_GRID); fprintf(fid,"set multiplot layout 2,1 scale 1.0,1.0\n"); fprintf(fid,"# real\n"); fprintf(fid,"set ylabel 'Real'\n"); fprintf(fid,"plot '-' using 1:2 with linespoints pointtype 7 linetype 1 linewidth 1 linecolor rgb '#999999' title 'original',\\\n"); fprintf(fid," '-' using 1:2 with points pointtype 7 linecolor rgb '#008000' title 'resampled'\n"); // export output for (i=0; i<nx; i++) { //fprintf(fid,"%6u %12.4e %12.4e\n", i, cos(2*M_PI*0.04*i), sin(2*M_PI*0.04*i)); fprintf(fid,"%6u %12.4e %12.4e\n", i, crealf(x[i]), cimagf(x[i])); } fprintf(fid,"e\n"); float t; for (i=0; i<ny; i++) { t = (float)(i) / r - (float)(h_len); fprintf(fid,"%12.4e %12.4e %12.4e\n", t, crealf(y[i]), cimagf(y[i])); } fprintf(fid,"e\n"); fprintf(fid,"# imag\n"); fprintf(fid,"set ylabel 'Imag'\n"); fprintf(fid,"plot '-' using 1:3 with linespoints pointtype 7 linetype 1 linewidth 1 linecolor rgb '#999999' title 'original',\\\n"); fprintf(fid," '-' using 1:3 with points pointtype 7 linecolor rgb '#800000' title 'resampled'\n"); // export output for (i=0; i<nx; i++) { //fprintf(fid,"%6u %12.4e %12.4e\n", i, cos(2*M_PI*0.04*i), sin(2*M_PI*0.04*i)); fprintf(fid,"%6u %12.4e %12.4e\n", i, crealf(x[i]), cimagf(x[i])); } fprintf(fid,"e\n"); for (i=0; i<ny; i++) { t = (float)(i) / r - (float)(h_len); fprintf(fid,"%12.4e %12.4e %12.4e\n", t, crealf(y[i]), cimagf(y[i])); } fprintf(fid,"e\n"); fprintf(fid,"unset multiplot\n"); // close output file fclose(fid); fid = fopen(OUTPUT_FILENAME_FREQ,"w"); unsigned int nfft = 512; float complex X[nfft]; float complex Y[nfft]; liquid_doc_compute_psdcf(x,nx,X,nfft,LIQUID_DOC_PSDWINDOW_HANN,0); liquid_doc_compute_psdcf(y,ny,Y,nfft,LIQUID_DOC_PSDWINDOW_HANN,0); fft_shift(X,nfft); fft_shift(Y,nfft); float scaling_factor = 20*log10f(nfft); fprintf(fid,"# %s: auto-generated file\n\n", OUTPUT_FILENAME_FREQ); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set xrange [-0.5:0.5];\n"); fprintf(fid,"set yrange [-120:20]\n"); fprintf(fid,"set size ratio 0.6\n"); fprintf(fid,"set xlabel 'Normalized Input Frequency'\n"); fprintf(fid,"set ylabel 'Power Spectral Density [dB]'\n"); fprintf(fid,"set key top right nobox\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set pointsize 0.6\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n",LIQUID_DOC_COLOR_GRID); fprintf(fid,"# real\n"); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 4 linecolor rgb '#999999' title 'original',\\\n"); fprintf(fid," '-' using 1:2 with lines linetype 1 linewidth 4 linecolor rgb '#004080' title 'resampled'\n"); // export output for (i=0; i<nfft; i++) { float fx = (float)(i) / (float)nfft - 0.5f; fprintf(fid,"%12.8f %12.4e\n", fx, 20*log10f(cabsf(X[i])) - scaling_factor); } fprintf(fid,"e\n"); for (i=0; i<nfft; i++) { float fy = ((float)(i) / (float)nfft - 0.5f)*r; fprintf(fid,"%12.8f %12.4e\n", fy, 20*log10f(cabsf(Y[i])) - scaling_factor - 20*log10(r)); } fprintf(fid,"e\n"); fclose(fid); printf("done.\n"); return 0; }
__host__ void single_precision_math_functions() { int iX; float fX, fY; acosf(1.0f); acoshf(1.0f); asinf(0.0f); asinhf(0.0f); atan2f(0.0f, 1.0f); atanf(0.0f); atanhf(0.0f); cbrtf(0.0f); ceilf(0.0f); copysignf(1.0f, -2.0f); cosf(0.0f); coshf(0.0f); //cospif(0.0f); //cyl_bessel_i0f(0.0f); //cyl_bessel_i1f(0.0f); erfcf(0.0f); //erfcinvf(2.0f); //erfcxf(0.0f); erff(0.0f); //erfinvf(1.0f); exp10f(0.0f); exp2f(0.0f); expf(0.0f); expm1f(0.0f); fabsf(1.0f); fdimf(1.0f, 0.0f); //fdividef(0.0f, 1.0f); floorf(0.0f); fmaf(1.0f, 2.0f, 3.0f); fmaxf(0.0f, 0.0f); fminf(0.0f, 0.0f); fmodf(0.0f, 1.0f); frexpf(0.0f, &iX); hypotf(1.0f, 0.0f); ilogbf(1.0f); isfinite(0.0f); isinf(0.0f); isnan(0.0f); ///j0f(0.0f); ///j1f(0.0f); ///jnf(-1.0f, 1.0f); ldexpf(0.0f, 0); ///lgammaf(1.0f); ///llrintf(0.0f); ///llroundf(0.0f); log10f(1.0f); log1pf(-1.0f); log2f(1.0f); logbf(1.0f); logf(1.0f); ///lrintf(0.0f); ///lroundf(0.0f); modff(0.0f, &fX); ///nanf("1"); nearbyintf(0.0f); //nextafterf(0.0f); //norm3df(1.0f, 0.0f, 0.0f); //norm4df(1.0f, 0.0f, 0.0f, 0.0f); //normcdff(0.0f); //normcdfinvf(1.0f); //fX = 1.0f; normf(1, &fX); powf(1.0f, 0.0f); //rcbrtf(1.0f); remainderf(2.0f, 1.0f); remquof(1.0f, 2.0f, &iX); //rhypotf(0.0f, 1.0f); ///rintf(1.0f); //rnorm3df(0.0f, 0.0f, 1.0f); //rnorm4df(0.0f, 0.0f, 0.0f, 1.0f); //fX = 1.0f; rnormf(1, &fX); roundf(0.0f); //rsqrtf(1.0f); ///scalblnf(0.0f, 1); scalbnf(0.0f, 1); signbit(1.0f); sincosf(0.0f, &fX, &fY); //sincospif(0.0f, &fX, &fY); sinf(0.0f); sinhf(0.0f); //sinpif(0.0f); sqrtf(0.0f); tanf(0.0f); tanhf(0.0f); tgammaf(2.0f); truncf(0.0f); ///y0f(1.0f); ///y1f(1.0f); ///ynf(1, 1.0f); }
void AudioInput::encodeAudioFrame() { int iArg; //ClientUser *p=ClientUser::get(g.uiSession); int i; float sum; short max; short *psSource; iFrameCounter++; if (! bRunning) { return; } MutexLocker l(&qmSpeex); bResetProcessor = false; if (bResetProcessor) { if (sppPreprocess) speex_preprocess_state_destroy(sppPreprocess); if (sesEcho) speex_echo_state_destroy(sesEcho); sppPreprocess = speex_preprocess_state_init(iFrameSize, iSampleRate); iArg = 1; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_VAD, &iArg); //speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_DENOISE, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_DEREVERB, &iArg); iArg = 30000; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_TARGET, &iArg); float v = 30000.0f / static_cast<float>(g_struct.s.iMinLoudness); iArg = (floorf(20.0f * log10f(v))); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &iArg); iArg = g_struct.s.iNoiseSuppress; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &iArg); if (iEchoChannels > 0) { sesEcho = speex_echo_state_init_mc(iFrameSize, iFrameSize*10, 1, bEchoMulti ? iEchoChannels : 1); iArg = iSampleRate; speex_echo_ctl(sesEcho, SPEEX_ECHO_SET_SAMPLING_RATE, &iArg); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, sesEcho); Trace("AudioInput: ECHO CANCELLER ACTIVE"); } else { sesEcho = NULL; } bResetProcessor = false; } int iIsSpeech=1; psSource = psMic; /* //回音消除和音质处理 if (bEcho && sesEcho && psSpeaker) { speex_echo_cancellation(sesEcho, psMic, psSpeaker, psClean); iIsSpeech=speex_preprocess_run(sppPreprocess, psClean); psSource = psClean; } else { iIsSpeech=speex_preprocess_run(sppPreprocess, psMic); psSource = psMic; }*/ /*sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psSource[i] * psSource[i]); float micLevel = sqrtf(sum / static_cast<float>(iFrameSize)); dPeakSignal=20.0f*log10f(micLevel / 32768.0f); if (dPeakSignal < -96.0f) dPeakSignal = -96.0f; spx_int32_t prob = 0; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_GET_PROB, &prob); fSpeechProb = static_cast<float>(prob) / 100.0f; float level = (g_struct.s.vsVAD == Settings::SignalToNoise) ? fSpeechProb : (1.0f + dPeakMic / 96.0f); if (level > g_struct.s.fVADmax) iIsSpeech = 1; else if (level > g_struct.s.fVADmin && bPreviousVoice) iIsSpeech = 1; else iIsSpeech = 0; if (! iIsSpeech) { iHoldFrames++; if (iHoldFrames < g_struct.s.iVoiceHold) iIsSpeech=1; } else { iHoldFrames = 0; }*/ //tIdle.restart(); /* int r = celt_encoder_ctl(ceEncoder, CELT_SET_POST_MDCT_CALLBACK(celtBack, NULL)); qWarning() << "Set Callback" << r; */ //编码 speex或者CELT unsigned char buffer[512]; int len; if (umtType == MessageHandler::UDPVoiceCELT) { if (cCodec == NULL) { cCodec = CELTCodec::instance(); ceEncoder = cCodec->encoderCreate(); } else if (cCodec && ! bPreviousVoice) { cCodec->encoder_ctl(ceEncoder, CELT_RESET_STATE); } cCodec->encoder_ctl(ceEncoder, CELT_SET_PREDICTION(0)); cCodec->encoder_ctl(ceEncoder,CELT_SET_BITRATE(iAudioQuality)); len = cCodec->encode(ceEncoder, psSource, SAMPLE_RATE / 50, buffer, 512); iBitrate = len * 50 * 8; /*//////////////////////////////////////////////////////////////////////// if (m_de_cdDecoder == NULL) { m_de_cdDecoder = cCodec->decoderCreate(); } celt_int16 fout2[2560]={0}; if (cCodec) { int len3 = cCodec->decode(m_de_cdDecoder, buffer, len, fout2, SAMPLE_RATE / 50); len3++; UINT dwDataWrote; if( FAILED(g_pWaveFile.Write( SAMPLE_RATE / 50*2*2, (BYTE*)fout2, &dwDataWrote ) )) { int a=0; a++; } else { OutputDebugString(L"plushuwav g_pWaveFile.Write 3"); } } ///////////////////////////////////////////////////////////////////////*/ } else { assert(0); } QByteArray qba; for(int i=0; i<len; i++) { qba.push_back(buffer[i]); } flushCheck(qba, false); if (! iIsSpeech) iBitrate = 0; bPreviousVoice = iIsSpeech; }
int process_cl(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out) { dt_iop_global_tonemap_data_t *d = (dt_iop_global_tonemap_data_t *)piece->data; dt_iop_global_tonemap_global_data_t *gd = (dt_iop_global_tonemap_global_data_t *)self->data; dt_iop_global_tonemap_gui_data_t *g = (dt_iop_global_tonemap_gui_data_t *)self->gui_data; dt_bilateral_cl_t *b = NULL; cl_int err = -999; cl_mem dev_m = NULL; cl_mem dev_r = NULL; float *maximum = NULL; const int devid = piece->pipe->devid; int gtkernel = -1; const int width = roi_out->width; const int height = roi_out->height; float parameters[4] = { 0.0f }; switch(d->operator) { case OPERATOR_REINHARD: gtkernel = gd->kernel_global_tonemap_reinhard; break; case OPERATOR_DRAGO: gtkernel = gd->kernel_global_tonemap_drago; break; case OPERATOR_FILMIC: gtkernel = gd->kernel_global_tonemap_filmic; break; } if(d->operator== OPERATOR_DRAGO) { const float eps = 0.0001f; float tmp_lwmax = NAN; // see comments in process() about lwmax value if(self->dev->gui_attached && g && piece->pipe->type == DT_DEV_PIXELPIPE_FULL) { dt_pthread_mutex_lock(&g->lock); const uint64_t hash = g->hash; dt_pthread_mutex_unlock(&g->lock); if(hash != 0 && !dt_dev_sync_pixelpipe_hash(self->dev, piece->pipe, 0, self->priority, &g->lock, &g->hash)) dt_control_log(_("inconsistent output")); dt_pthread_mutex_lock(&g->lock); tmp_lwmax = g->lwmax; dt_pthread_mutex_unlock(&g->lock); } if(isnan(tmp_lwmax)) { dt_opencl_local_buffer_t flocopt = (dt_opencl_local_buffer_t){ .xoffset = 0, .xfactor = 1, .yoffset = 0, .yfactor = 1, .cellsize = sizeof(float), .overhead = 0, .sizex = 1 << 4, .sizey = 1 << 4 }; if(!dt_opencl_local_buffer_opt(devid, gd->kernel_pixelmax_first, &flocopt)) goto error; const size_t bwidth = ROUNDUP(width, flocopt.sizex); const size_t bheight = ROUNDUP(height, flocopt.sizey); const int bufsize = (bwidth / flocopt.sizex) * (bheight / flocopt.sizey); dt_opencl_local_buffer_t slocopt = (dt_opencl_local_buffer_t){ .xoffset = 0, .xfactor = 1, .yoffset = 0, .yfactor = 1, .cellsize = sizeof(float), .overhead = 0, .sizex = 1 << 16, .sizey = 1 }; if(!dt_opencl_local_buffer_opt(devid, gd->kernel_pixelmax_second, &slocopt)) goto error; const int reducesize = MIN(REDUCESIZE, ROUNDUP(bufsize, slocopt.sizex) / slocopt.sizex); size_t sizes[3]; size_t local[3]; dev_m = dt_opencl_alloc_device_buffer(devid, (size_t)bufsize * sizeof(float)); if(dev_m == NULL) goto error; dev_r = dt_opencl_alloc_device_buffer(devid, (size_t)reducesize * sizeof(float)); if(dev_r == NULL) goto error; sizes[0] = bwidth; sizes[1] = bheight; sizes[2] = 1; local[0] = flocopt.sizex; local[1] = flocopt.sizey; local[2] = 1; dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_first, 0, sizeof(cl_mem), &dev_in); dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_first, 1, sizeof(int), &width); dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_first, 2, sizeof(int), &height); dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_first, 3, sizeof(cl_mem), &dev_m); dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_first, 4, flocopt.sizex * flocopt.sizey * sizeof(float), NULL); err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_pixelmax_first, sizes, local); if(err != CL_SUCCESS) goto error; sizes[0] = reducesize * slocopt.sizex; sizes[1] = 1; sizes[2] = 1; local[0] = slocopt.sizex; local[1] = 1; local[2] = 1; dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_second, 0, sizeof(cl_mem), &dev_m); dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_second, 1, sizeof(cl_mem), &dev_r); dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_second, 2, sizeof(int), &bufsize); dt_opencl_set_kernel_arg(devid, gd->kernel_pixelmax_second, 3, slocopt.sizex * sizeof(float), NULL); err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_pixelmax_second, sizes, local); if(err != CL_SUCCESS) goto error; maximum = dt_alloc_align(16, reducesize * sizeof(float)); err = dt_opencl_read_buffer_from_device(devid, (void *)maximum, dev_r, 0, (size_t)reducesize * sizeof(float), CL_TRUE); if(err != CL_SUCCESS) goto error; dt_opencl_release_mem_object(dev_r); dt_opencl_release_mem_object(dev_m); dev_r = dev_m = NULL; for(int k = 1; k < reducesize; k++) { float mine = maximum[0]; float other = maximum[k]; maximum[0] = (other > mine) ? other : mine; } tmp_lwmax = MAX(eps, (maximum[0] * 0.01f)); dt_free_align(maximum); maximum = NULL; } const float lwmax = tmp_lwmax; const float ldc = d->drago.max_light * 0.01f / log10f(lwmax + 1.0f); const float bl = logf(MAX(eps, d->drago.bias)) / logf(0.5f); parameters[0] = eps; parameters[1] = ldc; parameters[2] = bl; parameters[3] = lwmax; if(self->dev->gui_attached && g && piece->pipe->type == DT_DEV_PIXELPIPE_PREVIEW) { uint64_t hash = dt_dev_hash_plus(self->dev, piece->pipe, 0, self->priority); dt_pthread_mutex_lock(&g->lock); g->lwmax = lwmax; g->hash = hash; dt_pthread_mutex_unlock(&g->lock); } } const float scale = piece->iscale / roi_in->scale; const float sigma_r = 8.0f; // does not depend on scale const float iw = piece->buf_in.width / scale; const float ih = piece->buf_in.height / scale; const float sigma_s = fminf(iw, ih) * 0.03f; if(d->detail != 0.0f) { b = dt_bilateral_init_cl(devid, roi_in->width, roi_in->height, sigma_s, sigma_r); if(!b) goto error; // get detail from unchanged input buffer err = dt_bilateral_splat_cl(b, dev_in); if(err != CL_SUCCESS) goto error; } size_t sizes[2] = { ROUNDUPWD(width), ROUNDUPHT(height) }; dt_opencl_set_kernel_arg(devid, gtkernel, 0, sizeof(cl_mem), &dev_in); dt_opencl_set_kernel_arg(devid, gtkernel, 1, sizeof(cl_mem), &dev_out); dt_opencl_set_kernel_arg(devid, gtkernel, 2, sizeof(int), &width); dt_opencl_set_kernel_arg(devid, gtkernel, 3, sizeof(int), &height); dt_opencl_set_kernel_arg(devid, gtkernel, 4, 4 * sizeof(float), ¶meters); err = dt_opencl_enqueue_kernel_2d(devid, gtkernel, sizes); if(err != CL_SUCCESS) goto error; if(d->detail != 0.0f) { err = dt_bilateral_blur_cl(b); if(err != CL_SUCCESS) goto error; // and apply it to output buffer after logscale err = dt_bilateral_slice_to_output_cl(b, dev_in, dev_out, d->detail); if(err != CL_SUCCESS) goto error; dt_bilateral_free_cl(b); } return TRUE; error: if(b) dt_bilateral_free_cl(b); dt_opencl_release_mem_object(dev_m); dt_opencl_release_mem_object(dev_r); dt_free_align(maximum); dt_print(DT_DEBUG_OPENCL, "[opencl_global_tonemap] couldn't enqueue kernel! %d\n", err); return FALSE; } #endif void tiling_callback(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out, struct dt_develop_tiling_t *tiling) { dt_iop_global_tonemap_data_t *d = (dt_iop_global_tonemap_data_t *)piece->data; const float scale = piece->iscale / roi_in->scale; const float iw = piece->buf_in.width / scale; const float ih = piece->buf_in.height / scale; const float sigma_s = fminf(iw, ih) * 0.03f; const float sigma_r = 8.0f; const int detail = (d->detail != 0.0f); const int width = roi_in->width; const int height = roi_in->height; const int channels = piece->colors; const size_t basebuffer = width * height * channels * sizeof(float); tiling->factor = 2.0f + (detail ? (float)dt_bilateral_memory_use2(width, height, sigma_s, sigma_r) / basebuffer : 0.0f); tiling->maxbuf = (detail ? MAX(1.0f, (float)dt_bilateral_singlebuffer_size2(width, height, sigma_s, sigma_r) / basebuffer) : 1.0f); tiling->overhead = 0; tiling->overlap = (detail ? ceilf(4 * sigma_s) : 0); tiling->xalign = 1; tiling->yalign = 1; return; } void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece) { dt_iop_global_tonemap_params_t *p = (dt_iop_global_tonemap_params_t *)p1; dt_iop_global_tonemap_data_t *d = (dt_iop_global_tonemap_data_t *)piece->data; d->operator= p->operator; d->drago.bias = p->drago.bias; d->drago.max_light = p->drago.max_light; d->detail = p->detail; // drago needs the maximum L-value of the whole image so it must not use tiling if(d->operator == OPERATOR_DRAGO) piece->process_tiling_ready = 0; #ifdef HAVE_OPENCL if(d->detail != 0.0f) piece->process_cl_ready = (piece->process_cl_ready && !(darktable.opencl->avoid_atomics)); #endif }
static int testf(float float_x, long double long_double_x, /*float complex float_complex_x,*/ int int_x, long long_x) { int r = 0; r += acosf(float_x); r += acoshf(float_x); r += asinf(float_x); r += asinhf(float_x); r += atan2f(float_x, float_x); r += atanf(float_x); r += atanhf(float_x); /*r += cargf(float_complex_x); - will fight with complex numbers later */ r += cbrtf(float_x); r += ceilf(float_x); r += copysignf(float_x, float_x); r += cosf(float_x); r += coshf(float_x); r += erfcf(float_x); r += erff(float_x); r += exp2f(float_x); r += expf(float_x); r += expm1f(float_x); r += fabsf(float_x); r += fdimf(float_x, float_x); r += floorf(float_x); r += fmaf(float_x, float_x, float_x); r += fmaxf(float_x, float_x); r += fminf(float_x, float_x); r += fmodf(float_x, float_x); r += frexpf(float_x, &int_x); r += gammaf(float_x); r += hypotf(float_x, float_x); r += ilogbf(float_x); r += ldexpf(float_x, int_x); r += lgammaf(float_x); r += llrintf(float_x); r += llroundf(float_x); r += log10f(float_x); r += log1pf(float_x); r += log2f(float_x); r += logbf(float_x); r += logf(float_x); r += lrintf(float_x); r += lroundf(float_x); r += modff(float_x, &float_x); r += nearbyintf(float_x); r += nexttowardf(float_x, long_double_x); r += powf(float_x, float_x); r += remainderf(float_x, float_x); r += remquof(float_x, float_x, &int_x); r += rintf(float_x); r += roundf(float_x); #ifdef __UCLIBC_SUSV3_LEGACY__ r += scalbf(float_x, float_x); #endif r += scalblnf(float_x, long_x); r += scalbnf(float_x, int_x); r += significandf(float_x); r += sinf(float_x); r += sinhf(float_x); r += sqrtf(float_x); r += tanf(float_x); r += tanhf(float_x); r += tgammaf(float_x); r += truncf(float_x); return r; }
float est_voicing_mbe( MODEL *model, COMP Sw[], COMP W[], COMP Sw_[], /* DFT of all voiced synthesised signal */ /* useful for debugging/dump file */ COMP Ew[]) /* DFT of error */ { int i,l,al,bl,m; /* loop variables */ COMP Am; /* amplitude sample for this band */ int offset; /* centers Hw[] about current harmonic */ float den; /* denominator of Am expression */ float error; /* accumulated error between original and synthesised */ float Wo; float sig, snr; float elow, ehigh, eratio; float sixty; sig = 1E-4; for(l=1; l<=model->L/4; l++) { sig += model->A[l]*model->A[l]; } for(i=0; i<FFT_ENC; i++) { Sw_[i].real = 0.0; Sw_[i].imag = 0.0; Ew[i].real = 0.0; Ew[i].imag = 0.0; } Wo = model->Wo; error = 1E-4; /* Just test across the harmonics in the first 1000 Hz (L/4) */ for(l=1; l<=model->L/4; l++) { Am.real = 0.0; Am.imag = 0.0; den = 0.0; al = ceil((l - 0.5)*Wo*FFT_ENC/TWO_PI); bl = ceil((l + 0.5)*Wo*FFT_ENC/TWO_PI); /* Estimate amplitude of harmonic assuming harmonic is totally voiced */ offset = FFT_ENC/2 - l*Wo*FFT_ENC/TWO_PI + 0.5; for(m=al; m<bl; m++) { Am.real += Sw[m].real*W[offset+m].real; Am.imag += Sw[m].imag*W[offset+m].real; den += W[offset+m].real*W[offset+m].real; } Am.real = Am.real/den; Am.imag = Am.imag/den; /* Determine error between estimated harmonic and original */ offset = FFT_ENC/2 - l*Wo*FFT_ENC/TWO_PI + 0.5; for(m=al; m<bl; m++) { Sw_[m].real = Am.real*W[offset+m].real; Sw_[m].imag = Am.imag*W[offset+m].real; Ew[m].real = Sw[m].real - Sw_[m].real; Ew[m].imag = Sw[m].imag - Sw_[m].imag; error += Ew[m].real*Ew[m].real; error += Ew[m].imag*Ew[m].imag; } } snr = 10.0*log10f(sig/error); if (snr > V_THRESH) model->voiced = 1; else model->voiced = 0; /* post processing, helps clean up some voicing errors ------------------*/ /* Determine the ratio of low freqency to high frequency energy, voiced speech tends to be dominated by low frequency energy, unvoiced by high frequency. This measure can be used to determine if we have made any gross errors. */ elow = ehigh = 1E-4; for(l=1; l<=model->L/2; l++) { elow += model->A[l]*model->A[l]; } for(l=model->L/2; l<=model->L; l++) { ehigh += model->A[l]*model->A[l]; } eratio = 10.0*log10f(elow/ehigh); /* Look for Type 1 errors, strongly V speech that has been accidentally declared UV */ if (model->voiced == 0) if (eratio > 10.0) model->voiced = 1; /* Look for Type 2 errors, strongly UV speech that has been accidentally declared V */ if (model->voiced == 1) { if (eratio < -10.0) model->voiced = 0; /* A common source of Type 2 errors is the pitch estimator gives a low (50Hz) estimate for UV speech, which gives a good match with noise due to the close harmoonic spacing. These errors are much more common than people with 50Hz3 pitch, so we have just a small eratio threshold. */ sixty = 60.0*TWO_PI/FS; if ((eratio < -4.0) && (model->Wo <= sixty)) model->voiced = 0; } //printf(" v: %d snr: %f eratio: %3.2f %f\n",model->voiced,snr,eratio,dF0); return snr; }
void ff_sipr_decode_frame_16k(SiprContext *ctx, SiprParameters *params, float *out_data) { int frame_size = SUBFRAME_COUNT_16k * L_SUBFR_16k; float *synth = ctx->synth_buf + LP_FILTER_ORDER_16k; float lsf_new[LP_FILTER_ORDER_16k]; double lsp_new[LP_FILTER_ORDER_16k]; float Az[2][LP_FILTER_ORDER_16k]; float fixed_vector[L_SUBFR_16k]; float pitch_fac, gain_code; int i; int pitch_delay_3x; float *excitation = ctx->excitation + 292; lsf_decode_fp_16k(ctx->lsf_history, lsf_new, params->vq_indexes, params->ma_pred_switch); ff_set_min_dist_lsf(lsf_new, LSFQ_DIFF_MIN / 2, LP_FILTER_ORDER_16k); lsf2lsp(lsf_new, lsp_new); acelp_lp_decodef(Az[0], Az[1], lsp_new, ctx->lsp_history_16k); memcpy(ctx->lsp_history_16k, lsp_new, LP_FILTER_ORDER_16k * sizeof(double)); memcpy(synth - LP_FILTER_ORDER_16k, ctx->synth, LP_FILTER_ORDER_16k * sizeof(*synth)); for (i = 0; i < SUBFRAME_COUNT_16k; i++) { int i_subfr = i * L_SUBFR_16k; AMRFixed f; float gain_corr_factor; int pitch_delay_int; int pitch_delay_frac; if (!i) { pitch_delay_3x = dec_delay3_1st(params->pitch_delay[i]); } else pitch_delay_3x = dec_delay3_2nd(params->pitch_delay[i], PITCH_MIN, PITCH_MAX, ctx->pitch_lag_prev); pitch_fac = gain_pitch_cb_16k[params->gp_index[i]]; f.pitch_fac = FFMIN(pitch_fac, 1.0); f.pitch_lag = DIVIDE_BY_3(pitch_delay_3x+1); ctx->pitch_lag_prev = f.pitch_lag; pitch_delay_int = DIVIDE_BY_3(pitch_delay_3x + 2); pitch_delay_frac = pitch_delay_3x + 2 - 3*pitch_delay_int; ff_acelp_interpolatef(&excitation[i_subfr], &excitation[i_subfr] - pitch_delay_int + 1, sinc_win, 3, pitch_delay_frac + 1, LP_FILTER_ORDER, L_SUBFR_16k); memset(fixed_vector, 0, sizeof(fixed_vector)); ff_decode_10_pulses_35bits(params->fc_indexes[i], &f, ff_fc_4pulses_8bits_tracks_13, 5, 4); ff_set_fixed_vector(fixed_vector, &f, 1.0, L_SUBFR_16k); gain_corr_factor = gain_cb_16k[params->gc_index[i]]; gain_code = gain_corr_factor * acelp_decode_gain_codef(sqrt(L_SUBFR_16k), fixed_vector, 19.0 - 15.0/(0.05*M_LN10/M_LN2), pred_16k, ctx->energy_history, L_SUBFR_16k, 2); ctx->energy_history[1] = ctx->energy_history[0]; ctx->energy_history[0] = 20.0 * log10f(gain_corr_factor); ff_weighted_vector_sumf(&excitation[i_subfr], &excitation[i_subfr], fixed_vector, pitch_fac, gain_code, L_SUBFR_16k); ff_celp_lp_synthesis_filterf(synth + i_subfr, Az[i], &excitation[i_subfr], L_SUBFR_16k, LP_FILTER_ORDER_16k); } memcpy(ctx->synth, synth + frame_size - LP_FILTER_ORDER_16k, LP_FILTER_ORDER_16k * sizeof(*synth)); memmove(ctx->excitation, ctx->excitation + 2 * L_SUBFR_16k, (L_INTERPOL+PITCH_MAX) * sizeof(float)); postfilter(out_data, synth, ctx->iir_mem, ctx->filt_mem, ctx->mem_preemph); memcpy(ctx->iir_mem, Az[1], LP_FILTER_ORDER_16k * sizeof(float)); }
int main(int argc, char *argv[]) { uint16_t *addr_in; float *addr_out; int fd_in; int fd_out; struct stat sb; size_t length; uint64_t fftlen; size_t num_ffts; size_t index; if (argc < 4|| argc > 5) { fprintf(stderr, "%s filein fileout fftlength [nthreads]\n", argv[0]); exit(EXIT_FAILURE); } fd_in = open(argv[1], O_RDONLY|O_LARGEFILE); if (fd_in == -1) handle_error("in open"); fd_out = open(argv[2], O_LARGEFILE|O_CREAT|O_TRUNC|O_RDWR, 0666); if (fd_out == -1) handle_error("out open"); fftlen = atoll(argv[3]); int nthreads = (argc == 5) ? 4 : atoi(argv[4]); posix_fallocate(fd_out, 0, fftlen* sizeof(float)); if (fstat(fd_in, &sb) == -1) /* To obtain file size */ handle_error("fstat"); length = sb.st_size; //two bytes per short, two shorts per complex value num_ffts = length/fftlen; //map the input into memory. addr_in = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd_in, 0); if (addr_in == MAP_FAILED) handle_error("input mmap"); //map the output into memory. addr_out = mmap(NULL, fftlen*sizeof(float), PROT_WRITE, MAP_SHARED, fd_out, 0); if (addr_out == MAP_FAILED) handle_error("output mmap"); //fftwf stuff fftwf_init_threads(); fftwf_plan_with_nthreads(nthreads); fftwf_complex *in, *out; fftwf_plan my_plan; in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*fftlen); out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*fftlen); my_plan = fftwf_plan_dft_1d(fftlen, in, out, FFTW_FORWARD, FFTW_ESTIMATE); float *fin = (float*)in; float *fout = (float*)out; for(index = 0; index < fftlen*2; index++) { float tmp = (float) addr_in[index]; fin[index] =tmp; } addr_in += 2 * fftlen; //run that FFT fftwf_execute(my_plan); //calculate Power size_t currindex=0; float real, imag; for(index = 0; index < fftlen; index++) { real = fout[currindex++]; imag = fout[currindex++]; addr_out[index] = 10.0f*log10f( real * real + imag * imag ); } fftwf_destroy_plan(my_plan); fftwf_free(in); fftwf_free(out); msync(addr_out, fftlen * sizeof(float), MS_SYNC); exit(EXIT_SUCCESS); }
int run_tests() { int result = 0; /* Complex string */ snprintf(str, 256, "y=26*2/2+log10(pi)+2.*pow(2,1*(3+7*.1)*1.1+x{0}[0])*3*4+cos(2.)"); setup_test('f', 1, 1, src_float, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %g\n", 26*2/2+log10f(M_PI)+2.f *powf(2,1*(3+7*.1f)*1.1f+src_float[0])*3*4+cosf(2.0f)); /* Building vectors, conditionals */ snprintf(str, 256, "y=(x>1)?[1,2,3]:[2,4,6]"); setup_test('f', 1, 3, src_float, 'i', 1, 3, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%i, %i, %i]\n", src_float[0]>1?1:2, src_float[1]>1?2:4, src_float[2]>1?3:6); /* Conditionals with shortened syntax */ snprintf(str, 256, "y=x?:123"); setup_test('f', 1, 1, src_float, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %i\n", (int)src_float[0]?:123); /* Conditional that should be optimized */ snprintf(str, 256, "y=1?2:123"); setup_test('f', 1, 1, src_float, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: 2\n"); /* Building vectors with variables, operations inside vector-builder */ snprintf(str, 256, "y=[x*-2+1,0]"); setup_test('i', 1, 2, src_int, 'd', 1, 3, dest_double); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%g, %g, %g]\n", (double)src_int[0]*-2+1, (double)src_int[1]*-2+1, 0.0); /* Building vectors with variables, operations inside vector-builder */ snprintf(str, 256, "y=[-99.4, -x*1.1+x]"); setup_test('i', 1, 2, src_int, 'd', 1, 3, dest_double); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%g, %g, %g]\n", -99.4, (double)(-src_int[0]*1.1+src_int[0]), (double)(-src_int[1]*1.1+src_int[1])); /* Indexing vectors by range */ snprintf(str, 256, "y=x[1:2]+100"); setup_test('d', 1, 3, src_double, 'f', 1, 2, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%g, %g]\n", (float)src_double[1]+100, (float)src_double[2]+100); /* Typical linear scaling expression with vectors */ snprintf(str, 256, "y=x*[0.1,3.7,-.1112]+[2,1.3,9000]"); setup_test('f', 1, 3, src_float, 'f', 1, 3, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%g, %g, %g]\n", src_float[0]*0.1f+2.f, src_float[1]*3.7f+1.3f, src_float[2]*-.1112f+9000.f); /* Check type and vector length promotion of operation sequences */ snprintf(str, 256, "y=1+2*3-4*x"); setup_test('f', 1, 2, src_float, 'f', 1, 2, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%g, %g]\n", 1.f+2.f*3.f-4.f*src_float[0], 1.f+2.f*3.f-4.f*src_float[1]); /* Swizzling, more pre-computation */ snprintf(str, 256, "y=[x[2],x[0]]*0+1+12"); setup_test('f', 1, 3, src_float, 'f', 1, 2, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%g, %g]\n", src_float[2]*0.f+1.f+12.f, src_float[0]*0.f+1.f+12.f); /* Logical negation */ snprintf(str, 256, "y=!(x[1]*0)"); setup_test('d', 1, 3, src_double, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %i\n", (int)!(src_double[1]*0)); /* any() */ snprintf(str, 256, "y=any(x-1)"); setup_test('d', 1, 3, src_double, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %i\n", ((int)src_double[0]-1)?1:0 | ((int)src_double[1]-1)?1:0 | ((int)src_double[2]-1)?1:0); /* all() */ snprintf(str, 256, "y=x[2]*all(x-1)"); setup_test('d', 1, 3, src_double, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); int temp = ((int)src_double[0]-1)?1:0 & ((int)src_double[1]-1)?1:0 & ((int)src_double[2]-1)?1:0; eprintf("Expected: %i\n", (int)src_double[2] * temp); /* pi and e, extra spaces */ snprintf(str, 256, "y=x + pi - e"); setup_test('d', 1, 1, src_double, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %g\n", (float)(src_double[0]+M_PI-M_E)); /* bad vector notation */ snprintf(str, 256, "y=(x-2)[1]"); setup_test('i', 1, 1, src_int, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* vector index outside bounds */ snprintf(str, 256, "y=x[3]"); setup_test('i', 1, 3, src_int, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* vector length mismatch */ snprintf(str, 256, "y=x[1:2]"); setup_test('i', 1, 3, src_int, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* unnecessary vector notation */ snprintf(str, 256, "y=x+[1]"); setup_test('i', 1, 1, src_int, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %i\n", src_int[0]+1); /* invalid history index */ snprintf(str, 256, "y=x{-101}"); setup_test('i', 1, 1, src_int, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* invalid history index */ snprintf(str, 256, "y=x-y{-101}"); setup_test('i', 1, 1, src_int, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* scientific notation */ snprintf(str, 256, "y=x[1]*1.23e-20"); setup_test('i', 1, 2, src_int, 'd', 1, 1, dest_double); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %g\n", (double)src_int[1] * 1.23e-20); /* Vector assignment */ snprintf(str, 256, "y[1]=x[1]"); setup_test('d', 1, 3, src_double, 'i', 1, 3, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [NULL, %i, NULL]\n", (int)src_double[1]); /* Vector assignment */ snprintf(str, 256, "y[1:2]=[x[1],10]"); setup_test('d', 1, 3, src_double, 'i', 1, 3, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [NULL, %i, %i]\n", (int)src_double[1], 10); /* Output vector swizzling */ snprintf(str, 256, "[y[0],y[2]]=x[1:2]"); setup_test('f', 1, 3, src_float, 'd', 1, 3, dest_double); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%g, NULL, %g]\n", (double)src_float[1], (double)src_float[2]); /* Multiple expressions */ snprintf(str, 256, "y[0]=x*100-23.5; y[2]=100-x*6.7"); setup_test('i', 1, 1, src_int, 'f', 1, 3, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* Error check: separating sub-expressions with commas */ snprintf(str, 256, "foo=1, y=y{-1}+foo"); setup_test('i', 1, 1, src_int, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* Initialize filters */ snprintf(str, 256, "y=x+y{-1}; y{-1}=100"); setup_test('i', 1, 1, src_int, 'i', 2, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %i\n", src_int[0]*iterations + 100); /* Initialize filters + vector index */ snprintf(str, 256, "y=x+y{-1}; y[1]{-1}=100"); setup_test('i', 1, 2, src_int, 'i', 2, 2, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%i, %i]\n", src_int[0]*iterations, src_int[1]*iterations + 100); /* Initialize filters + vector index */ snprintf(str, 256, "y=x+y{-1}; y{-1}=[100,101]"); setup_test('i', 1, 2, src_int, 'i', 2, 2, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%i, %i]\n", src_int[0]*iterations + 100, src_int[1]*iterations + 101); /* Initialize filters */ snprintf(str, 256, "y=x+y{-1}; y[0]{-1}=100; y[2]{-1}=200"); setup_test('i', 1, 3, src_int, 'i', 2, 3, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [%i, %i, %i]\n", src_int[0]*iterations + 100, src_int[1]*iterations, src_int[2]*iterations + 200); /* Initialize filters */ snprintf(str, 256, "y=x+y{-1}-y{-2}; y{-1}=[100,101]; y{-2}=[100,101]"); setup_test('i', 1, 2, src_int, 'i', 3, 2, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: [1, 2]\n"); /* Only initialize */ snprintf(str, 256, "y{-1}=100"); setup_test('i', 1, 3, src_int, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* Some examples of bad syntax */ strcpy(str, ""); setup_test('i', 1, 1, src_int, 'f', 1, 3, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); snprintf(str, 256, " "); setup_test('i', 1, 1, src_int, 'f', 1, 3, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); snprintf(str, 256, "y"); setup_test('i', 1, 1, src_int, 'f', 1, 3, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); snprintf(str, 256, "y="); setup_test('i', 1, 1, src_int, 'f', 1, 3, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); snprintf(str, 256, "=x"); setup_test('i', 1, 1, src_int, 'f', 1, 3, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); snprintf(str, 256, "sin(x)"); setup_test('i', 1, 1, src_int, 'f', 1, 3, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* Variable declaration */ snprintf(str, 256, "var=3.5; y=x+var"); setup_test('i', 1, 1, src_int, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %g\n", (float)src_int[0] + 3.5); /* Variable declaration */ snprintf(str, 256, "ema=ema{-1}*0.9+x*0.1; y=ema*2; ema{-1}=90"); setup_test('i', 1, 1, src_int, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: 2\n"); /* Use of uninitialized variable */ snprintf(str, 256, "y=x + myvariable * 10"); setup_test('i', 1, 1, src_int, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); /* Vector functions mean() and sum() */ snprintf(str, 256, "y=mean(x)==(sum(x)/3)"); setup_test('f', 1, 3, src_float, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %i\n", 1); /* Overloaded vector functions max() and min() */ snprintf(str, 256, "y=max(x)-min(x)"); setup_test('f', 1, 3, src_float, 'i', 1, 1, dest_int); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: %i\n", ((src_float[0]>src_float[1])? (src_float[0]>src_float[2]?(int)src_float[0]:(int)src_float[2]): (src_float[1]>src_float[2]?(int)src_float[1]:(int)src_float[2])) - ((src_float[0]<src_float[1])? (src_float[0]<src_float[2]?(int)src_float[0]:(int)src_float[2]): (src_float[1]<src_float[2]?(int)src_float[1]:(int)src_float[2]))); /* Optimization: operations by zero */ snprintf(str, 256, "y=0*sin(x)*200+1.1"); setup_test('i', 1, 1, src_int, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: 1.1\n"); /* Optimization: operations by one */ snprintf(str, 256, "y=x*1"); setup_test('i', 1, 1, src_int, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_SUCCESS); eprintf("Expected: 1\n"); /* Error check: division by zero */ snprintf(str, 256, "y=x/0"); setup_test('i', 1, 1, src_int, 'f', 1, 1, dest_float); result += parse_and_eval(EXPECT_FAILURE); eprintf("Expected: FAILURE\n"); return result; }
void AudioInput::encodeAudioFrame() { int iArg; int i; float sum; short max; short *psSource; iFrameCounter++; if (! bRunning) return; sum=1.0f; max = 1; for (i=0;i<iFrameSize;i++) { sum += static_cast<float>(psMic[i] * psMic[i]); max = std::max(static_cast<short>(abs(psMic[i])), max); } dPeakMic = qMax(20.0f*log10f(sqrtf(sum / static_cast<float>(iFrameSize)) / 32768.0f), -96.0f); dMaxMic = max; if (psSpeaker && (iEchoChannels > 0)) { sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psSpeaker[i] * psSpeaker[i]); dPeakSpeaker = qMax(20.0f*log10f(sqrtf(sum / static_cast<float>(iFrameSize)) / 32768.0f), -96.0f); } else { dPeakSpeaker = 0.0; } QMutexLocker l(&qmSpeex); resetAudioProcessor(); speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_GET_AGC_GAIN, &iArg); float gainValue = static_cast<float>(iArg); iArg = g.s.iNoiseSuppress - iArg; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &iArg); if (sesEcho && psSpeaker) { speex_echo_cancellation(sesEcho, psMic, psSpeaker, psClean); speex_preprocess_run(sppPreprocess, psClean); psSource = psClean; } else { speex_preprocess_run(sppPreprocess, psMic); psSource = psMic; } sum=1.0f; for (i=0;i<iFrameSize;i++) sum += static_cast<float>(psSource[i] * psSource[i]); float micLevel = sqrtf(sum / static_cast<float>(iFrameSize)); dPeakSignal = qMax(20.0f*log10f(micLevel / 32768.0f), -96.0f); spx_int32_t prob = 0; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_GET_PROB, &prob); fSpeechProb = static_cast<float>(prob) / 100.0f; // clean microphone level: peak of filtered signal attenuated by AGC gain dPeakCleanMic = qMax(dPeakSignal - gainValue, -96.0f); float level = (g.s.vsVAD == Settings::SignalToNoise) ? fSpeechProb : (1.0f + dPeakCleanMic / 96.0f); bool bIsSpeech = false; if (level > g.s.fVADmax) bIsSpeech = true; else if (level > g.s.fVADmin && bPreviousVoice) bIsSpeech = true; if (! bIsSpeech) { iHoldFrames++; if (iHoldFrames < g.s.iVoiceHold) bIsSpeech = true; } else { iHoldFrames = 0; } if (g.s.atTransmit == Settings::Continuous) bIsSpeech = true; else if (g.s.atTransmit == Settings::PushToTalk) bIsSpeech = g.s.uiDoublePush && ((g.uiDoublePush < g.s.uiDoublePush) || (g.tDoublePush.elapsed() < g.s.uiDoublePush)); bIsSpeech = bIsSpeech || (g.iPushToTalk > 0); ClientUser *p = ClientUser::get(g.uiSession); if (g.s.bMute || ((g.s.lmLoopMode != Settings::Local) && p && (p->bMute || p->bSuppress)) || g.bPushToMute || (g.iTarget < 0)) { bIsSpeech = false; } if (bIsSpeech) { iSilentFrames = 0; } else { iSilentFrames++; if (iSilentFrames > 500) iFrameCounter = 0; } if (p) { if (! bIsSpeech) p->setTalking(Settings::Passive); else if (g.iTarget == 0) p->setTalking(Settings::Talking); else p->setTalking(Settings::Shouting); } if (g.s.bTxAudioCue && g.uiSession != 0) { AudioOutputPtr ao = g.ao; if (bIsSpeech && ! bPreviousVoice && ao) ao->playSample(g.s.qsTxAudioCueOn); else if (ao && !bIsSpeech && bPreviousVoice) ao->playSample(g.s.qsTxAudioCueOff); } if (! bIsSpeech && ! bPreviousVoice) { iBitrate = 0; if (g.s.iaeIdleAction != Settings::Nothing && ((tIdle.elapsed() / 1000000ULL) > g.s.iIdleTime)) { if (g.s.iaeIdleAction == Settings::Deafen && !g.s.bDeaf) { tIdle.restart(); emit doDeaf(); } else if (g.s.iaeIdleAction == Settings::Mute && !g.s.bMute) { tIdle.restart(); emit doMute(); } } spx_int32_t increment = 0; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_INCREMENT, &increment); return; } else { spx_int32_t increment = 12; speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_INCREMENT, &increment); } if (bIsSpeech && !bPreviousVoice) { bResetEncoder = true; } tIdle.restart(); EncodingOutputBuffer buffer; Q_ASSERT(buffer.size() >= static_cast<size_t>(iAudioQuality / 100 * iAudioFrames / 8)); int len = 0; bool encoded = true; if (!selectCodec()) return; if (umtType == MessageHandler::UDPVoiceCELTAlpha || umtType == MessageHandler::UDPVoiceCELTBeta) { len = encodeCELTFrame(psSource, buffer); if (len <= 0) { iBitrate = 0; qWarning() << "encodeCELTFrame failed" << iBufferedFrames << iFrameSize << len; return; } ++iBufferedFrames; } else if (umtType == MessageHandler::UDPVoiceOpus) { encoded = false; opusBuffer.insert(opusBuffer.end(), psSource, psSource + iFrameSize); ++iBufferedFrames; if (!bIsSpeech || iBufferedFrames >= iAudioFrames) { if (iBufferedFrames < iAudioFrames) { // Stuff frame to framesize if speech ends and we don't have enough audio // this way we are guaranteed to have a valid framecount and won't cause // a codec configuration switch by suddenly using a wildly different // framecount per packet. const int missingFrames = iAudioFrames - iBufferedFrames; opusBuffer.insert(opusBuffer.end(), iFrameSize * missingFrames, 0); iBufferedFrames += missingFrames; iFrameCounter += missingFrames; } Q_ASSERT(iBufferedFrames == iAudioFrames); len = encodeOpusFrame(&opusBuffer[0], iBufferedFrames * iFrameSize, buffer); opusBuffer.clear(); if (len <= 0) { iBitrate = 0; qWarning() << "encodeOpusFrame failed" << iBufferedFrames << iFrameSize << len; iBufferedFrames = 0; // These are lost. Make sure not to mess up our sequence counter next flushCheck. return; } encoded = true; } } if (encoded) { flushCheck(QByteArray(reinterpret_cast<char *>(&buffer[0]), len), !bIsSpeech); } if (! bIsSpeech) iBitrate = 0; bPreviousVoice = bIsSpeech; }
TEST(math, log10f) { ASSERT_FLOAT_EQ(3.0f, log10f(1000.0f)); }
int main(int argc, char*argv[]) { // options unsigned int k=4; // filter samples/symbol unsigned int m=3; // filter delay [symbols] float beta = 0.3f; // filter excess bandwidth factor // read properties from command line int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: %s, k must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, m must be at least 1\n", argv[0]); exit(1); } else if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, beta must be in (0,1)\n", argv[0]); exit(1); } unsigned int i; // derived values unsigned int h_len = 2*k*m+1; // filter length // arrays float ht[h_len]; // transmit filter coefficients float hr[h_len]; // recieve filter coefficients // // start of filter design procedure // float H_prime[h_len]; // frequency response of Nyquist filter float complex h_tx[h_len]; // impulse response of square-root Nyquist filter float complex H_tx[h_len]; // frequency response of square-root Nyquist filter // compute frequency response of Nyquist filter for (i=0; i<h_len; i++) { float f = (float)i / (float)h_len; if (f > 0.5f) f = f - 1.0f; H_prime[i] = firdes_freqresponse_fexp(f,k,beta); } // compute square-root response, copy to fft input for (i=0; i<h_len; i++) H_tx[i] = sqrtf(H_prime[i]); // compute ifft and copy response fft_run(h_len, H_tx, h_tx, LIQUID_FFT_BACKWARD, 0); for (i=0; i<h_len; i++) ht[i] = crealf( h_tx[(i+k*m+1)%h_len] ) / (float)(h_len); // copy receive... for (i=0; i<h_len; i++) hr[i] = ht[i]; #if 0 // print results for (i=0; i<h_len; i++) printf("H_prime(%3u) = %12.8f;\n", i+1, H_prime[i]); #endif // // end of filter design procedure // // print results to screen printf("fexp receive filter:\n"); for (i=0; i<h_len; i++) printf(" hr(%3u) = %12.8f;\n", i+1, hr[i]); // compute isi float rxy0 = liquid_filter_crosscorr(ht,h_len, hr,h_len, 0); float isi_rms = 0.0f; for (i=1; i<2*m; i++) { float e = liquid_filter_crosscorr(ht,h_len, hr,h_len, i*k) / rxy0; isi_rms += e*e; } isi_rms = sqrtf(isi_rms / (float)(2*m-1)); printf("\n"); printf("ISI (RMS) = %12.8f dB\n", 20*log10f(isi_rms)); // // export output file // FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"\n\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"m = %u;\n", m); fprintf(fid,"beta = %f;\n", beta); fprintf(fid,"h_len = 2*k*m+1;\n"); fprintf(fid,"nfft = 1024;\n"); fprintf(fid,"ht = zeros(1,h_len);\n"); fprintf(fid,"hp = zeros(1,h_len);\n"); fprintf(fid,"hr = zeros(1,h_len);\n"); // print results for (i=0; i<h_len; i++) fprintf(fid,"ht(%3u) = %12.4e;\n", i+1, ht[i]); for (i=0; i<h_len; i++) fprintf(fid,"hr(%3u) = %12.4e;\n", i+1, hr[i]); fprintf(fid,"hc = k*conv(ht,hr);\n"); // plot results fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"Ht = 20*log10(abs(fftshift(fft(ht, nfft))));\n"); fprintf(fid,"Hr = 20*log10(abs(fftshift(fft(hr, nfft))));\n"); fprintf(fid,"Hc = 20*log10(abs(fftshift(fft(hc/k,nfft))));\n"); fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f,Ht,'LineWidth',1,'Color',[0.00 0.25 0.50],...\n"); fprintf(fid," f,Hr,'LineWidth',1,'Color',[0.00 0.50 0.25],...\n"); fprintf(fid," f,Hc,'LineWidth',2,'Color',[0.50 0.00 0.00],...\n"); fprintf(fid," [-0.5/k 0.5/k], [1 1]*20*log10(0.5),'or');\n"); fprintf(fid,"legend('transmit','receive','composite','alias points',1);\n"); fprintf(fid,"xlabel('Normalized Frequency');\n"); fprintf(fid,"ylabel('PSD');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-0.5 0.5 -100 20]);\n"); fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"tr = [ -k*m:k*m]/k;\n"); fprintf(fid,"tc = [-2*k*m:2*k*m]/k;\n"); fprintf(fid,"ic = [0:k:(4*k*m)]+1;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(tr,ht,'-x', tr,hr,'-x');\n"); fprintf(fid," legend('transmit','receive',1);\n"); fprintf(fid," xlabel('Time');\n"); fprintf(fid," ylabel('fexp Tx/Rx Filters');\n"); fprintf(fid," grid on;\n"); fprintf(fid," axis([-2*m 2*m floor(5*min([hr ht]))/5 ceil(5*max([hr ht]))/5]);\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(tc,hc,'-x', tc(ic),hc(ic),'or');\n"); fprintf(fid," xlabel('Time');\n"); fprintf(fid," ylabel('fexp Composite Response');\n"); fprintf(fid," grid on;\n"); fprintf(fid," axis([-2*m 2*m -0.2 1.2]);\n"); fprintf(fid," axis([-2*m 2*m floor(5*min(hc))/5 ceil(5*max(hc))/5]);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); return 0; }
static gboolean spectrogram_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data) { w_spectrogram_t *w = user_data; GtkAllocation a; gtk_widget_get_allocation (widget, &a); if (!w->samples || a.height < 1) { return FALSE; } int width, height; width = a.width; height = a.height; int ratio = ftoi (FFT_SIZE/(a.height*2)); ratio = CLAMP (ratio,0,1023); if (deadbeef->get_output ()->state () == OUTPUT_STATE_PLAYING) { do_fft (w); float log_scale = (log2f(w->samplerate/2)-log2f(25.))/(a.height); float freq_res = w->samplerate / FFT_SIZE; if (a.height != w->height) { w->height = MIN (a.height, MAX_HEIGHT); for (int i = 0; i < w->height; i++) { w->log_index[i] = ftoi (powf(2.,((float)i) * log_scale + log2f(25.)) / freq_res); if (i > 0 && w->log_index[i-1] == w->log_index [i]) { w->low_res_end = i; } } } } // start drawing if (!w->surf || cairo_image_surface_get_width (w->surf) != a.width || cairo_image_surface_get_height (w->surf) != a.height) { if (w->surf) { cairo_surface_destroy (w->surf); w->surf = NULL; } w->surf = cairo_image_surface_create (CAIRO_FORMAT_RGB24, a.width, a.height); } cairo_surface_flush (w->surf); unsigned char *data = cairo_image_surface_get_data (w->surf); if (!data) { return FALSE; } int stride = cairo_image_surface_get_stride (w->surf); if (deadbeef->get_output ()->state () == OUTPUT_STATE_PLAYING) { for (int i = 0; i < a.height; i++) { // scrolling: move line i 1px to the left memmove (data + (i*stride), data + sizeof (uint32_t) + (i*stride), stride - sizeof (uint32_t)); } for (int i = 0; i < a.height; i++) { float f = 1.0; int index0, index1; int bin0, bin1, bin2; if (CONFIG_LOG_SCALE) { bin0 = w->log_index[CLAMP (i-1,0,height-1)]; bin1 = w->log_index[i]; bin2 = w->log_index[CLAMP (i+1,0,height-1)]; } else { bin0 = (i-1) * ratio; bin1 = i * ratio; bin2 = (i+1) * ratio; } index0 = bin0 + ftoi ((bin1 - bin0)/2.f); if (index0 == bin0) index0 = bin1; index1 = bin1 + ftoi ((bin2 - bin1)/2.f); if (index1 == bin2) index1 = bin1; index0 = CLAMP (index0,0,FFT_SIZE/2-1); index1 = CLAMP (index1,0,FFT_SIZE/2-1); f = spectrogram_get_value (w, index0, index1); float x = 10 * log10f (f); // interpolate if (i <= w->low_res_end && CONFIG_LOG_SCALE) { int j = 0; // find index of next value while (i+j < height && w->log_index[i+j] == w->log_index[i]) { j++; } float v0 = x; float v1 = w->data[w->log_index[i+j]]; if (v1 != 0) { v1 = 10 * log10f (v1); } int k = 0; while ((k+i) >= 0 && w->log_index[k+i] == w->log_index[i]) { j++; k--; } x = linear_interpolate (v0,v1,(1.0/(j-1)) * ((-1 * k) - 1)); } // TODO: get rid of hardcoding x += CONFIG_DB_RANGE - 63; x = CLAMP (x, 0, CONFIG_DB_RANGE); int color_index = GRADIENT_TABLE_SIZE - ftoi (GRADIENT_TABLE_SIZE/(float)CONFIG_DB_RANGE * x); color_index = CLAMP (color_index, 0, GRADIENT_TABLE_SIZE-1); _draw_point (data, stride, width-1, height-1-i, w->colors[color_index]); } } cairo_surface_mark_dirty (w->surf); cairo_save (cr); cairo_set_source_surface (cr, w->surf, 0, 0); cairo_rectangle (cr, 0, 0, a.width, a.height); cairo_fill (cr); cairo_restore (cr); return FALSE; }
/** * Converts amplitude level to decibel where an amplitude of 1 * relates to a decibel value of 0, and amplitude 0 related to -inf. */ static float amplitude_to_decibe(float a) { return log10f(fabsf(a))*20; }
/** * Handle the case of a vector consisting entirely (or almost entirely) of * integers. (If the cardinality of string values in a vector is 1 and that * unique string value looks a representation of missing data, the vector * is treated as if it were entirely integral.) This is the trickiest case * since it could be any or none of the 3 statistical classes. * * Heuristics. * 1. card({values}) < MAX_CATEGORY_CARDINALITY * The real question is whether or not categorical statistical tests * are applicable to a given vector. * Categorical methods are rarely applied to data with more than * MAX_CATEGORY_CARDINALITY categories. However, as the sample size * grows MAX_CATEGORY_CARDINALITY *can* grow as well. * 2. max(abs({values})) < MAX_VALUE * Although integers can serve as category labels it rarely makes * sense for those integers to have large absolute values. * Zip codes are a confounder of this heuristic. * 3. negative integers are almost never involved in categorical data * UNLESS they represent levels symmetric around 0...which further * constrains plausible max(abs({values})). * * Caveats: * 1. The current rationale will miss quantitative variables (of either * integral or floating-point type) that might be usefully treated as * categorical (e.g. a vector of zip codes containing only 3 distinct * values). Or even more extreme: an essentially boolean variable in * which the labels happen to be two large integers. * * For plausibly categorical cases might be better to consider number * of duplicate values (using value_bag instead of value_set). * */ static int _integer_inference( const struct column *c ) { int stat_class = STC_UNK; // ...unless overridden below. const int N = c->type_vote[ FTY_INTEGER ]; const double K = set_count( & c->value_set ); const int N_MAG = __builtin_popcount( c->integer_magnitudes ); if( c->excess_values ) { // It can only be ordinal or quantitative, and... if( c->has_negative_integers ) { // ...it's not ordinal. stat_class = STC_QUA; } else { const int MAX_MAG = (int)floorf( log10f( c->extrema[1] ) ); // Following can't positively id ordinal variables, // but it can positively rule them out. I'm sampling // the interval [1,N] divided into ranges by base-10 // magnitude. If data are missing in any range, it's // not strictly ordinal...or it's just missing some // data. TODO: See comments at top. if( ( N_MAG == MAX_MAG ) && ( (int)round(c->extrema[0]) == 1 ) && ( (int)round(c->extrema[1]) == N ) ) stat_class = STC_ORD; else stat_class = STC_QUA; } } else { // |{value_set}| <= MAX_CATEGORY_CARDINALITY // There are few enough values to treat it as a // categorical variable, but... if( c->has_negative_integers ) { // ...require all values to be in (-K,+K) where // K == MAX_ABSOLUTE_CATEGORICAL_VALUE // e.g. { -2, -1, 0, 1, 2 } with -2 indicating // "strongly dislike" and +2 "strongly like" stat_class = (-(MAX_ABSOLUTE_CATEGORICAL_VALUE/2) <= c->extrema[0]) && (c->extrema[1] <= +(MAX_ABSOLUTE_CATEGORICAL_VALUE/2)) ? STC_CAT : STC_QUA; } else { // The column takes on a "small" set of non-negative // integer values. Very likely categorical. The // relation between the cardinality of the value set // and the sample size is primary determinant now... stat_class = (K <= MAX_CATEGORY_CARDINALITY) && (c->extrema[1] <= MAX_ABSOLUTE_CATEGORICAL_VALUE) && (K < (N/2)) // 3rd clause is just a sanity check for very small // sample sizes. ? STC_CAT : STC_QUA; // Zip codes are a confounding case. They *can* be categorical, // but in a large sample they're more likely to be nominative-- // that is, non-statistical. } } return stat_class; }