#include "stdafx.h" #include "VisUtils.h" namespace VisUtils { void PrepareFFTChunk(audio_chunk const & source, audio_chunk & out, double centerOffset) { const t_uint32 channels = source.get_channel_count(); const t_uint32 sampleRate = source.get_sample_rate(); FB2K_DYNAMIC_ASSERT( sampleRate > 0 ); out.set_channels(channels, source.get_channel_config()); out.set_sample_rate(sampleRate); const t_size inSize = source.get_sample_count(); const t_size fftSize = MatchFFTSize(inSize); out.set_sample_count(fftSize); out.set_data_size(fftSize * channels); if (fftSize >= inSize) { //rare case with *REALLY* small input pfc::memcpy_t( out.get_data(), source.get_data(), inSize * channels ); pfc::memset_null_t( out.get_data() + inSize * channels, (fftSize - inSize) * channels ); } else { //inSize > fftSize, we're using a subset of source chunk for the job, pick a subset around centerOffset. const double baseOffset = pfc::max_t(0, centerOffset - 0.5 * (double)fftSize / (double)sampleRate); const t_size baseSample = pfc::min_t( (t_size) audio_math::time_to_samples(baseOffset, sampleRate), inSize - fftSize); pfc::memcpy_t( out.get_data(), source.get_data() + baseSample * channels, fftSize * channels); } } bool IsValidFFTSize(t_size p_size) { return p_size >= 2 && (p_size & (p_size - 1)) == 0; } t_size MatchFFTSize(t_size samples) { if (samples <= 2) return 2; t_size mask = 1; while(!IsValidFFTSize(samples)) { samples &= ~mask; mask <<= 1; } return samples; } };