@@ -222,6 +222,10 @@ class ActivityContext {
222222 return 0.0 ;
223223 }
224224
225+ virtual double getPeakLevel (int streamIndex, int channelIndex) {
226+ return 0.0 ;
227+ }
228+
225229 static int64_t getNanoseconds (clockid_t clockId = CLOCK_MONOTONIC) {
226230 struct timespec time;
227231 int result = clock_gettime (clockId, &time);
@@ -867,6 +871,142 @@ class ActivityTestDisconnect : public ActivityContext {
867871 std::shared_ptr<oboe::flowgraph::SinkFloat> mSinkFloat ;
868872};
869873
874+ /* *
875+ * Test multiple streams.
876+ */
877+ class ActivityTestMultiStream : public ActivityContext {
878+ public:
879+ class MultiStreamCallback : public oboe ::AudioStreamDataCallback {
880+ public:
881+ MultiStreamCallback () {
882+ for (int i = 0 ; i < 8 ; i++) mPeakLevels [i] = 0.0 ;
883+ }
884+
885+ oboe::DataCallbackResult onAudioReady (oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) override {
886+ int channelCount = audioStream->getChannelCount ();
887+ if (channelCount > 8 ) channelCount = 8 ;
888+
889+ if (audioStream->getDirection () == oboe::Direction::Output) {
890+ int channelCount = audioStream->getChannelCount ();
891+ float phaseIncrement = 440 .0f * M_PI * 2 / (float )audioStream->getSampleRate ();
892+ if (audioStream->getFormat () == oboe::AudioFormat::Float) {
893+ float *floatData = (float *) audioData;
894+ for (int i = 0 ; i < numFrames; i++) {
895+ float sample = sinf (mPhase ) * 0 .5f ;
896+ mPhase += phaseIncrement;
897+ if (mPhase > M_PI * 2 ) mPhase -= (float )(M_PI * 2 );
898+ for (int c = 0 ; c < channelCount; c++) {
899+ *floatData++ = sample;
900+ }
901+ }
902+ } else if (audioStream->getFormat () == oboe::AudioFormat::I16) {
903+ int16_t *shortData = (int16_t *) audioData;
904+ for (int i = 0 ; i < numFrames; i++) {
905+ float sample = sinf (mPhase ) * 0 .5f ;
906+ mPhase += phaseIncrement;
907+ if (mPhase > M_PI * 2 ) mPhase -= (float )(M_PI * 2 );
908+ for (int c = 0 ; c < channelCount; c++) {
909+ *shortData++ = (int16_t )(sample * 32767 );
910+ }
911+ }
912+ } else if (audioStream->getFormat () == oboe::AudioFormat::I24) {
913+ uint8_t *byteData = (uint8_t *) audioData;
914+ for (int i = 0 ; i < numFrames; i++) {
915+ float sample = sinf (mPhase ) * 0 .5f ;
916+ mPhase += phaseIncrement;
917+ if (mPhase > M_PI * 2 ) mPhase -= (float )(M_PI * 2 );
918+ int32_t sample24 = (int32_t )(sample * 8388607 );
919+ for (int c = 0 ; c < channelCount; c++) {
920+ *byteData++ = (uint8_t )(sample24 & 0xFF );
921+ *byteData++ = (uint8_t )((sample24 >> 8 ) & 0xFF );
922+ *byteData++ = (uint8_t )((sample24 >> 16 ) & 0xFF );
923+ }
924+ }
925+ }
926+ }
927+
928+ // Measure peak level for both input and output
929+ if (audioStream->getFormat () == oboe::AudioFormat::Float) {
930+ float *floatData = (float *) audioData;
931+ for (int i = 0 ; i < numFrames; i++) {
932+ for (int c = 0 ; c < channelCount; c++) {
933+ float sample = std::abs (*floatData++);
934+ if (sample > mPeakLevels [c]) mPeakLevels [c] = sample;
935+ }
936+ }
937+ } else if (audioStream->getFormat () == oboe::AudioFormat::I16) {
938+ int16_t *shortData = (int16_t *) audioData;
939+ for (int i = 0 ; i < numFrames; i++) {
940+ for (int c = 0 ; c < channelCount; c++) {
941+ float sample = std::abs (*shortData++) / 32768 .0f ;
942+ if (sample > mPeakLevels [c]) mPeakLevels [c] = sample;
943+ }
944+ }
945+ } else if (audioStream->getFormat () == oboe::AudioFormat::I24) {
946+ uint8_t *byteData = (uint8_t *) audioData;
947+ for (int i = 0 ; i < numFrames; i++) {
948+ for (int c = 0 ; c < channelCount; c++) {
949+ int32_t sample24 = (byteData[0 ]) | (byteData[1 ] << 8 ) | (byteData[2 ] << 16 );
950+ if (sample24 & 0x800000 ) sample24 |= ~0xFFFFFF ; // sign extend
951+ float sample = std::abs (sample24) / 8388608 .0f ;
952+ byteData += 3 ;
953+ if (sample > mPeakLevels [c]) mPeakLevels [c] = sample;
954+ }
955+ }
956+ }
957+
958+ return oboe::DataCallbackResult::Continue;
959+ }
960+
961+ double getPeakLevel (int index) {
962+ if (index < 0 || index >= 8 ) return 0.0 ;
963+ double peak = mPeakLevels [index];
964+ mPeakLevels [index] = 0.0 ;
965+ return peak;
966+ }
967+ private:
968+ float mPhase = 0 .0f ;
969+ double mPeakLevels [8 ];
970+ };
971+
972+ ActivityTestMultiStream () = default ;
973+
974+ virtual ~ActivityTestMultiStream () = default ;
975+
976+ void configureBuilder (bool isInput, oboe::AudioStreamBuilder &builder) override {
977+ std::shared_ptr<MultiStreamCallback> callback = std::make_shared<MultiStreamCallback>();
978+ mCallbacks .push_back (callback);
979+ builder.setDataCallback (callback);
980+ }
981+
982+ oboe::Result startStreams () override {
983+ oboe::Result result = oboe::Result::OK;
984+ for (auto entry : mOboeStreams ) {
985+ std::shared_ptr<oboe::AudioStream> oboeStream = entry.second ;
986+ if (oboeStream) {
987+ result = oboeStream->requestStart ();
988+ if (result != oboe::Result::OK) break ;
989+ }
990+ }
991+ return result;
992+ }
993+
994+ double getPeakLevel (int streamIndex, int channelIndex) override {
995+ std::shared_ptr<oboe::AudioStream> oboeStream = getStream (streamIndex);
996+ if (oboeStream) {
997+ oboe::AudioStreamDataCallback *callback = oboeStream->getDataCallback ();
998+ if (callback) {
999+ MultiStreamCallback *myCallback = static_cast <MultiStreamCallback*>(callback);
1000+ return myCallback->getPeakLevel (channelIndex);
1001+ }
1002+ }
1003+ return 0.0 ;
1004+ }
1005+
1006+ private:
1007+ std::vector<std::shared_ptr<MultiStreamCallback>> mCallbacks ;
1008+ };
1009+
8701010/* *
8711011 * Global context for native tests.
8721012 * Switch between various ActivityContexts.
@@ -910,6 +1050,9 @@ class NativeAudioContext {
9101050 case ActivityType::DataPath:
9111051 currentActivity = &mActivityDataPath ;
9121052 break ;
1053+ case ActivityType::TestMultiStream:
1054+ currentActivity = &mActivityTestMultiStream ;
1055+ break ;
9131056 }
9141057 }
9151058
@@ -926,6 +1069,7 @@ class NativeAudioContext {
9261069 ActivityGlitches mActivityGlitches ;
9271070 ActivityDataPath mActivityDataPath ;
9281071 ActivityTestDisconnect mActivityTestDisconnect ;
1072+ ActivityTestMultiStream mActivityTestMultiStream ;
9291073
9301074private:
9311075
@@ -941,6 +1085,8 @@ class NativeAudioContext {
9411085 Glitches = 6 ,
9421086 TestDisconnect = 7 ,
9431087 DataPath = 8 ,
1088+ DynamicWorkload = 9 ,
1089+ TestMultiStream = 10 ,
9441090 };
9451091
9461092 ActivityType mActivityType = ActivityType::Undefined;
0 commit comments