Add support for audio playback via audout

Adds an audio manager to state to manage the creation of audio tracks and an audout service implementation that interfaces with it.
This commit is contained in:
Billy Laws
2020-01-02 20:19:34 +00:00
committed by ◱ PixelyIon
parent 08bbc66b09
commit 93206d5a3c
15 changed files with 513 additions and 1 deletions

View File

@ -0,0 +1,64 @@
#include "audio.h"
namespace skyline::audio {
Audio::Audio(const DeviceState &state) : state(state), oboe::AudioStreamCallback() {
oboe::AudioStreamBuilder builder;
builder.setChannelCount(constant::ChannelCount)
->setSampleRate(constant::SampleRate)
->setFormat(constant::PcmFormat)
->setCallback(this)
->openManagedStream(outputStream);
outputStream->requestStart();
}
std::shared_ptr<AudioTrack> Audio::OpenTrack(int channelCount, int sampleRate, const std::function<void()> &releaseCallback) {
std::shared_ptr<AudioTrack> track = std::make_shared<AudioTrack>(channelCount, sampleRate, releaseCallback);
audioTracks.push_back(track);
return track;
}
void Audio::CloseTrack(std::shared_ptr<AudioTrack> &track) {
audioTracks.erase(std::remove(audioTracks.begin(), audioTracks.end(), track), audioTracks.end());
track.reset();
}
oboe::DataCallbackResult Audio::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
i16 *destBuffer = static_cast<i16 *>(audioData);
int setIndex = 0;
size_t sampleI16Size = static_cast<size_t>(numFrames) * audioStream->getChannelCount();
for (auto &track : audioTracks) {
if (track->playbackState == AudioOutState::Stopped)
continue;
track->bufferLock.lock();
std::queue<i16> &srcBuffer = track->sampleQueue;
size_t amount = std::min(srcBuffer.size(), sampleI16Size);
for (size_t i = 0; i < amount; i++) {
if (setIndex == i) {
destBuffer[i] = srcBuffer.front();
setIndex++;
} else {
destBuffer[i] += srcBuffer.front();
}
srcBuffer.pop();
}
track->sampleCounter += amount;
track->CheckReleasedBuffers();
track->bufferLock.unlock();
}
if (sampleI16Size > setIndex)
memset(destBuffer, 0, (sampleI16Size - setIndex) * 2);
return oboe::DataCallbackResult::Continue;
}
}