|
28 | 28 | #include <unistd.h> // For CPU affinity |
29 | 29 | #include "SynthWorkload.h" |
30 | 30 |
|
| 31 | +/** |
| 32 | + * @class AudioWorkloadTest |
| 33 | + * @brief A class designed to test audio workload performance using the Oboe library. |
| 34 | + * |
| 35 | + * This class sets up an audio stream, generates a synthetic audio load (sine wave and/or |
| 36 | + * a more complex synth workload), and collects statistics about the audio callback performance, |
| 37 | + * such as callback duration, XRun counts, and CPU usage. |
| 38 | + */ |
31 | 39 | class AudioWorkloadTest : oboe::AudioStreamDataCallback { |
32 | 40 | public: |
| 41 | + /** |
| 42 | + * @struct CallbackStatus |
| 43 | + * @brief Structure to store statistics for each audio callback invocation. |
| 44 | + */ |
33 | 45 | struct CallbackStatus { |
34 | | - int32_t numVoices; |
35 | | - int64_t beginTimeNs; |
36 | | - int64_t finishTimeNs; |
37 | | - int32_t xRunCount; |
38 | | - int32_t cpuIndex; |
| 46 | + int32_t numVoices; // Number of synthesizer voices active during this callback |
| 47 | + int64_t beginTimeNs; // Timestamp (nanoseconds) when the callback started |
| 48 | + int64_t finishTimeNs; // Timestamp (nanoseconds) when the callback finished |
| 49 | + int32_t xRunCount; // Cumulative XRun (underrun/overrun) count at this point |
| 50 | + int32_t cpuIndex; // CPU core index on which the callback executed |
39 | 51 | }; |
40 | 52 |
|
| 53 | + /** |
| 54 | + * @brief Constructor for AudioWorkloadTest. |
| 55 | + * Initializes the audio stream pointer to nullptr. |
| 56 | + */ |
41 | 57 | AudioWorkloadTest(); |
| 58 | + |
| 59 | + /** |
| 60 | + * @brief Opens an audio stream with specified parameters. |
| 61 | + * Configures the stream for low latency output. |
| 62 | + * @return 0 on success, or a negative Oboe error code on failure. |
| 63 | + */ |
42 | 64 | int32_t open(); |
| 65 | + |
| 66 | + /** |
| 67 | + * @brief Gets the number of frames processed in a single audio callback burst. |
| 68 | + * @return The number of frames per burst. |
| 69 | + */ |
43 | 70 | int32_t getFramesPerBurst() const; |
| 71 | + |
| 72 | + /** |
| 73 | + * @brief Gets the sample rate of the audio stream. |
| 74 | + * @return The sample rate in Hz. |
| 75 | + */ |
44 | 76 | int32_t getSampleRate() const; |
| 77 | + |
| 78 | + /** |
| 79 | + * @brief Gets the current buffer size of the audio stream in frames. |
| 80 | + * @return The buffer size in frames. |
| 81 | + */ |
45 | 82 | int32_t getBufferSizeInFrames() const; |
46 | | - int32_t start(int32_t numCallbacks, int32_t bufferSizeInBursts, int32_t numVoices, int32_t alternateNumVoices, int32_t alternatingPeriodMs, bool adpfEnabled, bool sineEnabled); |
| 83 | + |
| 84 | + /** |
| 85 | + * @brief Starts the audio stream and the workload test. |
| 86 | + * @param targetDurationMillis The desired duration of the test in milliseconds. |
| 87 | + * @param bufferSizeInBursts The desired buffer size in terms of multiples of framesPerBurst. |
| 88 | + * @param numVoices The primary number of synthesizer voices to simulate. |
| 89 | + * @param alternateNumVoices An alternative number of voices for alternating workload. |
| 90 | + * @param alternatingPeriodMs The period in milliseconds to alternate between numVoices and |
| 91 | + * alternateNumVoices. |
| 92 | + * @param adpfEnabled Whether to enable Adaptive Performance (ADPF) hints. |
| 93 | + * @param hearWorkload If true, the synthesized audio will be audible; otherwise, it's processed |
| 94 | + * silently. |
| 95 | + * @return 0 on success, or a negative Oboe error code on failure. |
| 96 | + */ |
| 97 | + int32_t start(int32_t targetDurationMillis, int32_t bufferSizeInBursts, int32_t numVoices, |
| 98 | + int32_t alternateNumVoices, int32_t alternatingPeriodMs, bool adpfEnabled, |
| 99 | + bool hearWorkload); |
| 100 | + |
| 101 | + /** |
| 102 | + * @brief Gets the number of available CPU cores on the system. |
| 103 | + * @return The number of CPU cores. |
| 104 | + */ |
47 | 105 | static int32_t getCpuCount(); |
| 106 | + |
| 107 | + /** |
| 108 | + * @brief Sets the CPU affinity for the current thread (intended for the audio callback |
| 109 | + * thread). |
| 110 | + * @param mask A bitmask specifying the allowed CPU cores. |
| 111 | + * @return 0 on success, -1 on failure. |
| 112 | + */ |
48 | 113 | static int32_t setCpuAffinityForCallback(uint32_t mask); |
49 | | - int32_t getXRunCount(); |
50 | | - int32_t getCallbackCount(); |
| 114 | + |
| 115 | + /** |
| 116 | + * @brief Gets the number of XRuns (underruns/overruns) that occurred during the last test run. |
| 117 | + * @return The XRun count. |
| 118 | + */ |
| 119 | + int32_t getXRunCount() const; |
| 120 | + |
| 121 | + /** |
| 122 | + * @brief Gets the total number of audio callbacks invoked during the last test run. |
| 123 | + * @return The callback count. |
| 124 | + */ |
| 125 | + int32_t getCallbackCount() const; |
| 126 | + |
| 127 | + /** |
| 128 | + * @brief Gets the duration of the last audio callback in nanoseconds. |
| 129 | + * @return The duration in nanoseconds. |
| 130 | + */ |
51 | 131 | int64_t getLastDurationNs(); |
| 132 | + |
| 133 | + /** |
| 134 | + * @brief Checks if the audio workload test is currently running. |
| 135 | + * @return True if running, false otherwise. |
| 136 | + */ |
52 | 137 | bool isRunning(); |
| 138 | + |
| 139 | + /** |
| 140 | + * @brief Stops the audio stream. |
| 141 | + * @return 0 on success, or a negative Oboe error code on failure. |
| 142 | + */ |
53 | 143 | int32_t stop(); |
| 144 | + |
| 145 | + /** |
| 146 | + * @brief Closes the audio stream and releases resources. |
| 147 | + * @return 0 on success. |
| 148 | + */ |
54 | 149 | int32_t close(); |
| 150 | + |
| 151 | + /** |
| 152 | + * @brief Retrieves the collected statistics for each audio callback. |
| 153 | + * @return A vector of CallbackStatus structures. |
| 154 | + */ |
55 | 155 | std::vector<CallbackStatus> getCallbackStatistics(); |
56 | | - oboe::DataCallbackResult onAudioReady(oboe::AudioStream* audioStream, void* audioData, int32_t numFrames) override; |
| 156 | + |
| 157 | + /** |
| 158 | + * @brief The Oboe audio callback function. |
| 159 | + * This function is called by the Oboe library when it needs more audio data. |
| 160 | + * It generates audio, performs workload simulation, and collects statistics. |
| 161 | + * @param audioStream Pointer to the Oboe audio stream. |
| 162 | + * @param audioData Pointer to the buffer where audio data should be written. |
| 163 | + * @param numFrames The number of audio frames to be filled. |
| 164 | + * @return oboe::DataCallbackResult::Continue to continue streaming, or |
| 165 | + * oboe::DataCallbackResult::Stop to stop. |
| 166 | + */ |
| 167 | + oboe::DataCallbackResult onAudioReady(oboe::AudioStream* audioStream, void* audioData, |
| 168 | + int32_t numFrames) override; |
57 | 169 |
|
58 | 170 | private: |
59 | | - oboe::AudioStream* mStream; |
| 171 | + // Member variables |
| 172 | + oboe::AudioStream* mStream; // Pointer to the Oboe audio stream instance |
| 173 | + |
| 174 | + // Atomic variables for thread-safe access from audio callback and other threads |
60 | 175 | std::atomic<int32_t> mFramesPerBurst{0}; |
61 | 176 | std::atomic<int32_t> mSampleRate{0}; |
62 | 177 | std::atomic<int32_t> mCallbackCount{0}; |
63 | 178 | std::atomic<int32_t> mPreviousXRunCount{0}; |
64 | 179 | std::atomic<int32_t> mXRunCount{0}; |
65 | | - std::atomic<int32_t> mNumCallbacks{0}; |
| 180 | + std::atomic<int32_t> mTargetDurationMs{0}; |
66 | 181 | std::atomic<int32_t> mBufferSizeInBursts{0}; |
67 | 182 | std::atomic<int32_t> mBufferSizeInFrames{0}; |
68 | 183 | std::atomic<int32_t> mNumVoices{0}; |
69 | 184 | std::atomic<int32_t> mAlternateNumVoices{0}; |
70 | 185 | std::atomic<int32_t> mAlternatingPeriodMs{0}; |
71 | 186 | std::atomic<int64_t> mLastDurationNs{0}; |
72 | 187 | std::atomic<int64_t> mStartTimeMs{0}; |
73 | | - std::atomic<bool> mSineEnabled{false}; |
| 188 | + std::atomic<bool> mHearWorkload{false}; |
| 189 | + |
74 | 190 | std::vector<CallbackStatus> mCallbackStatistics; |
75 | 191 | std::atomic<bool> mRunning{false}; |
76 | | - SynthWorkload mSynthWorkload; |
| 192 | + |
| 193 | + // Sine wave generation parameters |
| 194 | + std::atomic<float> mPhase{0.0f}; // Current phase of the sine wave oscillator |
| 195 | + // Phase increment for a 440 Hz sine wave at a 48000 Hz sample rate |
| 196 | + static constexpr float kPhaseIncrement = 2.0f * (float) M_PI * 440.0f / 48000.0f; |
| 197 | + |
| 198 | + SynthWorkload mSynthWorkload; // Instance of the synthetic workload generator |
77 | 199 | }; |
78 | 200 |
|
79 | 201 | #endif // AUDIO_WORKLOAD_TEST_H |
0 commit comments