+ /* Push into the delay line */
+ size = _delay_line->feed (data, size);
+
+ emit_audio (data, size);
+}
+
+void
+Decoder::emit_audio (uint8_t* data, int size)
+{
+ /* Deinterleave and convert to float */
+
+ assert ((size % (bytes_per_audio_sample() * _film->audio_channels())) == 0);
+
+ int const total_samples = size / bytes_per_audio_sample();
+ int const frames = total_samples / _film->audio_channels();
+ shared_ptr<AudioBuffers> audio (new AudioBuffers (_film->audio_channels(), frames));
+
+ switch (audio_sample_format()) {
+ case AV_SAMPLE_FMT_S16:
+ {
+ int16_t* p = (int16_t *) data;
+ int sample = 0;
+ int channel = 0;
+ for (int i = 0; i < total_samples; ++i) {
+ audio->data(channel)[sample] = float(*p++) / (1 << 15);
+
+ ++channel;
+ if (channel == _film->audio_channels()) {
+ channel = 0;
+ ++sample;
+ }
+ }
+ }
+ break;
+
+ case AV_SAMPLE_FMT_S32:
+ {
+ int32_t* p = (int32_t *) data;
+ int sample = 0;
+ int channel = 0;
+ for (int i = 0; i < total_samples; ++i) {
+ audio->data(channel)[sample] = float(*p++) / (1 << 31);
+
+ ++channel;
+ if (channel == _film->audio_channels()) {
+ channel = 0;
+ ++sample;
+ }
+ }
+ }
+
+ case AV_SAMPLE_FMT_FLTP:
+ {
+ float* p = reinterpret_cast<float*> (data);
+ for (int i = 0; i < _film->audio_channels(); ++i) {
+ memcpy (audio->data(i), p, frames * sizeof(float));
+ p += frames;
+ }
+ }
+ break;
+
+ default:
+ assert (false);
+ }