diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-10-20 15:40:46 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-10-20 20:05:08 +0100 |
| commit | b996eb8276dc4645745540190c9a2f5e2c875c0c (patch) | |
| tree | 0dc0cef257733a52cc347197cb0ed08ae53fe4f4 /src/lib/decoder.cc | |
| parent | a6976df179011056027a99ae210fb28117c36840 (diff) | |
Rework audio to deinterleave straight away and pass data
around as floats. Should simplify things.
Diffstat (limited to 'src/lib/decoder.cc')
| -rw-r--r-- | src/lib/decoder.cc | 103 |
1 files changed, 71 insertions, 32 deletions
diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index 03131dac2..ec046fcaf 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -105,7 +105,7 @@ Decoder::process_end () uint8_t remainder[-_delay_in_bytes]; _delay_line->get_remaining (remainder); _audio_frames_processed += _delay_in_bytes / (_fs->audio_channels() * _fs->bytes_per_sample()); - Audio (remainder, _delay_in_bytes); + emit_audio (remainder, _delay_in_bytes); } /* If we cut the decode off, the audio may be short; push some silence @@ -130,7 +130,7 @@ Decoder::process_end () while (bytes) { int64_t const t = min (bytes, silence_size); - Audio (silence, t); + emit_audio (silence, t); bytes -= t; } } @@ -175,53 +175,92 @@ Decoder::pass () } /** Called by subclasses to tell the world that some audio data is ready - * @param data Interleaved audio data, in FilmState::audio_sample_format. + * @param data Audio data, in FilmState::audio_sample_format. * @param size Number of bytes of data. */ void Decoder::process_audio (uint8_t* data, int size) { - /* Samples per channel */ - int const samples = size / _fs->bytes_per_sample(); + /* Push into the delay line */ + size = _delay_line->feed (data, size); - /* Maybe apply gain */ - if (_fs->audio_gain() != 0) { - float const linear_gain = pow (10, _fs->audio_gain() / 20); - uint8_t* p = data; - switch (_fs->audio_sample_format()) { - case AV_SAMPLE_FMT_S16: - for (int i = 0; i < samples; ++i) { - /* XXX: assumes little-endian; also we should probably be dithering here */ + emit_audio (data, size); +} - /* unsigned sample */ - int const ou = p[0] | (p[1] << 8); +void +Decoder::emit_audio (uint8_t* data, int size) +{ + /* Deinterleave and convert to float */ + + float* samples[_fs->audio_channels()]; + int const total_samples = size / _fs->bytes_per_sample(); + int const frames = total_samples / _fs->audio_channels(); + for (int i = 0; i < _fs->audio_channels(); ++i) { + samples[i] = new float[frames]; + } - /* signed sample */ - int const os = ou >= 0x8000 ? (- 0x10000 + ou) : ou; + switch (_fs->audio_sample_format()) { + case AV_SAMPLE_FMT_S16: + { + uint8_t* p = data; + int sample = 0; + int channel = 0; + for (int i = 0; i < total_samples; ++i) { + /* unsigned sample */ + int const ou = p[0] | (p[1] << 8); + /* signed sample */ + int const os = ou >= 0x8000 ? (- 0x10000 + ou) : ou; + /* float sample */ + samples[channel][sample] = float(os) / 0x8000; + + cout << samples[channel][sample] << " from s16\n"; + + ++channel; + if (channel == _fs->audio_channels()) { + channel = 0; + ++sample; + } - /* signed sample with altered gain */ - int const gs = int (os * linear_gain); + p += 2; + } + } + break; + + case AV_SAMPLE_FMT_FLTP: + { + float* p = reinterpret_cast<float*> (data); + for (int i = 0; i < _fs->audio_channels(); ++i) { + for (int j = 0; j < frames; ++j) { + samples[i][j] = *p++; + cout << samples[i][j] << " from float.\n"; + ++p; + } + } + } + break; - /* unsigned sample with altered gain */ - int const gu = gs > 0 ? gs : (0x10000 + gs); + default: + assert (false); + } - /* write it back */ - p[0] = gu & 0xff; - p[1] = (gu & 0xff00) >> 8; - p += 2; + /* Maybe apply gain */ + if (_fs->audio_gain() != 0) { + float const linear_gain = pow (10, _fs->audio_gain() / 20); + for (int i = 0; i < _fs->audio_channels(); ++i) { + for (int j = 0; j < frames; ++j) { + samples[i][j] *= linear_gain; } - break; - default: - assert (false); } } /* Update the number of audio frames we've pushed to the encoder */ - _audio_frames_processed += size / (_fs->audio_channels() * _fs->bytes_per_sample()); + _audio_frames_processed += frames; - /* Push into the delay line and then tell the world what we've got */ - int available = _delay_line->feed (data, size); - Audio (data, available); + Audio (samples, frames); + + for (int i = 0; i < _fs->audio_channels(); ++i) { + delete[] samples[i]; + } } /** Called by subclasses to tell the world that some video data is ready. |
