Add "pitch" parameter to scriptable audio injector options.

Used in playSound() to pitch-shift the audio when injector is created.
This commit is contained in:
Ken Cooke 2018-01-19 14:50:51 -08:00
parent 95d0e8aa56
commit a421ba7649
3 changed files with 43 additions and 5 deletions

View file

@ -463,10 +463,39 @@ AudioInjectorPointer AudioInjector::playSoundAndDelete(const QByteArray& buffer,
AudioInjectorPointer AudioInjector::playSound(const QByteArray& buffer, const AudioInjectorOptions options) {
AudioInjectorPointer injector = AudioInjectorPointer::create(buffer, options);
if (!injector->inject(&AudioInjectorManager::threadInjector)) {
qWarning() << "AudioInjector::playSound failed to thread injector";
if (options.pitch == 1.0f) {
AudioInjectorPointer injector = AudioInjectorPointer::create(buffer, options);
if (!injector->inject(&AudioInjectorManager::threadInjector)) {
qWarning() << "AudioInjector::playSound failed to thread injector";
}
return injector;
} else {
const int standardRate = AudioConstants::SAMPLE_RATE;
const int resampledRate = AudioConstants::SAMPLE_RATE / glm::clamp(options.pitch, 1/16.0f, 16.0f); // limit to 4 octaves
const int numChannels = options.ambisonic ? AudioConstants::AMBISONIC :
(options.stereo ? AudioConstants::STEREO : AudioConstants::MONO);
AudioSRC resampler(standardRate, resampledRate, numChannels);
// create a resampled buffer that is guaranteed to be large enough
const int nInputFrames = buffer.size() / (numChannels * sizeof(int16_t));
const int maxOutputFrames = resampler.getMaxOutput(nInputFrames);
QByteArray resampledBuffer(maxOutputFrames * numChannels * sizeof(int16_t), '\0');
resampler.render(reinterpret_cast<const int16_t*>(buffer.data()),
reinterpret_cast<int16_t*>(resampledBuffer.data()),
nInputFrames);
AudioInjectorPointer injector = AudioInjectorPointer::create(resampledBuffer, options);
if (!injector->inject(&AudioInjectorManager::threadInjector)) {
qWarning() << "AudioInjector::playSound failed to thread pitch-shifted injector";
}
return injector;
}
return injector;
}

View file

@ -26,7 +26,8 @@ AudioInjectorOptions::AudioInjectorOptions() :
ambisonic(false),
ignorePenumbra(false),
localOnly(false),
secondOffset(0.0f)
secondOffset(0.0f),
pitch(1.0f)
{
}
@ -40,6 +41,7 @@ QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInje
obj.setProperty("ignorePenumbra", injectorOptions.ignorePenumbra);
obj.setProperty("localOnly", injectorOptions.localOnly);
obj.setProperty("secondOffset", injectorOptions.secondOffset);
obj.setProperty("pitch", injectorOptions.pitch);
return obj;
}
@ -87,6 +89,12 @@ void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOpt
} else {
qCWarning(audio) << "Audio injector options: secondOffset is not a number";
}
} else if (it.name() == "pitch") {
if (it.value().isNumber()) {
injectorOptions.pitch = it.value().toNumber();
} else {
qCWarning(audio) << "Audio injector options: pitch is not a number";
}
} else {
qCWarning(audio) << "Unknown audio injector option:" << it.name();
}

View file

@ -29,6 +29,7 @@ public:
bool ignorePenumbra;
bool localOnly;
float secondOffset;
float pitch; // multiplier, where 2.0f shifts up one octave
};
Q_DECLARE_METATYPE(AudioInjectorOptions);