void AudioBuffer::convert_channels(AudioBuffer &_dest, unsigned _frames_count) { AudioSpec destspec{m_spec.format, _dest.channels(), m_spec.rate}; if(_dest.spec() != destspec) { throw std::logic_error("unsupported format"); } _frames_count = std::min(frames(),_frames_count); if(m_spec.channels == destspec.channels) { _dest.add_frames(*this,_frames_count); return; } switch(m_spec.format) { case AUDIO_FORMAT_U8: convert_channels<uint8_t>(*this,_dest,_frames_count); break; case AUDIO_FORMAT_S16: convert_channels<int16_t>(*this,_dest,_frames_count); break; case AUDIO_FORMAT_F32: convert_channels<float>(*this,_dest,_frames_count); break; default: throw std::logic_error("unsupported format"); } }
void SoundFX::load_audio_file(const char *_filename, AudioBuffer &_sample, const AudioSpec &_spec) { try { std::string path = g_program.config().get_file_path(_filename, FILE_TYPE_ASSET); WAVFile wav; wav.open_read(path.c_str()); _sample.load(wav); if(_spec != _sample.spec()) { PDEBUGF(LOG_V1, LOG_AUDIO, "converting from %s to %s\n", _sample.spec().to_string().c_str(), _spec.to_string().c_str()); _sample.convert(_spec); } } catch(std::exception &e) { PERRF(LOG_AUDIO, "SoundFX: %s: %s\n", _filename, e.what()); } }
void AudioBuffer::add_frames(const AudioBuffer &_source, unsigned _frames_count) { if(_source.spec() != m_spec) { throw std::logic_error("sound buffers must have the same spec"); } _frames_count = std::min(_frames_count, _source.frames()); if(_frames_count == 0) { return; } unsigned datalen = _frames_count * frame_size(); auto srcstart = _source.m_data.begin(); m_data.insert(m_data.end(), srcstart, srcstart+datalen); }
void AudioBuffer::convert_rate(AudioBuffer &_dest, unsigned _frames_count, SRC_STATE *_SRC) { AudioSpec destspec{AUDIO_FORMAT_F32, m_spec.channels, _dest.rate()}; if(m_spec.format != AUDIO_FORMAT_F32 || _dest.spec() != destspec) { throw std::logic_error("unsupported format"); } _frames_count = std::min(frames(),_frames_count); double rate_ratio = double(destspec.rate)/double(m_spec.rate); unsigned out_frames = unsigned(ceil(double(_frames_count) * rate_ratio)); if(out_frames==0) { return; } unsigned destpos = _dest.samples(); unsigned destframes = _dest.frames(); _dest.resize_frames(_dest.frames()+out_frames); #if HAVE_LIBSAMPLERATE SRC_DATA srcdata; srcdata.data_in = &at<float>(0); srcdata.data_out = &_dest.at<float>(destpos); srcdata.input_frames = _frames_count; srcdata.output_frames = out_frames; srcdata.src_ratio = rate_ratio; int srcresult; if(_SRC != nullptr) { srcdata.end_of_input = 0; srcresult = src_process(_SRC, &srcdata); } else { srcdata.end_of_input = 1; srcresult = src_simple(&srcdata, SRC_SINC_BEST_QUALITY, destspec.channels) ; } if(srcresult != 0) { throw std::runtime_error(std::string("error resampling: ") + src_strerror(srcresult)); } assert(srcdata.output_frames_gen>=0 && srcdata.output_frames_gen<=out_frames); if(srcdata.output_frames_gen != out_frames) { _dest.resize_frames(destframes + srcdata.output_frames_gen); } PDEBUGF(LOG_V2, LOG_MIXER, "convert rate: f-in: %d, f-out: %d, gen: %d\n", _frames_count, out_frames, srcdata.output_frames_gen); #else for(unsigned i=destpos; i<_dest.samples(); ++i) { _dest.operator[]<float>(i) = 0.f; } #endif }
void AudioBuffer::convert_format(AudioBuffer &_dest, unsigned _frames_count) { AudioSpec destspec{_dest.format(), m_spec.channels, m_spec.rate}; if(_dest.spec() != destspec) { throw std::logic_error("destination must have same channels and rate"); } _frames_count = std::min(frames(),_frames_count); if(m_spec.format == destspec.format) { _dest.add_frames(*this,_frames_count); return; } const unsigned samples_count = m_spec.frames_to_samples(_frames_count); std::vector<uint8_t> buffer, *data=&buffer; switch(m_spec.format) { case AUDIO_FORMAT_U8: u8_to_f32(m_data, buffer, samples_count); break; case AUDIO_FORMAT_S16: s16_to_f32(m_data, buffer, samples_count); break; case AUDIO_FORMAT_F32: data = &m_data; break; default: throw std::logic_error("unsupported source format"); } switch(destspec.format) { case AUDIO_FORMAT_S16: f32_to_s16(*data, _dest.m_data, samples_count); break; case AUDIO_FORMAT_F32: _dest.m_data.swap(buffer); break; default: throw std::logic_error("unsupported destination format"); } }