1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci* Copyright 2020 Google Inc. 3cb93a386Sopenharmony_ci* 4cb93a386Sopenharmony_ci* Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci* found in the LICENSE file. 6cb93a386Sopenharmony_ci*/ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "modules/audioplayer/SkAudioPlayer.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkData.h" 11cb93a386Sopenharmony_ci#include "oboe/Oboe.h" 12cb93a386Sopenharmony_ci#include "stream/MemInputStream.h" 13cb93a386Sopenharmony_ci#include "wav/WavStreamReader.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_cinamespace { 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ciclass OboeAudioPlayer final : public SkAudioPlayer, oboe::AudioStreamCallback { 18cb93a386Sopenharmony_cipublic: 19cb93a386Sopenharmony_ci explicit OboeAudioPlayer(sk_sp<SkData> data) 20cb93a386Sopenharmony_ci : fData(std::move(data)) 21cb93a386Sopenharmony_ci , fMemInputStream(const_cast<unsigned char *> 22cb93a386Sopenharmony_ci (static_cast<const unsigned char *>(fData->data())), static_cast<int32_t>(fData->size())) 23cb93a386Sopenharmony_ci { 24cb93a386Sopenharmony_ci // wrap data in MemInputStream to parse WAV header 25cb93a386Sopenharmony_ci fReader = std::make_unique<parselib::WavStreamReader>(&fMemInputStream); 26cb93a386Sopenharmony_ci fReader->parse(); 27cb93a386Sopenharmony_ci // set member variables and builder properties using reader 28cb93a386Sopenharmony_ci fNumSampleFrames = fReader->getNumSampleFrames(); 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci oboe::AudioStreamBuilder builder; 31cb93a386Sopenharmony_ci builder.setPerformanceMode(oboe::PerformanceMode::LowLatency); 32cb93a386Sopenharmony_ci builder.setSharingMode(oboe::SharingMode::Exclusive); 33cb93a386Sopenharmony_ci builder.setSampleRate(fReader->getSampleRate()); 34cb93a386Sopenharmony_ci builder.setChannelCount(fReader->getNumChannels()); 35cb93a386Sopenharmony_ci builder.setCallback(this); 36cb93a386Sopenharmony_ci builder.setFormat(oboe::AudioFormat::Float); 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci // open the stream (must manually close it when done) 39cb93a386Sopenharmony_ci fStream = nullptr; 40cb93a386Sopenharmony_ci builder.openStream(fStream); 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ciprivate: 44cb93a386Sopenharmony_ci oboe::DataCallbackResult 45cb93a386Sopenharmony_ci onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override { 46cb93a386Sopenharmony_ci // we assume float samples here 47cb93a386Sopenharmony_ci float *outBuffer = static_cast<float *>(audioData); 48cb93a386Sopenharmony_ci int framesRead = fReader->getDataFloat(outBuffer, numFrames); 49cb93a386Sopenharmony_ci fReadFrameIndex += framesRead; 50cb93a386Sopenharmony_ci int remainingFrames = numFrames - framesRead; 51cb93a386Sopenharmony_ci if (remainingFrames > 0) { 52cb93a386Sopenharmony_ci if (fIsLooping) { 53cb93a386Sopenharmony_ci // handle wrap around 54cb93a386Sopenharmony_ci fReader->positionToAudio(); 55cb93a386Sopenharmony_ci fReader->getDataFloat(&outBuffer[framesRead * fReader->getNumChannels()], 56cb93a386Sopenharmony_ci remainingFrames); 57cb93a386Sopenharmony_ci fReadFrameIndex += remainingFrames; 58cb93a386Sopenharmony_ci } else { 59cb93a386Sopenharmony_ci // render silence for rest 60cb93a386Sopenharmony_ci renderSilence(&outBuffer[framesRead * fReader->getNumChannels()], remainingFrames); 61cb93a386Sopenharmony_ci return oboe::DataCallbackResult::Stop; 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci return oboe::DataCallbackResult::Continue; 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci void renderSilence(float *start, int numFrames) { 68cb93a386Sopenharmony_ci for (int i = 0; i < numFrames * fReader->getNumChannels(); ++i) { 69cb93a386Sopenharmony_ci start[i] = 0; 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci double onGetDuration() const override { 73cb93a386Sopenharmony_ci return fNumSampleFrames * fStream->getChannelCount() / fStream->getSampleRate(); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci double onGetTime() const override { 77cb93a386Sopenharmony_ci return (fReadFrameIndex * fStream->getChannelCount()) / fStream->getSampleRate(); 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci double onSetTime(double t) override { 81cb93a386Sopenharmony_ci fReadFrameIndex = (t * fStream->getSampleRate()) / fStream->getChannelCount(); 82cb93a386Sopenharmony_ci return onGetTime(); 83cb93a386Sopenharmony_ci } 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci State onSetState(State state) override { 86cb93a386Sopenharmony_ci switch (state) { 87cb93a386Sopenharmony_ci case State::kPlaying: fStream->start(); break; 88cb93a386Sopenharmony_ci case State::kStopped: fStream->close(); break; 89cb93a386Sopenharmony_ci case State::kPaused : fStream->pause(); break; 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci return state; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci // TODO: implement rate function (change sample rate of AudioStream) 97cb93a386Sopenharmony_ci float onSetRate(float r) override { 98cb93a386Sopenharmony_ci return r; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci // TODO: implement volume function (multiply each sample by desired amplitude) 102cb93a386Sopenharmony_ci float onSetVolume(float v) override { 103cb93a386Sopenharmony_ci return v; 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci const sk_sp<SkData> fData; 107cb93a386Sopenharmony_ci std::shared_ptr<oboe::AudioStream> fStream; 108cb93a386Sopenharmony_ci std::unique_ptr<parselib::WavStreamReader> fReader; 109cb93a386Sopenharmony_ci parselib::MemInputStream fMemInputStream; 110cb93a386Sopenharmony_ci int32_t fReadFrameIndex {0}; 111cb93a386Sopenharmony_ci int fNumSampleFrames; 112cb93a386Sopenharmony_ci bool fIsLooping {false}; 113cb93a386Sopenharmony_ci}; 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci} // namespace 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_cistd::unique_ptr<SkAudioPlayer> SkAudioPlayer::Make(sk_sp<SkData> src) { 118cb93a386Sopenharmony_ci return std::unique_ptr<SkAudioPlayer>(new OboeAudioPlayer(std::move(src))); 119cb93a386Sopenharmony_ci} 120