From 16e1e247638aa0da5541aa78fb141e60744d56a0 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Thu, 4 Aug 2011 15:03:15 +0200 Subject: Handle sample rates and channels. --- decoder.h | 10 ++++++++++ decoders/ffmpeg_decoder.cpp | 2 ++ decoders/mpg123_decoder.cpp | 9 ++++++++- encoders/lame_encoder.cpp | 6 ++++++ encoders/vorbis_encoder.cpp | 24 ++++++++++++------------ 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/decoder.h b/decoder.h index a1d857f..474f2f1 100644 --- a/decoder.h +++ b/decoder.h @@ -7,6 +7,10 @@ //! Interface for classes outputting raw audio. class RawAudioSource { + protected: + int samplerate; + int channels; + public: typedef boost::shared_ptr p; @@ -15,6 +19,12 @@ class RawAudioSource { //! Read into provided buffer. virtual std::size_t read(char* buf, std::size_t buf_size) = 0; + + //! Return sample rate. + int get_samplerate() { return samplerate; } + + //! Return number of channels. + int get_channels() { return channels; } }; //! Decoder base class. diff --git a/decoders/ffmpeg_decoder.cpp b/decoders/ffmpeg_decoder.cpp index 630e38e..7b7397f 100644 --- a/decoders/ffmpeg_decoder.cpp +++ b/decoders/ffmpeg_decoder.cpp @@ -14,6 +14,8 @@ DecoderFFmpeg::DecoderFFmpeg(const std::string& filename) { av_dump_format(lavf_ctx, 0, filename.c_str(), 0); lavc_ctx = lavf_ctx->streams[0]->codec; + samplerate = lavc_ctx->sample_rate; + channels = lavc_ctx->channels; codec = avcodec_find_decoder(lavc_ctx->codec_id); std::cerr << "Opening decoder: " << avcodec_open(lavc_ctx, codec) << std::endl; diff --git a/decoders/mpg123_decoder.cpp b/decoders/mpg123_decoder.cpp index ec6f490..13e9861 100644 --- a/decoders/mpg123_decoder.cpp +++ b/decoders/mpg123_decoder.cpp @@ -17,8 +17,15 @@ DecoderMpg123::DecoderMpg123(const std::string& filename) { throw std::runtime_error(mpg123_plain_strerror(error)); } + long rate; + int channels, enc; + mpg123_getformat(handle, &rate, &channels, &enc); + std::cout << boost::format("mpg123: %li Hz, %i channels, encoding value %i") % rate % channels % enc << std::endl; + this->samplerate = rate; + this->channels = channels; + mpg123_format_none(handle); - mpg123_format(handle, 44100, 2, MPG123_ENC_SIGNED_16); + mpg123_format(handle, rate, channels, MPG123_ENC_SIGNED_16); } DecoderMpg123::~DecoderMpg123() { diff --git a/encoders/lame_encoder.cpp b/encoders/lame_encoder.cpp index 28749aa..9c70507 100644 --- a/encoders/lame_encoder.cpp +++ b/encoders/lame_encoder.cpp @@ -4,6 +4,11 @@ EncoderLame::EncoderLame(RawAudioSource::p source_) : source(source_) { gfp = lame_init(); + + lame_set_in_samplerate(gfp, source->get_samplerate()); + lame_set_out_samplerate(gfp, 0); + lame_set_num_channels(gfp, source->get_channels()); + int error = lame_init_params(gfp); if(error < 0) { @@ -20,6 +25,7 @@ std::size_t EncoderLame::read(char* buf, std::size_t buf_size) { std::streamsize src_read = source->read(src_data, 0x30000); if(src_read < 0) src_read = 0; + // TODO: handle non-stereo inputs std::size_t size = lame_encode_buffer_interleaved(gfp, (short*)src_data, src_read / 4, (unsigned char*)buf, buf_size); // no more data, flush encoder if(src_read == 0 && size == 0) { diff --git a/encoders/vorbis_encoder.cpp b/encoders/vorbis_encoder.cpp index 4449345..3c94f6f 100644 --- a/encoders/vorbis_encoder.cpp +++ b/encoders/vorbis_encoder.cpp @@ -5,7 +5,7 @@ VorbisEncoder::VorbisEncoder(RawAudioSource::p source_) : source(source_) { vorbis_info_init(&vi); - vorbis_encode_init_vbr(&vi, 2, 44100, .4); + vorbis_encode_init_vbr(&vi, source->get_channels(), source->get_samplerate(), .4); vorbis_analysis_init(&dsp, &vi); vorbis_block_init(&dsp, &vb); @@ -55,27 +55,27 @@ std::size_t VorbisEncoder::write_pages(char *buf, std::size_t buf_size) { */ std::size_t VorbisEncoder::encode(char *buf, std::size_t buf_size) { const int samples_n = 1024; + int channels = source->get_channels(); - // samples_n samples, 2 channels, 2 byte per sample - char src_data[samples_n*2*2]; + // samples_n samples, channels, 2 byte per sample + char src_data[samples_n*channels*2]; int16_t *src_data_16 = (int16_t*)src_data; - std::streamsize src_read = source->read(src_data, samples_n*2*2); - if(src_read % 4) { - throw std::runtime_error("invalid buffer size"); - } + std::streamsize src_read = source->read(src_data, samples_n*channels*2); - if(src_read == 0) { + if(src_read <= 0) { vorbis_analysis_wrote(&dsp, 0); + } else if(src_read % 4) { + throw std::runtime_error("invalid buffer size"); } else { int samples_read = src_read / 4; float **buffer = vorbis_analysis_buffer(&dsp, samples_read); int sample; for(sample = 0; sample < samples_read; sample++) { - for(int c = 0; c < 2; c++) { - int i = sample*2+c; - if(i*2 >= src_read) break; - buffer[c][sample] = src_data_16[sample*2+c]/32768.; + for(int c = 0; c < channels; c++) { + int i = sample*channels+c; + if(i*channels >= src_read) break; + buffer[c][sample] = src_data_16[sample*channels+c]/32768.; } } vorbis_analysis_wrote(&dsp, sample); -- cgit v1.2.3