summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2011-08-04 15:03:15 +0200
committerJon Bergli Heier <snakebite@jvnv.net>2011-08-04 15:03:15 +0200
commit16e1e247638aa0da5541aa78fb141e60744d56a0 (patch)
treeb6f99c16767c95c0b9fb0a79abea613150b11a4e
parent2c01957dfe1135955627cbbbffddc70d090d2656 (diff)
Handle sample rates and channels.
-rw-r--r--decoder.h10
-rw-r--r--decoders/ffmpeg_decoder.cpp2
-rw-r--r--decoders/mpg123_decoder.cpp9
-rw-r--r--encoders/lame_encoder.cpp6
-rw-r--r--encoders/vorbis_encoder.cpp24
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<RawAudioSource> 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);