修复windows平台下音频播放问题。
This commit is contained in:
parent
aecd5a46ed
commit
fb216de107
|
|
@ -243,7 +243,27 @@ namespace Game
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.set_voice(samples, audioSampleRate, audioChannels);
|
if (!audioOutput->is_open() &&
|
||||||
|
!audioOutput->init("default", audioSampleRate, audioChannels))
|
||||||
|
{
|
||||||
|
std::cerr << "[WARN] Audio output init failed." << std::endl;
|
||||||
|
back_to_idle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t playbackSampleRate = audioOutput->get_sample_rate();
|
||||||
|
uint32_t playbackChannels = audioOutput->get_channels();
|
||||||
|
std::vector<int16_t> playbackSamples = samples;
|
||||||
|
if (playbackChannels != audioChannels)
|
||||||
|
{
|
||||||
|
playbackSamples = VoiceEffect::convert_channels(playbackSamples, audioChannels, playbackChannels);
|
||||||
|
}
|
||||||
|
if (playbackSampleRate != audioSampleRate)
|
||||||
|
{
|
||||||
|
playbackSamples = VoiceEffect::resample(playbackSamples, audioSampleRate, playbackSampleRate, playbackChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
player.set_voice(playbackSamples, playbackSampleRate, playbackChannels);
|
||||||
player.play();
|
player.play();
|
||||||
speakingAnimationMs = 0;
|
speakingAnimationMs = 0;
|
||||||
state = TomGameState::Speaking;
|
state = TomGameState::Speaking;
|
||||||
|
|
@ -259,7 +279,20 @@ namespace Game
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.update(*audioOutput, 1024);
|
const uint32_t playbackSampleRate = audioOutput->is_open() ? audioOutput->get_sample_rate() : audioSampleRate;
|
||||||
|
const uint32_t playbackChannels = audioOutput->is_open() ? audioOutput->get_channels() : audioChannels;
|
||||||
|
uint32_t requestCount = (playbackSampleRate * playbackChannels * deltaMs) / 1000u;
|
||||||
|
if (requestCount < playbackSampleRate * playbackChannels / 20u)
|
||||||
|
{
|
||||||
|
requestCount = playbackSampleRate * playbackChannels / 20u;
|
||||||
|
}
|
||||||
|
if (requestCount < playbackChannels)
|
||||||
|
{
|
||||||
|
requestCount = playbackChannels;
|
||||||
|
}
|
||||||
|
requestCount -= requestCount % playbackChannels;
|
||||||
|
|
||||||
|
player.update(*audioOutput, static_cast<int>(std::min<uint32_t>(requestCount, 8192u)));
|
||||||
if (player.is_finished())
|
if (player.is_finished())
|
||||||
{
|
{
|
||||||
back_to_idle();
|
back_to_idle();
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,94 @@ namespace Game
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<int16_t> VoiceEffect::resample(
|
||||||
|
const std::vector<int16_t>& samples,
|
||||||
|
uint32_t sourceRate,
|
||||||
|
uint32_t targetRate,
|
||||||
|
uint32_t channels)
|
||||||
|
{
|
||||||
|
if (samples.empty() || sourceRate == 0 || targetRate == 0 || channels == 0 || sourceRate == targetRate)
|
||||||
|
{
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t sourceFrameCount = samples.size() / channels;
|
||||||
|
if (sourceFrameCount == 0)
|
||||||
|
{
|
||||||
|
return std::vector<int16_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t targetFrameCount = std::max<size_t>(
|
||||||
|
1,
|
||||||
|
(sourceFrameCount * static_cast<size_t>(targetRate) + static_cast<size_t>(sourceRate) - 1) /
|
||||||
|
static_cast<size_t>(sourceRate));
|
||||||
|
std::vector<int16_t> output(targetFrameCount * channels, 0);
|
||||||
|
const float sourceStep = static_cast<float>(sourceRate) / static_cast<float>(targetRate);
|
||||||
|
|
||||||
|
for (size_t outFrame = 0; outFrame < targetFrameCount; ++outFrame)
|
||||||
|
{
|
||||||
|
const float sourceFrame = static_cast<float>(outFrame) * sourceStep;
|
||||||
|
const size_t source0 = std::min(static_cast<size_t>(sourceFrame), sourceFrameCount - 1);
|
||||||
|
const size_t source1 = std::min(source0 + 1, sourceFrameCount - 1);
|
||||||
|
const float t = sourceFrame - static_cast<float>(source0);
|
||||||
|
|
||||||
|
for (uint32_t channel = 0; channel < channels; ++channel)
|
||||||
|
{
|
||||||
|
const int16_t a = samples[source0 * channels + channel];
|
||||||
|
const int16_t b = samples[source1 * channels + channel];
|
||||||
|
const float mixed = static_cast<float>(a) + (static_cast<float>(b) - static_cast<float>(a)) * t;
|
||||||
|
output[outFrame * channels + channel] = clamp_to_sample(mixed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int16_t> VoiceEffect::convert_channels(
|
||||||
|
const std::vector<int16_t>& samples,
|
||||||
|
uint32_t sourceChannels,
|
||||||
|
uint32_t targetChannels)
|
||||||
|
{
|
||||||
|
if (samples.empty() || sourceChannels == 0 || targetChannels == 0 || sourceChannels == targetChannels)
|
||||||
|
{
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t frameCount = samples.size() / sourceChannels;
|
||||||
|
if (frameCount == 0)
|
||||||
|
{
|
||||||
|
return std::vector<int16_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int16_t> output(frameCount * targetChannels, 0);
|
||||||
|
for (size_t frame = 0; frame < frameCount; ++frame)
|
||||||
|
{
|
||||||
|
for (uint32_t targetChannel = 0; targetChannel < targetChannels; ++targetChannel)
|
||||||
|
{
|
||||||
|
if (sourceChannels == 1)
|
||||||
|
{
|
||||||
|
output[frame * targetChannels + targetChannel] = samples[frame * sourceChannels];
|
||||||
|
}
|
||||||
|
else if (targetChannels == 1)
|
||||||
|
{
|
||||||
|
int32_t mixed = 0;
|
||||||
|
for (uint32_t sourceChannel = 0; sourceChannel < sourceChannels; ++sourceChannel)
|
||||||
|
{
|
||||||
|
mixed += samples[frame * sourceChannels + sourceChannel];
|
||||||
|
}
|
||||||
|
output[frame] = static_cast<int16_t>(mixed / static_cast<int32_t>(sourceChannels));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const uint32_t sourceChannel = std::min(targetChannel, sourceChannels - 1);
|
||||||
|
output[frame * targetChannels + targetChannel] = samples[frame * sourceChannels + sourceChannel];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<int16_t> VoiceEffect::trim_silence(
|
std::vector<int16_t> VoiceEffect::trim_silence(
|
||||||
const std::vector<int16_t>& samples,
|
const std::vector<int16_t>& samples,
|
||||||
float threshold,
|
float threshold,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,17 @@ namespace Game
|
||||||
const std::vector<int16_t>& samples,
|
const std::vector<int16_t>& samples,
|
||||||
float gain);
|
float gain);
|
||||||
|
|
||||||
|
static std::vector<int16_t> resample(
|
||||||
|
const std::vector<int16_t>& samples,
|
||||||
|
uint32_t sourceRate,
|
||||||
|
uint32_t targetRate,
|
||||||
|
uint32_t channels = 1);
|
||||||
|
|
||||||
|
static std::vector<int16_t> convert_channels(
|
||||||
|
const std::vector<int16_t>& samples,
|
||||||
|
uint32_t sourceChannels,
|
||||||
|
uint32_t targetChannels);
|
||||||
|
|
||||||
static std::vector<int16_t> trim_silence(
|
static std::vector<int16_t> trim_silence(
|
||||||
const std::vector<int16_t>& samples,
|
const std::vector<int16_t>& samples,
|
||||||
float threshold = 0.02f,
|
float threshold = 0.02f,
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,10 @@ namespace Platform
|
||||||
channels_ = static_cast<uint32_t>(obtained.channels);
|
channels_ = static_cast<uint32_t>(obtained.channels);
|
||||||
opened_ = true;
|
opened_ = true;
|
||||||
|
|
||||||
|
std::cout << "SdlAudioInput opened: requested "
|
||||||
|
<< sample_rate << " Hz/" << channels << " ch, obtained "
|
||||||
|
<< sample_rate_ << " Hz/" << channels_ << " ch." << std::endl;
|
||||||
|
|
||||||
SDL_PauseAudioDevice(device_id_, 0);
|
SDL_PauseAudioDevice(device_id_, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,10 @@ namespace Platform
|
||||||
max_queued_samples_ = std::max<uint32_t>(channels_, sample_rate_ * channels_ / 8);
|
max_queued_samples_ = std::max<uint32_t>(channels_, sample_rate_ * channels_ / 8);
|
||||||
opened_ = true;
|
opened_ = true;
|
||||||
|
|
||||||
|
std::cout << "SdlAudioOutput opened: requested "
|
||||||
|
<< sample_rate << " Hz/" << channels << " ch, obtained "
|
||||||
|
<< sample_rate_ << " Hz/" << channels_ << " ch." << std::endl;
|
||||||
|
|
||||||
SDL_PauseAudioDevice(device_id_, 0);
|
SDL_PauseAudioDevice(device_id_, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue