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 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");
	}
}