blob: 4888af32b148ade9ec1db84e427cdafca01ffd9b [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <vector>
#include "volume_control.h"
// Plugin interface for audio DSP modules.
// This is applicable only to audio CMA backends (Alsa, Fuscia).
// Please refer to
// chromecast/media/cma/backend/post_processors/
// as an example for new code, but OEM's implementations should not have any
// Chromium dependencies.
// Please refer to
// chromecast/media/cma/backend/post_processors/post_processor_wrapper.h for an
// example of how to port an existing AudioPostProcessor to AudioPostProcessor2
// Notes on PostProcessors that have a different number of in/out channels:
// * PostProcessor authors are free to define their channel order; Cast will
// simply pass this data to subsequent PostProcessors and MixerOutputStream.
// * Channel selection for stereo pairs will occur after the "mix" group, so
// devices that support stereo pairs should only change the number of
// in the "linearize" group of cast_audio.json.
namespace chromecast {
namespace media {
// Interface for AudioPostProcessors used for applying DSP in StreamMixer.
class AudioPostProcessor2 {
// The maximum amount of data that will ever be processed in one call.
static constexpr int kMaxAudioWriteTimeMilliseconds = 20;
virtual ~AudioPostProcessor2() = default;
// Updates the sample rate of the processor.
// Returns |false| if the processor cannot support |sample_rate|
// Returning false will result in crashing cast_shell.
virtual bool SetSampleRate(int sample_rate) = 0;
// Returns the number of output channels. This value should never change after
// construction.
virtual int NumOutputChannels() = 0;
// Processes audio frames from |data|.
// This will never be called before SetSampleRate().
// Output buffer should be made available via GetOutputBuffer().
// ProcessFrames may overwrite |data|, in which case GetOutputBuffer() should
// return |data|.
// |data| will be 32-bit interleaved float with |channels_in| channels.
// If |channels_out| is larger than |channels_in|, AudioPostProcessor2 must
// own a buffer of length at least |channels_out| * frames;
// |data| cannot be assumed to be larger than |channels_in| * frames.
// |frames| is the number of audio frames in data and is
// always non-zero and less than or equal to |kMaxAudioWriteTimeMilliseconds|.
// AudioPostProcessor must always provide |frames| frames of data back
// (may output 0’s).
// |system_volume| is the Cast Volume applied to the stream
// (normalized to 0-1). It is the same as the cast volume set via alsa.
// |volume_dbfs| is the actual attenuation in dBFS (-inf to 0), equivalent to
// VolumeMap::VolumeToDbFS(|volume|).
// AudioPostProcessor should assume that volume has already been applied.
// Returns the current rendering delay of the filter in frames.
virtual int ProcessFrames(float* data,
int frames,
float system_volume,
float volume_dbfs) = 0;
// Returns the data buffer in which the last output from ProcessFrames() was
// stored.
// This will never be called before ProcessFrames().
// This data location should be valid until ProcessFrames() is called
// again.
// The data returned by GetOutputBuffer() should not be modified by this
// instance until the next call to ProcessFrames().
// If |channels_in| >= |channels_out|, this may return |data| from the
// last call to ProcessFrames().
// If |channels_in| < |channels_out|, this PostProcessor is responsible for
// allocating an output buffer.
// If this PostProcessor owns the outputbuffer, it must ensure that the memory
// is valid until the next call to ProcessFrames() or destruction.
virtual float* GetOutputBuffer() = 0;
// Returns the number of frames of silence it will take for the processor to
// come to rest after playing out audio.
// In the case of an FIR filter, this is the length of the FIR kernel.
// In the case of IIR filters, this should be calculated as the number of
// frames for the output to decay to 10% (5 time constants).
// When inputs are paused, at least |GetRingingTimeInFrames()| of
// silence will be passed through the processor. This will only be checked
// when SetSampleRate() is called.
virtual int GetRingingTimeInFrames() = 0;
// Sends a message to the PostProcessor. Implementations are responsible
// for the format and parsing of messages.
// Returns |true| if the message was accepted or |false| if the message could
// not be applied (i.e. invalid parameter, format error, parameter out of
// range, etc).
// If the PostProcessor can/will not be updated at runtime, this can be
// implemented as "return false;"
virtual bool UpdateParameters(const std::string& message) = 0;
// Sets content type to the PostProcessor so it could change processing
// settings accordingly.
virtual void SetContentType(AudioContentType content_type) {}
// Called when device is playing as part of a stereo pair.
// |channel| is the playout channel on this device (0 for left, 1 for right).
// or -1 if the device is not part of a stereo pair.
virtual void SetPlayoutChannel(int channel) {}
} // namespace media
} // namespace chromecast