implement SkAudioPLayer for Android
move SkAudioPlayer for Android to proper module refine playback features for the Android AudioPlayer Change-Id: I1906c3b3ef91fa4173f66c2c068dc40a3cf824ca Reviewed-on: https://skia-review.googlesource.com/c/skia/+/319037 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Jorge Betancourt <jmbetancourt@google.com>
This commit is contained in:
parent
1c50643b3c
commit
f607dbbbe8
1
BUILD.gn
1
BUILD.gn
@ -2353,7 +2353,6 @@ if (skia_enable_tools) {
|
||||
":skia",
|
||||
"modules/skottie",
|
||||
"modules/sksg:samples",
|
||||
"//third_party/oboe",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,10 @@ component("audioplayer") {
|
||||
"sfml-system",
|
||||
"sfml-audio",
|
||||
]
|
||||
} else if (is_android) {
|
||||
sources += [ "SkAudioPlayer_oboe.cpp" ]
|
||||
deps += [ "../../third_party/oboe" ]
|
||||
libs = [ "OpenSLES" ]
|
||||
} else {
|
||||
sources += [ "SkAudioPlayer_none.cpp" ]
|
||||
}
|
||||
|
119
modules/audioplayer/SkAudioPlayer_oboe.cpp
Normal file
119
modules/audioplayer/SkAudioPlayer_oboe.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2020 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "modules/audioplayer/SkAudioPlayer.h"
|
||||
|
||||
#include "include/core/SkData.h"
|
||||
#include "oboe/Oboe.h"
|
||||
#include "stream/MemInputStream.h"
|
||||
#include "wav/WavStreamReader.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class OboeAudioPlayer final : public SkAudioPlayer, oboe::AudioStreamCallback {
|
||||
public:
|
||||
explicit OboeAudioPlayer(sk_sp<SkData> data)
|
||||
: fData(std::move(data))
|
||||
, fMemInputStream(const_cast<unsigned char *>
|
||||
(static_cast<const unsigned char *>(fData->data())), static_cast<int32_t>(fData->size()))
|
||||
{
|
||||
// wrap data in MemInputStream to parse WAV header
|
||||
fReader = std::make_unique<parselib::WavStreamReader>(&fMemInputStream);
|
||||
fReader->parse();
|
||||
// set member variables and builder properties using reader
|
||||
fNumSampleFrames = fReader->getNumSampleFrames();
|
||||
|
||||
oboe::AudioStreamBuilder builder;
|
||||
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
|
||||
builder.setSharingMode(oboe::SharingMode::Exclusive);
|
||||
builder.setSampleRate(fReader->getSampleRate());
|
||||
builder.setChannelCount(fReader->getNumChannels());
|
||||
builder.setCallback(this);
|
||||
builder.setFormat(oboe::AudioFormat::Float);
|
||||
|
||||
// open the stream (must manually close it when done)
|
||||
fStream = nullptr;
|
||||
builder.openStream(fStream);
|
||||
}
|
||||
|
||||
private:
|
||||
oboe::DataCallbackResult
|
||||
onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override {
|
||||
// we assume float samples here
|
||||
float *outBuffer = static_cast<float *>(audioData);
|
||||
int framesRead = fReader->getDataFloat(outBuffer, numFrames);
|
||||
fReadFrameIndex += framesRead;
|
||||
int remainingFrames = numFrames - framesRead;
|
||||
if (remainingFrames > 0) {
|
||||
if (fIsLooping) {
|
||||
// handle wrap around
|
||||
fReader->positionToAudio();
|
||||
fReader->getDataFloat(&outBuffer[framesRead * fReader->getNumChannels()],
|
||||
remainingFrames);
|
||||
fReadFrameIndex += remainingFrames;
|
||||
} else {
|
||||
// render silence for rest
|
||||
renderSilence(&outBuffer[framesRead * fReader->getNumChannels()], remainingFrames);
|
||||
return oboe::DataCallbackResult::Stop;
|
||||
}
|
||||
}
|
||||
return oboe::DataCallbackResult::Continue;
|
||||
}
|
||||
|
||||
void renderSilence(float *start, int numFrames) {
|
||||
for (int i = 0; i < numFrames * fReader->getNumChannels(); ++i) {
|
||||
start[i] = 0;
|
||||
}
|
||||
}
|
||||
double onGetDuration() const override {
|
||||
return fNumSampleFrames * fStream->getChannelCount() / fStream->getSampleRate();
|
||||
}
|
||||
|
||||
double onGetTime() const override {
|
||||
return (fReadFrameIndex * fStream->getChannelCount()) / fStream->getSampleRate();
|
||||
}
|
||||
|
||||
double onSetTime(double t) override {
|
||||
fReadFrameIndex = (t * fStream->getSampleRate()) / fStream->getChannelCount();
|
||||
return onGetTime();
|
||||
}
|
||||
|
||||
State onSetState(State state) override {
|
||||
switch (state) {
|
||||
case State::kPlaying: fStream->start(); break;
|
||||
case State::kStopped: fStream->close(); break;
|
||||
case State::kPaused : fStream->pause(); break;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
// TODO: implement rate function (change sample rate of AudioStream)
|
||||
float onSetRate(float r) override {
|
||||
return r;
|
||||
}
|
||||
|
||||
// TODO: implement volume function (multiply each sample by desired amplitude)
|
||||
float onSetVolume(float v) override {
|
||||
return v;
|
||||
}
|
||||
|
||||
const sk_sp<SkData> fData;
|
||||
std::shared_ptr<oboe::AudioStream> fStream;
|
||||
std::unique_ptr<parselib::WavStreamReader> fReader;
|
||||
parselib::MemInputStream fMemInputStream;
|
||||
int32_t fReadFrameIndex {0};
|
||||
int fNumSampleFrames;
|
||||
bool fIsLooping {false};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<SkAudioPlayer> SkAudioPlayer::Make(sk_sp<SkData> src) {
|
||||
return std::unique_ptr<SkAudioPlayer>(new OboeAudioPlayer(std::move(src)));
|
||||
}
|
3
third_party/oboe/BUILD.gn
vendored
3
third_party/oboe/BUILD.gn
vendored
@ -9,6 +9,7 @@ third_party("oboe") {
|
||||
public_include_dirs = [
|
||||
"../externals/oboe/include",
|
||||
"../externals/oboe/samples/parselib/src/main/cpp",
|
||||
"../externals/oboe/src/flowgraph",
|
||||
]
|
||||
include_dirs = [ "../externals/oboe/src" ]
|
||||
|
||||
@ -43,10 +44,12 @@ third_party("oboe") {
|
||||
"../externals/oboe/src/fifo/FifoController.cpp",
|
||||
"../externals/oboe/src/fifo/FifoControllerBase.cpp",
|
||||
"../externals/oboe/src/fifo/FifoControllerIndirect.cpp",
|
||||
"../externals/oboe/src/flowgraph/ChannelCountConverter.cpp",
|
||||
"../externals/oboe/src/flowgraph/ClipToRange.cpp",
|
||||
"../externals/oboe/src/flowgraph/FlowGraphNode.cpp",
|
||||
"../externals/oboe/src/flowgraph/ManyToMultiConverter.cpp",
|
||||
"../externals/oboe/src/flowgraph/MonoToMultiConverter.cpp",
|
||||
"../externals/oboe/src/flowgraph/MultiToMonoConverter.cpp",
|
||||
"../externals/oboe/src/flowgraph/RampLinear.cpp",
|
||||
"../externals/oboe/src/flowgraph/SampleRateConverter.cpp",
|
||||
"../externals/oboe/src/flowgraph/SinkFloat.cpp",
|
||||
|
Loading…
Reference in New Issue
Block a user