void FftClFft:: compute(DataStorage<float>::Ptr input, Tfr::ChunkData::Ptr output, DataStorageSize n ) { unsigned denseWidth = n.width/2+1; EXCEPTION_ASSERT( output->numberOfElements()/denseWidth == n.height ); EXCEPTION_ASSERT( input->numberOfElements()/n.width == n.height ); // interleave input to complex data Tfr::ChunkData::Ptr complexinput( new Tfr::ChunkData( input->size())); ::stftToComplex( input, complexinput ); // make room for full output Tfr::ChunkData::Ptr redundantOutput( new Tfr::ChunkData( n.width*n.height )); // compute computeWithClFft(complexinput, redundantOutput, n, FftDirection_Forward); // discard redundant output Tfr::ChunkElement* in = CpuMemoryStorage::ReadOnly<1>( redundantOutput ).ptr(); Tfr::ChunkElement* out = CpuMemoryStorage::WriteAll<1>( output ).ptr(); #pragma omp parallel for for (int i=0; i < (int)n.height; ++i) { unsigned x; for (x=0; x<denseWidth; ++x) out[i*denseWidth + x] = in[i*n.width + x]; } }
void FftClFft:: inverse(Tfr::ChunkData::Ptr input, DataStorage<float>::Ptr output, DataStorageSize n ) { unsigned denseWidth = n.width/2+1; unsigned redundantWidth = n.width; unsigned batchcount1 = output->numberOfElements()/redundantWidth, batchcount2 = input->numberOfElements()/denseWidth; EXCEPTION_ASSERT( batchcount1 == batchcount2 ); EXCEPTION_ASSERT( (denseWidth-1)*2 == redundantWidth ); EXCEPTION_ASSERT( redundantWidth*n.height == output->numberOfElements() ); Tfr::ChunkData::Ptr redundantInput( new Tfr::ChunkData( n.height*redundantWidth )); { Tfr::ChunkElement* in = CpuMemoryStorage::ReadOnly<1>( input ).ptr(); Tfr::ChunkElement* out = CpuMemoryStorage::WriteAll<1>( redundantInput ).ptr(); #pragma omp parallel for for (int i=0; i < (int)n.height; ++i) { unsigned x; for (x=0; x<denseWidth; ++x) out[i*redundantWidth + x] = in[i*denseWidth + x]; for (; x<redundantWidth; ++x) out[i*redundantWidth + x] = conj(in[i*denseWidth + redundantWidth - x]); } } Tfr::ChunkData::Ptr complexoutput( new Tfr::ChunkData( output->size())); computeWithClFft(redundantInput, complexoutput, DataStorageSize( redundantWidth, n.height), FftDirection_Inverse); ::stftDiscardImag( complexoutput, output ); TIME_STFT ComputationSynchronize(); }