Permalink
Browse files

o Allow to have a different amount of input vs. output channels.

  • Loading branch information...
1 parent 03a0c77 commit 30c747e70144670d60caf2d2726dddd65afccad7 @hzeller committed Nov 18, 2012
Showing with 27 additions and 13 deletions.
  1. +1 −1 conversion-buffer.cc
  2. +1 −0 conversion-buffer.h
  3. +10 −1 convolve-file-handler.cc
  4. +1 −0 convolve-file-handler.h
  5. +11 −10 sound-processor.cc
  6. +3 −1 sound-processor.h
View
@@ -50,7 +50,7 @@ ConversionBuffer::ConversionBuffer(SoundSource *source, const SF_INFO &info)
free(filename);
// After file-open: SetOutputSoundfile() already might attempt to write data.
- source_->SetOutputSoundfile(this, CreateOutputSoundfile(info));
+ source_->SetOutputSoundfile(this, info, CreateOutputSoundfile(info));
}
ConversionBuffer::~ConversionBuffer() {
View
@@ -41,6 +41,7 @@ class ConversionBuffer {
// Ownership is passed to the SoundSource, receiver needs to
// sf_close() the file.
virtual void SetOutputSoundfile(ConversionBuffer *parent,
+ const SF_INFO &info,
SNDFILE *sndfile) = 0;
// This callback is called by the ConversionBuffer if it needs more data.
View
@@ -58,7 +58,7 @@ FileHandler *ConvolveFileHandler::Create(FolveFilesystem *fs,
if ((in_info.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_24) bits = 24;
if ((in_info.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_32) bits = 32;
- // Remember whatever we could got to know in the partial file info.
+ // Remember whatever we could get to know in the partial file info.
Appendf(&partial_file_info->format, "%.1fkHz, %d Bit",
in_info.samplerate / 1000.0, bits);
partial_file_info->duration_seconds = in_info.frames / in_info.samplerate;
@@ -233,10 +233,14 @@ ConvolveFileHandler::ConvolveFileHandler(FolveFilesystem *fs,
out_info.format = in_info.format;
}
+ out_info.channels = processor->output_channels();
+ DLogf("Output channels: %d", out_info.channels);
+
output_buffer_ = new ConversionBuffer(this, out_info);
}
void ConvolveFileHandler::SetOutputSoundfile(ConversionBuffer *out_buffer,
+ const SF_INFO &info,
SNDFILE *sndfile) {
snd_out_ = sndfile;
if (snd_out_ == NULL) {
@@ -264,12 +268,17 @@ void ConvolveFileHandler::SetOutputSoundfile(ConversionBuffer *out_buffer,
// redact the values for min/max blocksize and min/max framesize with
// what SNDFILE is going to use, otherwise programs will trip over this.
// http://flac.sourceforge.net/format.html
+ // Also, number of output channels might be different.
if (copy_flac_header_verbatim_) {
out_buffer->WriteCharAt((1152 & 0xFF00) >> 8, 8);
out_buffer->WriteCharAt((1152 & 0x00FF) , 9);
out_buffer->WriteCharAt((1152 & 0xFF00) >> 8, 10);
out_buffer->WriteCharAt((1152 & 0x00FF) , 11);
for (int i = 12; i < 18; ++i) out_buffer->WriteCharAt(0, i); // framesize
+ // upper nibble: lowest 4 bit of samplerate, lower nibble: channels << 1
+ // 1 bit free.
+ out_buffer->WriteCharAt((in_info_.samplerate & 0x0f) << 4
+ | (info.channels - 1) << 1, 20);
} else {
// .. and if SNDFILE writes the header, it misses out in writing the
// number of samples to be expected. So let's fill that in.
View
@@ -53,6 +53,7 @@ class ConvolveFileHandler : public FileHandler,
// -- ConversionBuffer::SoundSource interface.
virtual void SetOutputSoundfile(ConversionBuffer *out_buffer,
+ const SF_INFO &info,
SNDFILE *sndfile);
virtual bool AddMoreSoundData();
View
@@ -58,8 +58,8 @@ static time_t GetModificationTime(const std::string &filename) {
SoundProcessor::SoundProcessor(const ZitaConfig &config, const std::string &cfg)
: zita_config_(config), config_file_(cfg),
config_file_timestamp_(GetModificationTime(cfg)),
- buffer_(new float[config.fragm * config.ninp]),
- channels_(config.ninp),
+ buffer_(new float[config.fragm
+ * std::max(input_channels(), output_channels())]),
input_pos_(0), output_pos_(0),
max_out_value_observed_(0.0) {
Reset();
@@ -76,7 +76,8 @@ int SoundProcessor::FillBuffer(SNDFILE *in) {
const int samples_needed = zita_config_.fragm - input_pos_;
assert(samples_needed); // Otherwise, call WriteProcessed() first.
output_pos_ = -1;
- int r = sf_readf_float(in, buffer_ + input_pos_ * channels_, samples_needed);
+ int r = sf_readf_float(in, buffer_ + input_pos_ * input_channels(),
+ samples_needed);
input_pos_ += r;
return r;
}
@@ -86,7 +87,7 @@ void SoundProcessor::WriteProcessed(SNDFILE *out, int sample_count) {
Process();
}
assert(sample_count <= zita_config_.fragm - output_pos_);
- sf_writef_float(out, buffer_ + output_pos_ * channels_, sample_count);
+ sf_writef_float(out, buffer_ + output_pos_ * output_channels(), sample_count);
output_pos_ += sample_count;
if (output_pos_ == zita_config_.fragm) {
input_pos_ = 0;
@@ -96,25 +97,25 @@ void SoundProcessor::WriteProcessed(SNDFILE *out, int sample_count) {
void SoundProcessor::Process() {
const int samples_missing = zita_config_.fragm - input_pos_;
if (samples_missing) {
- memset(buffer_ + input_pos_ * channels_, 0x00,
- samples_missing * channels_ * sizeof(float));
+ memset(buffer_ + input_pos_ * input_channels(), 0x00,
+ samples_missing * input_channels() * sizeof(float));
}
// Flatten channels: LRLRLRLRLR -> LLLLL and RRRRR
- for (int ch = 0; ch < channels_; ++ch) {
+ for (int ch = 0; ch < input_channels(); ++ch) {
float *dest = zita_config_.convproc->inpdata(ch);
for (int j = 0; j < input_pos_; ++j) {
- dest[j] = buffer_[j * channels_ + ch];
+ dest[j] = buffer_[j * input_channels() + ch];
}
}
zita_config_.convproc->process();
// Join channels again.
- for (int ch = 0; ch < channels_; ++ch) {
+ for (int ch = 0; ch < output_channels(); ++ch) {
float *source = zita_config_.convproc->outdata(ch);
for (int j = 0; j < input_pos_; ++j) {
- buffer_[j * channels_ + ch] = source[j];
+ buffer_[j * output_channels() + ch] = source[j];
const float out_abs = source[j];
if (out_abs > max_out_value_observed_) {
max_out_value_observed_ = out_abs;
View
@@ -34,6 +34,9 @@ class SoundProcessor {
// Fill Buffer from given sound file. Returns number of samples read.
int FillBuffer(SNDFILE *in);
+ inline int input_channels() const { return zita_config_.ninp; }
+ inline int output_channels() const { return zita_config_.nout;}
+
// Returns if the input buffer has enought samples for the FIR-filter
// to process. If not, another call to FillBuffer() is needed.
bool is_input_buffer_complete() const {
@@ -74,7 +77,6 @@ class SoundProcessor {
const time_t config_file_timestamp_;
float *const buffer_;
- const int channels_;
// TODO: instead of two positions, better have one position and two states
// READ, WRITE
int input_pos_;

0 comments on commit 30c747e

Please sign in to comment.