1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "effect-impl/EffectContext.h"
20 #include "Processors.h"
21 
22 #include <vibrator/ExternalVibrationUtils.h>
23 
24 #include <cstddef>
25 #include <map>
26 
27 namespace aidl::android::hardware::audio::effect {
28 
29 enum HapticGeneratorState {
30     HAPTIC_GENERATOR_STATE_UNINITIALIZED,
31     HAPTIC_GENERATOR_STATE_INITIALIZED,
32     HAPTIC_GENERATOR_STATE_ACTIVE,
33 };
34 
35 struct HapticGeneratorParam {
36     // The audio channels used to generate haptic channels. The first channel will be used to
37     // generate HAPTIC_A, The second channel will be used to generate HAPTIC_B.
38     // The value will be offset of audio channel
39     int mHapticChannelSource[2];
40 
41     int mHapticChannelCount;
42     int mAudioChannelCount;
43 
44     std::map<int, HapticGenerator::VibratorScale> mHapticScales;
45     // max intensity will be used to scale haptic data.
46     HapticGenerator::VibratorScale mMaxVibratorScale;
47 
48     HapticGenerator::VibratorInformation mVibratorInfo;
49 };
50 
51 // A structure to keep all shared pointers for all processors in HapticGenerator.
52 struct HapticGeneratorProcessorsRecord {
53     std::vector<std::shared_ptr<HapticBiquadFilter>> filters;
54     std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Ramp>> ramps;
55     std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::SlowEnvelope>> slowEnvs;
56     std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Distortion>> distortions;
57 
58     // Cache band-pass filter and band-stop filter for updating parameters
59     // according to vibrator info
60     std::shared_ptr<HapticBiquadFilter> bpf;
61     std::shared_ptr<HapticBiquadFilter> bsf;
62 };
63 
64 class HapticGeneratorContext final : public EffectContext {
65   public:
66     HapticGeneratorContext(int statusDepth, const Parameter::Common& common);
67     ~HapticGeneratorContext();
68     RetCode enable();
69     RetCode disable();
70     void reset();
71 
72     RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale>& hapticScales);
73     std::vector<HapticGenerator::HapticScale> getHgHapticScales() const;
74 
75     RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo);
76     HapticGenerator::VibratorInformation getHgVibratorInformation() const;
77 
78     IEffect::Status process(float* in, float* out, int samples);
79 
80     RetCode setCommon(const Parameter::Common& common) override;
81 
82   private:
83     static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
84     static constexpr float DEFAULT_BSF_ZERO_Q = 8.0f;
85     static constexpr float DEFAULT_BSF_POLE_Q = 4.0f;
86     static constexpr float DEFAULT_DISTORTION_OUTPUT_GAIN = 1.5f;
87     static constexpr float DEFAULT_BPF_Q = 1.0f;
88     static constexpr float DEFAULT_SLOW_ENV_NORMALIZATION_POWER = -0.8f;
89     static constexpr float DEFAULT_DISTORTION_CORNER_FREQUENCY = 300.0f;
90     static constexpr float DEFAULT_DISTORTION_INPUT_GAIN = 0.3f;
91     static constexpr float DEFAULT_DISTORTION_CUBE_THRESHOLD = 0.1f;
92 
93     HapticGeneratorState mState;
94     HapticGeneratorParam mParams;
95     int mSampleRate;
96     int64_t mFrameCount = 0;
97 
98     // A cache for all shared pointers of the HapticGenerator
99     struct HapticGeneratorProcessorsRecord mProcessorsRecord;
100 
101     // Using a vector of functions to record the processing chain for haptic-generating algorithm.
102     // The three parameters of the processing functions are pointer to output buffer, pointer to
103     // input buffer and frame count.
104     std::vector<std::function<void(float*, const float*, size_t)>> mProcessingChain;
105 
106     // inputBuffer is where to keep input buffer for the generating algorithm. It will be
107     // constructed according to hapticChannelSource.
108     std::vector<float> mInputBuffer;
109 
110     // outputBuffer is a buffer having the same length as inputBuffer. It can be used as
111     // intermediate buffer in the generating algorithm.
112     std::vector<float> mOutputBuffer;
113 
114     void init_params(const Parameter::Common& common);
115     void configure();
116 
117     float getDistortionOutputGain() const;
118     float getFloatProperty(const std::string& key, float defaultValue) const;
119     void addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter);
120     void buildProcessingChain();
121     float* runProcessingChain(float* buf1, float* buf2, size_t frameCount);
122 
123     std::string paramToString(const struct HapticGeneratorParam& param) const;
124     std::string contextToString() const;
125 };
126 
127 }  // namespace aidl::android::hardware::audio::effect
128