2020-04-19 23:04:05 +02:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
2020-03-27 20:36:02 +01:00
|
|
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
|
|
|
|
2020-01-02 21:19:34 +01:00
|
|
|
#include "audio.h"
|
|
|
|
|
|
|
|
namespace skyline::audio {
|
2020-06-15 17:38:49 +02:00
|
|
|
Audio::Audio(const DeviceState &state) : oboe::AudioStreamCallback() {
|
2022-11-16 21:12:17 +01:00
|
|
|
settings = std::shared_ptr<Settings>{state.settings};
|
|
|
|
|
2022-01-22 22:42:38 +01:00
|
|
|
builder.setChannelCount(constant::StereoChannelCount);
|
2020-04-17 23:35:31 +02:00
|
|
|
builder.setSampleRate(constant::SampleRate);
|
|
|
|
builder.setFormat(constant::PcmFormat);
|
|
|
|
builder.setUsage(oboe::Usage::Game);
|
|
|
|
builder.setCallback(this);
|
2021-03-20 19:33:11 +01:00
|
|
|
builder.setSharingMode(oboe::SharingMode::Exclusive);
|
|
|
|
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
|
2020-04-17 23:35:31 +02:00
|
|
|
|
|
|
|
builder.openManagedStream(outputStream);
|
2020-01-02 21:19:34 +01:00
|
|
|
outputStream->requestStart();
|
|
|
|
}
|
|
|
|
|
2020-11-03 10:44:09 +01:00
|
|
|
Audio::~Audio() {
|
|
|
|
outputStream->requestStop();
|
|
|
|
}
|
|
|
|
|
2020-04-22 19:02:27 +02:00
|
|
|
std::shared_ptr<AudioTrack> Audio::OpenTrack(u8 channelCount, u32 sampleRate, const std::function<void()> &releaseCallback) {
|
2022-04-25 16:00:30 +02:00
|
|
|
std::scoped_lock trackGuard{trackLock};
|
2020-04-17 23:35:31 +02:00
|
|
|
|
2020-08-21 15:28:47 +02:00
|
|
|
auto track{std::make_shared<AudioTrack>(channelCount, sampleRate, releaseCallback)};
|
2020-01-02 21:19:34 +01:00
|
|
|
audioTracks.push_back(track);
|
|
|
|
|
|
|
|
return track;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Audio::CloseTrack(std::shared_ptr<AudioTrack> &track) {
|
2022-04-25 16:00:30 +02:00
|
|
|
std::scoped_lock trackGuard{trackLock};
|
2020-04-17 23:35:31 +02:00
|
|
|
|
2020-01-02 21:19:34 +01:00
|
|
|
audioTracks.erase(std::remove(audioTracks.begin(), audioTracks.end(), track), audioTracks.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
oboe::DataCallbackResult Audio::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
|
2020-08-21 15:28:47 +02:00
|
|
|
auto destBuffer{static_cast<i16 *>(audioData)};
|
2021-10-24 21:45:29 +02:00
|
|
|
auto streamSamples{static_cast<size_t>(numFrames) * static_cast<size_t>(audioStream->getChannelCount())};
|
2020-08-21 15:28:47 +02:00
|
|
|
size_t writtenSamples{};
|
2020-04-17 23:35:31 +02:00
|
|
|
|
2020-08-21 15:28:47 +02:00
|
|
|
{
|
2022-04-25 16:00:30 +02:00
|
|
|
std::scoped_lock trackGuard{trackLock};
|
2020-01-02 21:19:34 +01:00
|
|
|
|
2020-08-21 15:28:47 +02:00
|
|
|
for (auto &track : audioTracks) {
|
|
|
|
if (track->playbackState == AudioOutState::Stopped)
|
|
|
|
continue;
|
2020-01-02 21:19:34 +01:00
|
|
|
|
2022-04-25 16:00:30 +02:00
|
|
|
std::scoped_lock bufferGuard{track->bufferLock};
|
2020-01-02 21:19:34 +01:00
|
|
|
|
2022-11-16 21:12:17 +01:00
|
|
|
if (!*settings->isAudioOutputDisabled) {
|
|
|
|
auto trackSamples{track->samples.Read(span(destBuffer, streamSamples), [](i16 *source, i16 *destination) {
|
|
|
|
*destination = Saturate<i16, i32>(static_cast<u32>(*destination) + static_cast<u32>(*source));
|
|
|
|
}, static_cast<ssize_t>(writtenSamples))};
|
2020-01-02 21:19:34 +01:00
|
|
|
|
2022-11-16 21:12:17 +01:00
|
|
|
writtenSamples = std::max(trackSamples, writtenSamples);
|
2020-01-02 21:19:34 +01:00
|
|
|
|
2022-11-16 21:12:17 +01:00
|
|
|
track->sampleCounter += trackSamples;
|
|
|
|
} else {
|
|
|
|
track->sampleCounter += streamSamples;
|
|
|
|
}
|
2020-08-21 15:28:47 +02:00
|
|
|
track->CheckReleasedBuffers();
|
|
|
|
}
|
2020-01-02 21:19:34 +01:00
|
|
|
}
|
|
|
|
|
2020-04-17 23:35:31 +02:00
|
|
|
if (streamSamples > writtenSamples)
|
|
|
|
memset(destBuffer + writtenSamples, 0, (streamSamples - writtenSamples) * sizeof(i16));
|
2020-01-02 21:19:34 +01:00
|
|
|
|
|
|
|
return oboe::DataCallbackResult::Continue;
|
|
|
|
}
|
2020-04-17 23:35:31 +02:00
|
|
|
|
|
|
|
void Audio::onErrorAfterClose(oboe::AudioStream *audioStream, oboe::Result error) {
|
2022-08-31 21:40:38 +02:00
|
|
|
builder.openManagedStream(outputStream);
|
|
|
|
outputStream->requestStart();
|
2020-04-17 23:35:31 +02:00
|
|
|
}
|
2020-01-02 21:19:34 +01:00
|
|
|
}
|