/* * Apply the MDCT to input samples to generate frequency coefficients. * This applies the KBD window and normalizes the input to reduce precision * loss due to fixed-point calculations. */ static void apply_mdct(AC3EncodeContext *s) { int blk, ch; for (ch = 0; ch < s->channels; ch++) { for (blk = 0; blk < s->num_blocks; blk++) { AC3Block *block = &s->blocks[blk]; const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE]; #if CONFIG_AC3ENC_FLOAT apply_window(&s->fdsp, s->windowed_samples, input_samples, s->mdct_window, AC3_WINDOW_SIZE); #else apply_window(&s->dsp, s->windowed_samples, input_samples, s->mdct_window, AC3_WINDOW_SIZE); #endif if (s->fixed_point) block->coeff_shift[ch+1] = normalize_samples(s); s->mdct.mdct_calcw(&s->mdct, block->mdct_coef[ch+1], s->windowed_samples); } } }
/** * Hybrid window filtering, see blocks 36 and 49 of the G.728 specification. * * @param order filter order * @param n input length * @param non_rec number of non-recursive samples * @param out filter output * @param hist pointer to the input history of the filter * @param out pointer to the non-recursive part of the output * @param out2 pointer to the recursive part of the output * @param window pointer to the windowing function table */ static void do_hybrid_window(int order, int n, int non_rec, float *out, float *hist, float *out2, const float *window) { int i; #ifndef _MSC_VER float buffer1[order + 1]; float buffer2[order + 1]; float work[order + n + non_rec]; #else float *buffer1 = av_malloc_items(order + 1, float); float *buffer2 = av_malloc_items(order + 1, float); float *work = av_malloc_items(order + n + non_rec, float); #endif apply_window(work, window, hist, order + n + non_rec); convolve(buffer1, work + order , n , order); convolve(buffer2, work + order + n, non_rec, order); for (i=0; i <= order; i++) { out2[i] = out2[i] * 0.5625 + buffer1[i]; out [i] = out2[i] + buffer2[i]; } /* Multiply by the white noise correcting factor (WNCF). */ *out *= 257./256.; #ifdef _MSC_VER av_free(buffer1); av_free(buffer2); av_free(work); #endif }
/** * Hybrid window filtering, see blocks 36 and 49 of the G.728 specification. * * @param order filter order * @param n input length * @param non_rec number of non-recursive samples * @param out filter output * @param hist pointer to the input history of the filter * @param out pointer to the non-recursive part of the output * @param out2 pointer to the recursive part of the output * @param window pointer to the windowing function table */ static void do_hybrid_window(int order, int n, int non_rec, float *out, float *hist, float *out2, const float *window) { int i; #if __STDC_VERSION__ >= 199901L float buffer1[order + 1]; float buffer2[order + 1]; float work[order + n + non_rec]; #else float *buffer1=(float *)alloca((order + 1)*sizeof(float)); float *buffer2=(float *)alloca((order + 1)*sizeof(float)); float *work=(float *)alloca((order + n + non_rec)*sizeof(float)); #endif apply_window(work, window, hist, order + n + non_rec); convolve(buffer1, work + order , n , order); convolve(buffer2, work + order + n, non_rec, order); for (i=0; i <= order; i++) { out2[i] = out2[i] * 0.5625 + buffer1[i]; out [i] = out2[i] + buffer2[i]; } /* Multiply by the white noise correcting factor (WNCF). */ *out *= 257./256.; }
/** * Backward synthesis filter, find the LPC coefficients from past speech data. */ static void backward_filter(float *hist, float *rec, const float *window, float *lpc, const float *tab, int order, int n, int non_rec, int move_size) { float temp[order+1]; do_hybrid_window(order, n, non_rec, temp, hist, rec, window); if (!compute_lpc_coefs(temp, order, lpc, 0, 1, 1)) apply_window(lpc, lpc, tab, order); memmove(hist, hist + n, move_size*sizeof(*hist)); }
static void apply_window_mp3(float *in, float *win, int *unused, float *out, int incr) { LOCAL_ALIGNED_16(float, suma, [17]); LOCAL_ALIGNED_16(float, sumb, [17]); LOCAL_ALIGNED_16(float, sumc, [17]); LOCAL_ALIGNED_16(float, sumd, [17]); float sum; int j; float *out2 = out + 32 * incr; /* copy to avoid wrap */ memcpy(in + 512, in, 32 * sizeof(*in)); apply_window(in + 16, win , win + 512, suma, sumc, 16); apply_window(in + 32, win + 48, win + 640, sumb, sumd, 16); SUM8(MLSS, suma[0], win + 32, in + 48); sumc[ 0] = 0; sumb[16] = 0; sumd[16] = 0; out[0 ] = suma[ 0]; out += incr; out2 -= incr; for(j=1; j<16; j++) { *out = suma[ j] - sumd[16-j]; *out2 = -sumb[16-j] - sumc[ j]; out += incr; out2 -= incr; } sum = 0; SUM8(MLSS, sum, win + 16 + 32, in + 32); *out = sum; }
/** * Backward synthesis filter, find the LPC coefficients from past speech data. */ static void backward_filter(float *hist, float *rec, const float *window, float *lpc, const float *tab, int order, int n, int non_rec, int move_size) { #if __STDC_VERSION__ >= 199901L float temp[order+1]; #else float *temp = _alloca((order + 1) * sizeof(float)); #endif do_hybrid_window(order, n, non_rec, temp, hist, rec, window); if (!compute_lpc_coefs(temp, order, lpc, 0, 1, 1)) apply_window(lpc, lpc, tab, order); memmove(hist, hist + n, move_size*sizeof(*hist)); }
/** * Backward synthesis filter, find the LPC coefficients from past speech data. */ static void backward_filter(float *hist, float *rec, const float *window, float *lpc, const float *tab, int order, int n, int non_rec, int move_size) { #ifndef _MSC_VER float temp[order+1]; #else float *temp = av_malloc_items(order + 1, float); #endif do_hybrid_window(order, n, non_rec, temp, hist, rec, window); if (!compute_lpc_coefs(temp, order, lpc, 0, 1, 1)) apply_window(lpc, lpc, tab, order); memmove(hist, hist + n, move_size*sizeof(*hist)); #ifdef _MSC_VER av_free(temp); #endif }
/** * Hybrid window filtering, see blocks 36 and 49 of the G.728 specification. * * @param order filter order * @param n input length * @param non_rec number of non-recursive samples * @param out filter output * @param hist pointer to the input history of the filter * @param out pointer to the non-recursive part of the output * @param out2 pointer to the recursive part of the output * @param window pointer to the windowing function table */ static void do_hybrid_window(int order, int n, int non_rec, float *out, float *hist, float *out2, const float *window) { int i; float buffer1[order + 1]; float buffer2[order + 1]; float work[order + n + non_rec]; apply_window(work, window, hist, order + n + non_rec); convolve(buffer1, work + order , n , order); convolve(buffer2, work + order + n, non_rec, order); for (i=0; i <= order; i++) { out2[i] = out2[i] * 0.5625 + buffer1[i]; out [i] = out2[i] + buffer2[i]; } /* Multiply by the white noise correcting factor (WNCF). */ *out *= 257./256.; }
void Visualizer::Update() { static float input_wave[512]; float fft_tmp[512]; unsigned int buffer_pos = 0; for (int i = 0; i < 256; i++) { //Clear the buffers fft_tmp[i] = 0; //Decay previous values fft[i] = fft[i] * (((float)decay) / 100.0f); } unsigned int nextPacketSize = 1; unsigned int flags; while(nextPacketSize > 0 ) { float *buf; pAudioCaptureClient->GetBuffer((BYTE**)&buf, &nextPacketSize, (DWORD *)&flags, NULL, NULL); for (int i = 0; i < nextPacketSize; i+=4) { for (int j = 0; j < 255; j++) { input_wave[2 * j] = input_wave[2 * (j + 1)]; input_wave[(2 * j) + 1] = input_wave[2 * j]; } input_wave[510] = buf[i] * 2.0f * amplitude; input_wave[511] = input_wave[510]; } buffer_pos += nextPacketSize/4; pAudioCaptureClient->ReleaseBuffer(nextPacketSize); } memcpy(fft_tmp, input_wave, sizeof(input_wave)); //Apply selected window switch (window_mode) { case 0: break; case 1: apply_window(fft_tmp, win_hanning, 256); break; case 2: apply_window(fft_tmp, win_hamming, 256); break; case 3: apply_window(fft_tmp, win_blackman, 256); break; default: break; } //Run the FFT calculation rfft(fft_tmp, 256, 1); fft_tmp[0] = fft_tmp[2]; apply_window(fft_tmp, fft_nrml, 256); //Compute FFT magnitude for (int i = 0; i < 128; i += 2) { float fftmag; //Compute magnitude from real and imaginary components of FFT and apply simple LPF fftmag = (float)sqrt((fft_tmp[i] * fft_tmp[i]) + (fft_tmp[i + 1] * fft_tmp[i + 1])); //Apply a slight logarithmic filter to minimize noise from very low amplitude frequencies fftmag = ( 0.5f * log10(1.1f * fftmag) ) + ( 0.9f * fftmag ); //Limit FFT magnitude to 1.0 if (fftmag > 1.0f) { fftmag = 1.0f; } //Update to new values only if greater than previous values if (fftmag > fft[i*2]) { fft[i*2] = fftmag;; } //Prevent from going negative if (fft[i*2] < 0.0f) { fft[i*2] = 0.0f; } //Set odd indexes to match their corresponding even index, as the FFT input array uses two indices for one value (real+imaginary) fft[(i * 2) + 1] = fft[i * 2]; fft[(i * 2) + 2] = fft[i * 2]; fft[(i * 2) + 3] = fft[i * 2]; } if (avg_mode == 0) { //Apply averaging over given number of values int k; float sum1 = 0; float sum2 = 0; for (k = 0; k < avg_size; k++) { sum1 += fft[k]; sum2 += fft[255 - k]; } //Compute averages for end bars sum1 = sum1 / k; sum2 = sum2 / k; for (k = 0; k < avg_size; k++) { fft[k] = sum1; fft[255 - k] = sum2; } for (int i = 0; i < (256 - avg_size); i += avg_size) { float sum = 0; for (int j = 0; j < avg_size; j += 1) { sum += fft[i + j]; } float avg = sum / avg_size; for (int j = 0; j < avg_size; j += 1) { fft[i + j] = avg; } } } else if(avg_mode == 1) { for (int i = 0; i < avg_size; i++) { float sum1 = 0; float sum2 = 0; int j; for (j = 0; j <= i + avg_size; j++) { sum1 += fft[j]; sum2 += fft[255 - j]; } fft[i] = sum1 / j; fft[255 - i] = sum2 / j; } for (int i = avg_size; i < 256 - avg_size; i++) { float sum = 0; for (int j = 1; j <= avg_size; j++) { sum += fft[i - j]; sum += fft[i + j]; } sum += fft[i]; fft[i] = sum / (2 * avg_size + 1); } } }
//----------------------------------------------------------------------------- // name: fft_bandpass() // desc: bandpass filter the samples x - pass through frequencies between // bandStart * nyquist and bandEnd * nyquist unharmed, smoothly sloping down // the amplitudes of frequencies outside the passband to 0 over // rolloff * nyquist hz. //----------------------------------------------------------------------------- void fft_bandpass( Frame * x, float bandStart, float bandEnd, float rolloff ) { float *window = 0; int winsize = -1; int i; // not sure why we have at least 4 "pi" variables floating around // (#define PIE, #define PI, float PI earlier in this file, double pi local to functions) // got to combine them all some time. // double pi = 4.*atan(1.0); // make and apply hanning window if( winsize != x->wlen ){ winsize = x->wlen; if(window) delete[] window; window = new float[winsize]; hanning( window, winsize ); } apply_window( x->waveform, window, x->wlen ); // fft rfft( x->waveform, x->len, FFT_FORWARD ); BirdBrain::scale_fft( x->waveform, x->wlen, x->wlen, x->wsize ); x->cmp2pol(); // the core int rollWidth = (int)(rolloff * (float)x->len); int startIndex = (int)(bandStart * (float)x->len); int endIndex = (int)(bandEnd * (float)x->len); int lTail = startIndex - rollWidth; int rTail = endIndex + rollWidth; for(i = 0; i < lTail; i++){ x->pol[i].mag = 0; } for(i = lTail > 0 ? lTail : 0; i < startIndex; i++){ x->pol[i].mag *= 0.5 * (1 + cos(((float)(startIndex - i)) * PIE / (float)rollWidth)); } for(i = endIndex; (i < rTail) && (i < x->len); i++){ x->pol[i].mag *= 0.5 * (1 + cos(((float)(i - endIndex)) * PIE / (float)rollWidth)); } for(i = rTail; i < x->len; i++){ x->pol[i].mag = 0; } x->pol2cmp(); // inverse fft rfft( x->waveform, x->len, FFT_INVERSE); // inverse window! hanning( window, winsize ); for(i = 0; i < winsize; i++){ if(window[i] < 0.15) window[i] = 0.15f; window[i] = 1 / window[i]; } apply_window( x->waveform, window, x->wlen ); if( window ) delete[] window; }
int OlaRandom::WriteSoundFile( char filename[], float * data, int datasize ) { if( m_winsize != datasize ) { hanna( m_window, datasize ); m_winsize = datasize; } apply_window( data, m_window, datasize ); /*int hopsize = segsize / 2; //m_last_buffer_size / 2; //m_last_buffer_size - datasize / 2; if( hopsize < 0 ) hopsize = 0; BirdBrain::ola( m_ola_buffer, data, hopsize, datasize ); m_last_buffer_size = datasize; // reset data and datasize for writing memcpy( data, m_ola_buffer, sizeof(float) * hopsize ); datasize = hopsize; */ if( !m_top ) m_hopsize = m_last_buffer_size / 2; //fprintf( stderr, "hop: %d\n", m_hopsize ); m_top = !m_top; memcpy( m_swap_buffer, m_ola_buffer, sizeof(float) * m_hopsize ); BirdBrain::ola( m_ola_buffer, data, m_hopsize, OLAR_BIG_BUFFER_SIZE, datasize ); m_last_buffer_size = datasize; memcpy( data, m_swap_buffer, sizeof(float) * m_hopsize ); datasize = m_hopsize; // data will always fit in one buffer because buffer size = max tree size (CUTOFF) if( this->write_to_buffer ) { while( m_data_count >= m_max_data_count ) { BB_log( BB_LOG_FINE, "Background: waiting for empty buffer" ); usleep( 2000 ); } // used to be if ... return 0; // set #samples for the write buffer if( m_buffer_samples[m_write_index] != 0 ) { BB_log( BB_LOG_WARNING, "Background: overwriting!" ); } m_buffer_samples[m_write_index] = datasize; // set the buffer to write float * next_buffer = m_big_buffer[m_write_index++]; m_write_index %= m_max_data_count; // copy the data memcpy( next_buffer, data, datasize * sizeof(float) ); // increment data count m_data_count++; /* fprintf( stderr, "+ " ); for( int i = 0; i < m_max_data_count; i++ ) fprintf( stderr, "%d ", m_buffer_samples[i] ); fprintf( stderr, "(%d)\n", datasize ); */ } // if it's also writing to buffer, it doesn't get here until after the write succeeds // so the same data should not be written more than once to the file int itemswritten = 0; if( this->write_to_file ) { if( !sfwrite ) { writeinfo = readinfo; sfwrite = sf_open( filename, SFM_RDWR, &writeinfo ); if( !sfwrite ) { std::cerr << "OlaRandom::WriteSoundFile : cannot open file '" << filename << "', quitting" << std::endl; //char x[256]; //std::cin.getline( x, 256 ); //exit(1); return 2; } } sf_seek( sfwrite, writeinfo.frames, SEEK_SET ); itemswritten = sf_write_float( sfwrite, data, datasize ); if( itemswritten <= 0 ) { std::cerr << "OlaRandom::WriteSoundFile : cannot write to file '" << filename << "'" << std::endl; std::cerr << "needed to write " << datasize << " samples" << std::endl; //char x[256]; //std::cin.getline( x, 256 ); //exit(3); return 2; } sf_close( sfwrite ); sfwrite = NULL; } // wrote something if( this->write_to_file ) return itemswritten; else return datasize; }
//----------------------------------------------------------------------------- // name: render() // desc: ... //----------------------------------------------------------------------------- t_CKUINT AudicleFaceVMSpace::render( void * data ) { static const int LP = 4; static long int count = 0; static char str[1024]; static unsigned wf = 0; float fval; GLint i; // rotate the sphere about y axis glRotatef( 0.0f, 0.0f, 1.0f, 0.0f ); // color waveform glColor3f( 0.4f, 0.4f, 1.0f ); // wait for data //while( !g_ready ) // usleep( 0 ); // get the window memcpy( g_buffer, g_out_buffer, g_buffer_size * sizeof(SAMPLE) * g_num_channels ); //g_ready = FALSE; SAMPLE * p = g_buffer + g_buffer_size; SAMPLE * p2 = g_buffer + g_num_channels - 1; SAMPLE * a = g_buffer; while( a != p) { *a = *p2; a++; p2 += g_num_channels; } // apply the window GLfloat x = -1.8f, inc = 3.6f / g_buffer_size, y = .7f; if( g_window ) apply_window( g_buffer, g_window, g_buffer_size ); // draw the time domain waveform glBegin( GL_LINE_STRIP ); GLint ii = ( g_buffer_size - (g_buffer_size/g_time_view) ) / 2; for( i = ii; i < ii + g_buffer_size / g_time_view; i++ ) { glVertex3f( x, g_gain * g_time_scale * 1.6 * g_buffer[i] + y, 0.0f ); x += inc * g_time_view; } glEnd(); if( g_changed ) { glColor3f( 1.0 * g_changedf, .5 * g_changedf, .5 * g_changedf ); GLfloat x = -1.8f, inc = 3.6f / g_buffer_size, y = .7f; // draw the time domain waveform glBegin( GL_LINE_STRIP ); GLint ii = ( g_buffer_size - (g_buffer_size/g_time_view) ) / 2; for( i = ii; i < ii + g_buffer_size / g_time_view; i++ ) { glVertex3f( x, g_gain * g_time_scale * .8 * (g_window ? g_window[i] : 1.0 ) + y, 0.0f ); x += inc * g_time_view; } glEnd(); g_changedf -= g_rate; if( g_changedf < 0.0 ) g_changed = FALSE; } static t_CKFLOAT r = 0.0; glPushMatrix(); glPushName( g_id ); glTranslatef( 1.7, 0.0, 0.0 ); glColor3f( 1.0, .8, .5 ); glRotatef( r, 0.0, 0.0, 1.0 ); glutWireSphere( sphere_down ? .06 : .08, 15, 15 ); glPopName(); glPopMatrix(); glPushMatrix(); glPushName( g_id2 ); glTranslatef( 1.45, 0.0, 0.0 ); glColor3f( 1.0, .5, .5 ); glRotatef( r, 0.0, 0.0, 1.0 ); glutWireSphere( sphere_down2 ? .06 : .08, 15, 15 ); glPopName(); glPopMatrix(); r += 1; // fft rfft( g_buffer, g_buffer_size/2, FFT_FORWARD ); x = -1.8f; y = -1.0f; complex * cbuf = (complex *)g_buffer; // draw the frequency domain representation for( i = 0; i < g_buffer_size/2; i++ ) { g_spectrums[wf][i].x = x; if( !g_usedb ) g_spectrums[wf][i].y = g_gain * g_freq_scale * ::pow( (double) 25 * cmp_abs( cbuf[i] ), 0.5 ) + y; else g_spectrums[wf][i].y = g_gain * g_freq_scale * ( 20.0f * log10( cmp_abs(cbuf[i])/8.0 ) + 80.0f ) / 80.0f + y + .5f; x += inc * g_freq_view; } g_draw[wf] = true; glPushMatrix(); glTranslatef( fp[0], fp[1], fp[2] ); for( i = 0; i < g_depth; i++ ) { if( g_draw[(wf+i)%g_depth] ) { Pt2D * pt = g_spectrums[(wf+i)%g_depth]; fval = (g_depth-i)/(float)g_depth; glColor3f( .4f * fval, 1.0f * fval, .4f * fval ); x = -1.8f; glBegin( GL_LINE_STRIP ); for( int j = 0; j < g_buffer_size/g_freq_view; j++, pt++ ) glVertex3f( x + j*(inc*g_freq_view), pt->y, -i * g_space + g_z ); glEnd(); } } glPopMatrix(); if( !g_wutrfall ) g_draw[wf] = false; wf--; wf %= g_depth; return 0; }