+ assert (_ffmpeg_content->audio_channels());
+ assert (bytes_per_audio_sample());
+
+ /* Deinterleave and convert to float */
+
+ assert ((size % (bytes_per_audio_sample() * _ffmpeg_content->audio_channels())) == 0);
+
+ int const total_samples = size / bytes_per_audio_sample();
+ int const frames = total_samples / _ffmpeg_content->audio_channels();
+ shared_ptr<AudioBuffers> audio (new AudioBuffers (_ffmpeg_content->audio_channels(), frames));
+
+ switch (audio_sample_format()) {
+ case AV_SAMPLE_FMT_S16:
+ {
+ int16_t* p = reinterpret_cast<int16_t *> (data[0]);
+ 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 == _ffmpeg_content->audio_channels()) {
+ channel = 0;
+ ++sample;
+ }
+ }
+ }
+ break;
+
+ case AV_SAMPLE_FMT_S16P:
+ {
+ int16_t** p = reinterpret_cast<int16_t **> (data);
+ for (int i = 0; i < _ffmpeg_content->audio_channels(); ++i) {
+ for (int j = 0; j < frames; ++j) {
+ audio->data(i)[j] = static_cast<float>(p[i][j]) / (1 << 15);
+ }
+ }
+ }
+ break;
+
+ case AV_SAMPLE_FMT_S32:
+ {
+ int32_t* p = reinterpret_cast<int32_t *> (data[0]);
+ int sample = 0;
+ int channel = 0;
+ for (int i = 0; i < total_samples; ++i) {
+ audio->data(channel)[sample] = static_cast<float>(*p++) / (1 << 31);
+
+ ++channel;
+ if (channel == _ffmpeg_content->audio_channels()) {
+ channel = 0;
+ ++sample;
+ }
+ }
+ }
+ break;
+
+ case AV_SAMPLE_FMT_FLT:
+ {
+ float* p = reinterpret_cast<float*> (data[0]);
+ int sample = 0;
+ int channel = 0;
+ for (int i = 0; i < total_samples; ++i) {
+ audio->data(channel)[sample] = *p++;
+
+ ++channel;
+ if (channel == _ffmpeg_content->audio_channels()) {
+ channel = 0;
+ ++sample;
+ }
+ }
+ }
+ break;
+
+ case AV_SAMPLE_FMT_FLTP:
+ {
+ float** p = reinterpret_cast<float**> (data);
+ for (int i = 0; i < _ffmpeg_content->audio_channels(); ++i) {
+ memcpy (audio->data(i), p[i], frames * sizeof(float));
+ }
+ }
+ break;
+
+ default:
+ throw DecodeError (String::compose (_("Unrecognised audio sample format (%1)"), static_cast<int> (audio_sample_format())));
+ }
+
+ return audio;