void PrepareFFTChunk(audio_chunk const & source, audio_chunk & out, double centerOffset) { const t_size 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<double>(0, centerOffset - 0.5 * (double)fftSize / (double)sampleRate); const t_size baseSample = pfc::min_t<t_size>( (t_size) audio_math::time_to_samples(baseOffset, sampleRate), inSize - fftSize); pfc::memcpy_t( out.get_data(), source.get_data() + baseSample * channels, fftSize * channels); } }
void output_impl::process_samples(const audio_chunk & p_chunk) { pfc::dynamic_assert(m_incoming_ptr == m_incoming.get_size()); t_samplespec spec; spec.fromchunk(p_chunk); if (!spec.is_valid()) pfc::throw_exception_with_message< exception_io_data >("Invalid audio stream specifications"); m_incoming_spec = spec; t_size length = p_chunk.get_used_size(); m_incoming.set_data_fromptr(p_chunk.get_data(),length); m_incoming_ptr = 0; }
bool decode_run(audio_chunk &chunk, abort_callback &abort) { if (m_current_packet >= m_demuxer->num_packets() + 1) return false; int64_t pull_packet = m_current_packet; if (m_current_packet == m_demuxer->num_packets()) { /* * If the end padding is shorter than the decoder delay, * we already have fed all packets to the decoder but still * we have to feed extra packet to pull the final delayed result. * Due to overlap+add, samples might not be fully reconstructed * anyway... */ if (decoder_delay() <= m_demuxer->end_padding()) return false; else pull_packet = m_current_packet - 1; } auto asbd = m_demuxer->format().asbd; uint32_t fpp = asbd.mFramesPerPacket; uint32_t npackets = m_demuxer->read_packets(pull_packet, m_packets_per_chunk, &m_chunk_buffer, abort); if (npackets == 0) return false; m_current_packet += npackets; int64_t trim = std::max(m_current_packet * fpp - m_demuxer->duration() - m_demuxer->start_offset() - decoder_delay(), static_cast<int64_t>(0)); if (trim >= fpp * npackets) return false; m_decoder->decode(m_chunk_buffer.data(), m_chunk_buffer.size(), chunk, abort); t_size nframes = chunk.get_sample_count(); unsigned nchannels = chunk.get_channels(); if (trim > 0) { nframes = fpp * npackets - trim; chunk.set_sample_count(nframes); } if (m_start_skip) { if (m_start_skip >= nframes) { m_start_skip -= nframes; return decode_run(chunk, abort); } uint32_t rest = nframes - m_start_skip; uint32_t bpf = nchannels * sizeof(audio_sample); audio_sample *bp = chunk.get_data(); std::memmove(bp, bp + m_start_skip * nchannels, rest * bpf); chunk.set_sample_count(rest); m_start_skip = 0; } update_dynamic_vbr_info(m_current_packet - npackets, m_current_packet); return true; }