void ReplayBuffer::read_blockset(timecode_t frame, BlockSet &blkset) { off_t base_offset; base_offset = index->get_frame_location(frame); blkset.begin_read(fd, base_offset); }
void process(int input_fd, int output_fd) { off_t current_offset = 0; std::complex<float> *frame_data = NULL; std::complex<float> *last_frame_data = NULL; size_t count = 0; size_t frame_count = 0, hop_factor = 8; FFT<float> *ifft = NULL; std::complex<float> *ifft_result = NULL; int16_t *samples = NULL; float scale_factor = 1.0; for (;;) { BlockSet blkset; try { blkset.begin_read(input_fd, current_offset); delete [] last_frame_data; last_frame_data = frame_data; frame_data = blkset.load_alloc_block<std::complex<float> >(REPLAY_PVOC_BLOCK, count); if (ifft == NULL) { ifft = new FFT<float>(count, FFT<float>::INVERSE); ifft_result = new std::complex<float>[count]; samples = new int16_t[count]; scale_factor = float(count) * float(hop_factor); } } catch (...) { /* * if it bombs out we are probably past end of file but who knows * so we just close the output_fd and rethrow. This is really ugly * but will make sure that any really bad errors get printed * rather than ignored. */ close(input_fd); close(output_fd); throw; } /* * phase information is stored as a delta from last_frame_data. * If last_frame_data is not NULL, we add the phase values into * those in frame_data. */ if (last_frame_data != NULL) { for (size_t i = 0; i < count; i++) { frame_data[i] = std::polar( std::abs(frame_data[i]), std::arg(frame_data[i]) + std::arg(last_frame_data[i]) ); } } /* * now if frame_count % hop_factor == 0, take the IFFT. * This should yield a block of (approximately) original * audio data. */ if (frame_count % hop_factor == 0) { ifft->compute(ifft_result, frame_data); /* take real part and scale as needed */ for (size_t i = 0; i < count; i++) { samples[i] = std::real(ifft_result[i]) / scale_factor; } write_all(output_fd, samples, count * sizeof(*samples)); } frame_count++; current_offset = blkset.end_offset( ); } }