Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 4 files). Show all
Unified · Split
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <QtNetwork/QNetworkRequest> | 14 | #include <QtNetwork/QNetworkRequest> |
| 15 | #include <QtNetwork/QNetworkReply> | 15 | #include <QtNetwork/QNetworkReply> |
| 16 | 16 | ||
| 17 | #include <AudioRingBuffer.h> | ||
| 17 | #include <AvatarData.h> | 18 | #include <AvatarData.h> |
| 18 | #include <NodeList.h> | 19 | #include <NodeList.h> |
| 19 | #include <PacketHeaders.h> | 20 | #include <PacketHeaders.h> |
| @@ -52,7 +53,9 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co · 32 unmodified lines | |||
| 52 | _avatarIdentityTimer(NULL), | 53 | _avatarIdentityTimer(NULL), |
| 53 | _avatarBillboardTimer(NULL), | 54 | _avatarBillboardTimer(NULL), |
| 54 | _timerFunctionMap(), | 55 | _timerFunctionMap(), |
| 55 | _avatarAudioBuffer(NULL), | 56 | _isListeningToAudioStream(false), |
| 57 | _avatarSound(NULL), | ||
| 58 | _numAvatarSoundSentBytes(0), | ||
| 56 | _controllerScriptingInterface(controllerScriptingInterface), | 59 | _controllerScriptingInterface(controllerScriptingInterface), |
| 57 | _avatarData(NULL), | 60 | _avatarData(NULL), |
| 58 | _wantMenuItems(wantMenuItems), | 61 | _wantMenuItems(wantMenuItems), |
| @@ -260,27 +263,55 @@ void ScriptEngine::run() { · 201 unmodified lines | |||
| 260 | } | 263 | } |
| 261 | 264 | ||
| 262 | if (_isAvatar && _avatarData) { | 265 | if (_isAvatar && _avatarData) { |
| 266 | |||
| 267 | const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * SAMPLE_RATE) / (1000 * 1000)) + 0.5); | ||
| 268 | const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t); | ||
| 269 | |||
| 263 | QByteArray avatarPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarData); | 270 | QByteArray avatarPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarData); |
| 264 | avatarPacket.append(_avatarData->toByteArray()); | 271 | avatarPacket.append(_avatarData->toByteArray()); |
| 265 | 272 | ||
| 266 | nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); | 273 | nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); |
| 267 | 274 | ||
| 268 | if (_avatarAudioBuffer && _numAvatarAudioBufferSamples > 0) { | 275 | if (_isListeningToAudioStream || _avatarSound) { |
| 269 | // if have an avatar audio stream then send it out to our audio-mixer | 276 | // if we have an avatar audio stream then send it out to our audio-mixer |
| 270 | |||
| 271 | bool silentFrame = true; | 277 | bool silentFrame = true; |
| 272 | 278 | ||
| 273 | // check if the all of the _numAvatarAudioBufferSamples to be sent are silence | 279 | int16_t numAvailableSamples = SCRIPT_AUDIO_BUFFER_SAMPLES; |
| 274 | for (int i = 0; i < _numAvatarAudioBufferSamples; ++i) { | 280 | const int16_t* nextSoundOutput = NULL; |
| 275 | if (_avatarAudioBuffer[i] != 0) { | 281 | |
| 276 | silentFrame = false; | 282 | if (_avatarSound) { |
| 277 | break; | 283 | |
| 284 | const QByteArray& soundByteArray = _avatarSound->getByteArray(); | ||
| 285 | nextSoundOutput = reinterpret_cast<const int16_t*>(soundByteArray.data() | ||
| 286 | + _numAvatarSoundSentBytes); | ||
| 287 | |||
| 288 | int numAvailableBytes = (soundByteArray.size() - _numAvatarSoundSentBytes) > SCRIPT_AUDIO_BUFFER_BYTES | ||
| 289 | ? SCRIPT_AUDIO_BUFFER_BYTES | ||
| 290 | : soundByteArray.size() - _numAvatarSoundSentBytes; | ||
| 291 | numAvailableSamples = numAvailableBytes / sizeof(int16_t); | ||
| 292 | |||
| 293 | |||
| 294 | // check if the all of the _numAvatarAudioBufferSamples to be sent are silence | ||
| 295 | for (int i = 0; i < numAvailableSamples; ++i) { | ||
| 296 | if (nextSoundOutput[i] != 0) { | ||
| 297 | silentFrame = false; | ||
| 298 | break; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | _numAvatarSoundSentBytes += numAvailableBytes; | ||
| 303 | if (_numAvatarSoundSentBytes == soundByteArray.size()) { | ||
| 304 | // we're done with this sound object - so set our pointer back to NULL | ||
| 305 | // and our sent bytes back to zero | ||
| 306 | _avatarSound = NULL; | ||
| 307 | _numAvatarSoundSentBytes = 0; | ||
| 278 | } | 308 | } |
| 279 | } | 309 | } |
| 280 | 310 | ||
| 281 | QByteArray audioPacket = byteArrayWithPopulatedHeader(silentFrame | 311 | QByteArray audioPacket = byteArrayWithPopulatedHeader(silentFrame |
| 282 | ? PacketTypeSilentAudioFrame | 312 | ? PacketTypeSilentAudioFrame |
| 283 | : PacketTypeMicrophoneAudioNoEcho); | 313 | : PacketTypeMicrophoneAudioNoEcho); |
| 314 | |||
| 284 | QDataStream packetStream(&audioPacket, QIODevice::Append); | 315 | QDataStream packetStream(&audioPacket, QIODevice::Append); |
| 285 | 316 | ||
| 286 | // use the orientation and position of this avatar for the source of this audio | 317 | // use the orientation and position of this avatar for the source of this audio |
| @@ -289,13 +320,17 @@ void ScriptEngine::run() { · 2 unmodified lines | |||
| 289 | packetStream.writeRawData(reinterpret_cast<const char*>(&headOrientation), sizeof(glm::quat)); | 320 | packetStream.writeRawData(reinterpret_cast<const char*>(&headOrientation), sizeof(glm::quat)); |
| 290 | 321 | ||
| 291 | if (silentFrame) { | 322 | if (silentFrame) { |
| 323 | if (!_isListeningToAudioStream) { | ||
| 324 | // if we have a silent frame and we're not listening then just send nothing and break out of here | ||
| 325 | break; | ||
| 326 | } | ||
| 327 | |||
| 292 | // write the number of silent samples so the audio-mixer can uphold timing | 328 | // write the number of silent samples so the audio-mixer can uphold timing |
| 293 | int16_t numSilentSamples = _numAvatarAudioBufferSamples; | 329 | packetStream.writeRawData(reinterpret_cast<const char*>(&SCRIPT_AUDIO_BUFFER_SAMPLES), sizeof(int16_t)); |
| 294 | packetStream.writeRawData(reinterpret_cast<const char*>(&numSilentSamples), sizeof(int16_t)); | 330 | } else if (nextSoundOutput) { |
| 295 | } else { | ||
| 296 | // write the raw audio data | 331 | // write the raw audio data |
| 297 | packetStream.writeRawData(reinterpret_cast<const char*>(_avatarAudioBuffer), | 332 | packetStream.writeRawData(reinterpret_cast<const char*>(nextSoundOutput), |
| 298 | _numAvatarAudioBufferSamples * sizeof(int16_t)); | 333 | numAvailableSamples * sizeof(int16_t)); |
| 299 | } | 334 | } |
| 300 | 335 | ||
| 301 | nodeList->broadcastToNodes(audioPacket, NodeSet() << NodeType::AudioMixer); | 336 | nodeList->broadcastToNodes(audioPacket, NodeSet() << NodeType::AudioMixer); |
| @@ -303,7 +338,7 @@ void ScriptEngine::run() { · 1 unmodified line | |||
| 303 | } | 338 | } |
| 304 | 339 | ||
| 305 | qint64 now = usecTimestampNow(); | 340 | qint64 now = usecTimestampNow(); |
| 306 | float deltaTime = (float)(now - lastUpdate)/(float)USECS_PER_SECOND; | 341 | float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND; |
| 307 | emit update(deltaTime); | 342 | emit update(deltaTime); |
| 308 | lastUpdate = now; | 343 | lastUpdate = now; |
| 309 | 344 | ||