mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Merge pull request #3835 from birarda/lobby
lobby changes, Sound and AudioInjectorOptions stereo tweaks
This commit is contained in:
commit
925e2fab66
11 changed files with 138 additions and 52 deletions
|
@ -14,11 +14,10 @@ var position = { x: 700, y: 25, z: 725 };
|
|||
var audioOptions = {
|
||||
position: position,
|
||||
volume: 0.4,
|
||||
loop: true,
|
||||
stereo: false
|
||||
loop: true
|
||||
};
|
||||
|
||||
var sound = SoundCache.getSound(soundURL, audioOptions.isStereo);
|
||||
var sound = SoundCache.getSound(soundURL);
|
||||
var injector = null;
|
||||
var count = 100;
|
||||
|
||||
|
|
|
@ -39,18 +39,23 @@ var ORB_SHIFT = { x: 0, y: -1.4, z: -0.8};
|
|||
|
||||
var HELMET_ATTACHMENT_URL = HIFI_PUBLIC_BUCKET + "models/attachments/IronManMaskOnly.fbx"
|
||||
|
||||
var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.raw")
|
||||
var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.stereo.raw")
|
||||
var currentDrone = null;
|
||||
|
||||
var latinSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.raw")
|
||||
var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.raw")
|
||||
var currentMusak = null;
|
||||
var latinSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.stereo.raw")
|
||||
var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.stereo.raw")
|
||||
var currentMusakInjector = null;
|
||||
var currentSound = null;
|
||||
|
||||
var inOculusMode = Menu.isOptionChecked("EnableVRMode");
|
||||
|
||||
function reticlePosition() {
|
||||
var RETICLE_DISTANCE = 1;
|
||||
return Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), RETICLE_DISTANCE));
|
||||
}
|
||||
|
||||
var MAX_NUM_PANELS = 21;
|
||||
|
||||
function drawLobby() {
|
||||
if (!panelWall) {
|
||||
print("Adding overlays for the lobby panel wall and orb shell.");
|
||||
|
@ -64,7 +69,7 @@ function drawLobby() {
|
|||
url: HIFI_PUBLIC_BUCKET + "models/sets/Lobby/LobbyPrototype/Lobby5_PanelsWithFrames.fbx",
|
||||
position: Vec3.sum(orbPosition, Vec3.multiplyQbyV(towardsMe, panelsCenterShift)),
|
||||
rotation: towardsMe,
|
||||
dimensions: panelsDimensions
|
||||
dimensions: panelsDimensions,
|
||||
};
|
||||
|
||||
var orbShellProps = {
|
||||
|
@ -77,21 +82,23 @@ function drawLobby() {
|
|||
|
||||
avatarStickPosition = MyAvatar.position;
|
||||
|
||||
panelWall = Overlays.addOverlay("model", panelWallProps);
|
||||
panelWall = Overlays.addOverlay("model", panelWallProps);
|
||||
orbShell = Overlays.addOverlay("model", orbShellProps);
|
||||
|
||||
// for HMD wearers, create a reticle in center of screen
|
||||
var CURSOR_SCALE = 0.025;
|
||||
|
||||
reticle = Overlays.addOverlay("billboard", {
|
||||
url: HIFI_PUBLIC_BUCKET + "images/cursor.svg",
|
||||
position: reticlePosition(),
|
||||
ignoreRayIntersection: true,
|
||||
isFacingAvatar: true,
|
||||
alpha: 1.0,
|
||||
scale: CURSOR_SCALE
|
||||
});
|
||||
if (inOculusMode) {
|
||||
var CURSOR_SCALE = 0.025;
|
||||
|
||||
reticle = Overlays.addOverlay("billboard", {
|
||||
url: HIFI_PUBLIC_BUCKET + "images/cursor.svg",
|
||||
position: reticlePosition(),
|
||||
ignoreRayIntersection: true,
|
||||
isFacingAvatar: true,
|
||||
alpha: 1.0,
|
||||
scale: CURSOR_SCALE
|
||||
});
|
||||
}
|
||||
|
||||
// add an attachment on this avatar so other people see them in the lobby
|
||||
MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15);
|
||||
|
||||
|
@ -125,39 +132,73 @@ function changeLobbyTextures() {
|
|||
Overlays.editOverlay(panelWall, textureProp);
|
||||
}
|
||||
|
||||
var MUSAK_VOLUME = 0.5;
|
||||
|
||||
function playNextMusak() {
|
||||
if (panelWall) {
|
||||
if (currentSound == latinSound) {
|
||||
if (elevatorSound.downloaded) {
|
||||
currentSound = elevatorSound;
|
||||
}
|
||||
} else if (currentSound == elevatorSound) {
|
||||
if (latinSound.downloaded) {
|
||||
currentSound = latinSound;
|
||||
}
|
||||
}
|
||||
|
||||
currentMusakInjector = Audio.playSound(currentSound, { localOnly: true, volume: MUSAK_VOLUME });
|
||||
}
|
||||
}
|
||||
|
||||
function playRandomMusak() {
|
||||
chosenSound = null;
|
||||
currentSound = null;
|
||||
|
||||
if (latinSound.downloaded && elevatorSound.downloaded) {
|
||||
chosenSound = Math.random < 0.5 ? latinSound : elevatorSound;
|
||||
currentSound = Math.random() < 0.5 ? latinSound : elevatorSound;
|
||||
} else if (latinSound.downloaded) {
|
||||
chosenSound = latinSound;
|
||||
currentSound = latinSound;
|
||||
} else if (elevatorSound.downloaded) {
|
||||
chosenSound = elevatorSound;
|
||||
currentSound = elevatorSound;
|
||||
}
|
||||
|
||||
if (chosenSound) {
|
||||
currentMusak = Audio.playSound(chosenSound, { stereo: true, localOnly: true })
|
||||
if (currentSound) {
|
||||
// pick a random number of seconds from 0-10 to offset the musak
|
||||
var secondOffset = Math.random() * 10;
|
||||
currentMusakInjector = Audio.playSound(currentSound, { localOnly: true, secondOffset: secondOffset, volume: MUSAK_VOLUME });
|
||||
} else {
|
||||
currentMusak = null;
|
||||
currentMusakInjector = null;
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupLobby() {
|
||||
|
||||
// for each of the 21 placeholder textures, set them back to default so the cached model doesn't have changed textures
|
||||
var panelTexturesReset = {};
|
||||
panelTexturesReset["textures"] = {};
|
||||
|
||||
for (var j = 0; j < MAX_NUM_PANELS; j++) {
|
||||
panelTexturesReset["textures"]["file" + (j + 1)] = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/LobbyPrototype/Texture.jpg";
|
||||
};
|
||||
|
||||
Overlays.editOverlay(panelWall, panelTexturesReset);
|
||||
|
||||
Overlays.deleteOverlay(panelWall);
|
||||
Overlays.deleteOverlay(orbShell);
|
||||
Overlays.deleteOverlay(reticle);
|
||||
|
||||
Audio.stopInjector(currentDrone);
|
||||
currentDrone = null;
|
||||
|
||||
Audio.stopInjector(currentMusak);
|
||||
currentMusak = null;
|
||||
if (reticle) {
|
||||
Overlays.deleteOverlay(reticle);
|
||||
}
|
||||
|
||||
panelWall = false;
|
||||
orbShell = false;
|
||||
reticle = false;
|
||||
|
||||
Audio.stopInjector(currentDrone);
|
||||
currentDrone = null;
|
||||
|
||||
Audio.stopInjector(currentMusakInjector);
|
||||
currentMusakInjector = null;
|
||||
|
||||
locations = {};
|
||||
toggleEnvironmentRendering(true);
|
||||
|
||||
|
@ -218,10 +259,18 @@ function toggleEnvironmentRendering(shouldRender) {
|
|||
|
||||
function update(deltaTime) {
|
||||
maybeCleanupLobby();
|
||||
if (reticle) {
|
||||
Overlays.editOverlay(reticle, {
|
||||
position: reticlePosition()
|
||||
});
|
||||
if (panelWall) {
|
||||
|
||||
if (reticle) {
|
||||
Overlays.editOverlay(reticle, {
|
||||
position: reticlePosition()
|
||||
});
|
||||
}
|
||||
|
||||
// if the reticle is up then we may need to play the next musak
|
||||
if (!Audio.isInjectorPlaying(currentMusakInjector)) {
|
||||
playNextMusak();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,12 @@
|
|||
Script.include("libraries/globals.js");
|
||||
|
||||
var modelURL = HIFI_PUBLIC_BUCKET + "models/entities/radio/Speakers.fbx";
|
||||
var soundURL = HIFI_PUBLIC_BUCKET + "sounds/FamilyStereo.raw";
|
||||
var soundURL = HIFI_PUBLIC_BUCKET + "sounds/family.stereo.raw";
|
||||
|
||||
var AudioRotationOffset = Quat.fromPitchYawRollDegrees(0, -90, 0);
|
||||
var audioOptions = {
|
||||
volume: 0.5,
|
||||
loop: true,
|
||||
stereo: true
|
||||
loop: true
|
||||
}
|
||||
|
||||
var injector = null;
|
||||
|
|
|
@ -78,6 +78,17 @@ float AudioInjector::getLoudness() {
|
|||
}
|
||||
|
||||
void AudioInjector::injectAudio() {
|
||||
|
||||
// check if we need to offset the sound by some number of seconds
|
||||
if (_options.secondOffset > 0.0f) {
|
||||
|
||||
// convert the offset into a number of bytes
|
||||
int byteOffset = (int) floorf(SAMPLE_RATE * _options.secondOffset * (_options.stereo ? 2.0f : 1.0f));
|
||||
byteOffset *= sizeof(int16_t);
|
||||
|
||||
_currentSendPosition = byteOffset;
|
||||
}
|
||||
|
||||
if (_options.localOnly) {
|
||||
injectLocally();
|
||||
} else {
|
||||
|
@ -89,10 +100,14 @@ void AudioInjector::injectLocally() {
|
|||
bool success = false;
|
||||
if (_localAudioInterface) {
|
||||
if (_audioData.size() > 0) {
|
||||
|
||||
_localBuffer = new AudioInjectorLocalBuffer(_audioData, this);
|
||||
_localBuffer->open(QIODevice::ReadOnly);
|
||||
_localBuffer->setShouldLoop(_options.loop);
|
||||
|
||||
// give our current send position to the local buffer
|
||||
_localBuffer->setCurrentOffset(_currentSendPosition);
|
||||
|
||||
QMetaObject::invokeMethod(_localAudioInterface, "outputLocalInjector",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, success),
|
||||
|
@ -100,7 +115,8 @@ void AudioInjector::injectLocally() {
|
|||
Q_ARG(qreal, _options.volume),
|
||||
Q_ARG(AudioInjector*, this));
|
||||
|
||||
|
||||
// if we're not looping and the buffer tells us it is empty then emit finished
|
||||
connect(_localBuffer, &AudioInjectorLocalBuffer::bufferEmpty, this, &AudioInjector::stop);
|
||||
|
||||
if (!success) {
|
||||
qDebug() << "AudioInjector::injectLocally could not output locally via _localAudioInterface";
|
||||
|
|
|
@ -47,6 +47,11 @@ qint64 AudioInjectorLocalBuffer::readData(char* data, qint64 maxSize) {
|
|||
_currentOffset += bytesRead;
|
||||
}
|
||||
|
||||
if (!_shouldLoop && bytesRead == bytesToEnd) {
|
||||
// we hit the end of the buffer, emit a signal
|
||||
emit bufferEmpty();
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
} else {
|
||||
return 0;
|
||||
|
|
|
@ -26,6 +26,9 @@ public:
|
|||
|
||||
void setShouldLoop(bool shouldLoop) { _shouldLoop = shouldLoop; }
|
||||
|
||||
void setCurrentOffset(int currentOffset) { _currentOffset = currentOffset; }
|
||||
signals:
|
||||
void bufferEmpty();
|
||||
private:
|
||||
|
||||
qint64 recursiveReadFromFront(char* data, qint64 maxSize);
|
||||
|
|
|
@ -20,7 +20,8 @@ AudioInjectorOptions::AudioInjectorOptions() :
|
|||
orientation(glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||
stereo(false),
|
||||
ignorePenumbra(false),
|
||||
localOnly(false)
|
||||
localOnly(false),
|
||||
secondOffset(0.0)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -31,9 +32,9 @@ QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInje
|
|||
obj.setProperty("volume", injectorOptions.volume);
|
||||
obj.setProperty("loop", injectorOptions.loop);
|
||||
obj.setProperty("orientation", quatToScriptValue(engine, injectorOptions.orientation));
|
||||
obj.setProperty("stereo", injectorOptions.stereo);
|
||||
obj.setProperty("ignorePenumbra", injectorOptions.ignorePenumbra);
|
||||
obj.setProperty("localOnly", injectorOptions.localOnly);
|
||||
obj.setProperty("secondOffset", injectorOptions.secondOffset);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -54,10 +55,6 @@ void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOpt
|
|||
quatFromScriptValue(object.property("orientation"), injectorOptions.orientation);
|
||||
}
|
||||
|
||||
if (object.property("stereo").isValid()) {
|
||||
injectorOptions.stereo = object.property("stereo").toBool();
|
||||
}
|
||||
|
||||
if (object.property("ignorePenumbra").isValid()) {
|
||||
injectorOptions.ignorePenumbra = object.property("ignorePenumbra").toBool();
|
||||
}
|
||||
|
@ -65,4 +62,8 @@ void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOpt
|
|||
if (object.property("localOnly").isValid()) {
|
||||
injectorOptions.localOnly = object.property("localOnly").toBool();
|
||||
}
|
||||
|
||||
if (object.property("secondOffset").isValid()) {
|
||||
injectorOptions.secondOffset = object.property("secondOffset").toNumber();
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ public:
|
|||
bool stereo;
|
||||
bool ignorePenumbra;
|
||||
bool localOnly;
|
||||
float secondOffset;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AudioInjectorOptions);
|
||||
|
|
|
@ -44,7 +44,11 @@ void AudioScriptingInterface::stopAllInjectors() {
|
|||
|
||||
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
||||
if (sound) {
|
||||
AudioInjector* injector = new AudioInjector(sound, injectorOptions);
|
||||
// stereo option isn't set from script, this comes from sound metadata or filename
|
||||
AudioInjectorOptions optionsCopy = injectorOptions;
|
||||
optionsCopy.stereo = sound->isStereo();
|
||||
|
||||
AudioInjector* injector = new AudioInjector(sound, optionsCopy);
|
||||
injector->setLocalAudioInterface(_localAudioInterface);
|
||||
|
||||
QThread* injectorThread = new QThread();
|
||||
|
|
|
@ -64,7 +64,14 @@ void Sound::downloadFinished(QNetworkReply* reply) {
|
|||
interpretAsWav(rawAudioByteArray, outputAudioByteArray);
|
||||
downSample(outputAudioByteArray);
|
||||
} else {
|
||||
// Process as RAW file
|
||||
// check if this was a stereo raw file
|
||||
// since it's raw the only way for us to know that is if the file was called .stereo.raw
|
||||
if (reply->url().fileName().toLower().endsWith("stereo.raw")) {
|
||||
_isStereo = true;
|
||||
qDebug() << "Processing sound from" << reply->url() << "as stereo audio file.";
|
||||
}
|
||||
|
||||
// Process as RAW file
|
||||
downSample(rawAudioByteArray);
|
||||
}
|
||||
trimFrames();
|
||||
|
@ -206,10 +213,12 @@ void Sound::interpretAsWav(const QByteArray& inputAudioByteArray, QByteArray& ou
|
|||
qDebug() << "Currently not supporting non PCM audio files.";
|
||||
return;
|
||||
}
|
||||
if (qFromLittleEndian<quint16>(fileHeader.wave.numChannels) != 1) {
|
||||
qDebug() << "Currently not supporting stereo audio files.";
|
||||
return;
|
||||
if (qFromLittleEndian<quint16>(fileHeader.wave.numChannels) == 2) {
|
||||
_isStereo = true;
|
||||
} else if (qFromLittleEndian<quint16>(fileHeader.wave.numChannels) > 2) {
|
||||
qDebug() << "Currently not support audio files with more than 2 channels.";
|
||||
}
|
||||
|
||||
if (qFromLittleEndian<quint16>(fileHeader.wave.bitsPerSample) != 16) {
|
||||
qDebug() << "Currently not supporting non 16bit audio files.";
|
||||
return;
|
||||
|
|
|
@ -25,7 +25,7 @@ class Sound : public Resource {
|
|||
public:
|
||||
Sound(const QUrl& url, bool isStereo = false);
|
||||
|
||||
bool isStereo() const { return _isStereo; }
|
||||
bool isStereo() const { return _isStereo; }
|
||||
bool isReady() const { return _isReady; }
|
||||
|
||||
const QByteArray& getByteArray() { return _byteArray; }
|
||||
|
|
Loading…
Reference in a new issue