From 7dc07a1c51cdc2f51899d30376cb51d1078928b4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 25 Sep 2014 17:54:11 -0700 Subject: [PATCH 1/8] Compute correct number of bytes to send when stereo --- libraries/audio/src/AudioInjector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 17b082f07a..fe97594803 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -104,7 +104,7 @@ void AudioInjector::injectAudio() { quint16 outgoingInjectedAudioSequenceNumber = 0; while (currentSendPosition < soundByteArray.size() && !_shouldStop) { - int bytesToCopy = std::min(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, + int bytesToCopy = std::min(((_options.isStereo()) ? 2 : 1) * NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, soundByteArray.size() - currentSendPosition); memcpy(injectAudioPacket.data() + positionOptionOffset, &_options.getPosition(), From 7f4ece2be131c46d13f977b2d23b3634e0dd4009 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 25 Sep 2014 17:54:53 -0700 Subject: [PATCH 2/8] Resize ringbuffer of injected stereo stream --- libraries/audio/src/InjectedAudioStream.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/audio/src/InjectedAudioStream.cpp b/libraries/audio/src/InjectedAudioStream.cpp index 84d33c53e3..d1bbc71898 100644 --- a/libraries/audio/src/InjectedAudioStream.cpp +++ b/libraries/audio/src/InjectedAudioStream.cpp @@ -38,6 +38,7 @@ int InjectedAudioStream::parseStreamProperties(PacketType type, const QByteArray packetStream.skipRawData(NUM_BYTES_RFC4122_UUID); packetStream >> _isStereo; + _ringBuffer.resizeForFrameSize(isStereo() ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); // pull the loopback flag and set our boolean uchar shouldLoopback; From 453869c8e99686f8723c38e80f1ff70a2f5467c6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 25 Sep 2014 18:11:48 -0700 Subject: [PATCH 3/8] Stereo flag + specific resample in Sound class --- .../audio/src/AudioScriptingInterface.cpp | 3 +++ libraries/audio/src/Sound.cpp | 25 +++++++++++++------ libraries/audio/src/Sound.h | 4 ++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index fa0d3a9565..43c7d35c1d 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -13,6 +13,9 @@ AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions* injectorOptions) { + if (sound->isStereo()) { + const_cast(injectorOptions)->setIsStereo(true); + } AudioInjector* injector = new AudioInjector(sound, *injectorOptions); QThread* injectorThread = new QThread(); diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 9edb04aa2c..3ac433ca31 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -31,7 +31,8 @@ // procedural audio version of Sound Sound::Sound(float volume, float frequency, float duration, float decay, QObject* parent) : - QObject(parent) + QObject(parent), + _isStereo(false) { static char monoAudioData[MAX_PACKET_SIZE]; static int16_t* monoAudioSamples = (int16_t*)(monoAudioData); @@ -69,8 +70,9 @@ Sound::Sound(float volume, float frequency, float duration, float decay, QObject } } -Sound::Sound(const QUrl& sampleURL, QObject* parent) : +Sound::Sound(const QUrl& sampleURL, bool isStereo, QObject* parent) : QObject(parent), + _isStereo(isStereo), _hasDownloaded(false) { // assume we have a QApplication or QCoreApplication instance and use the @@ -88,6 +90,7 @@ Sound::Sound(const QUrl& sampleURL, QObject* parent) : Sound::Sound(const QByteArray byteArray, QObject* parent) : QObject(parent), _byteArray(byteArray), + _isStereo(false), _hasDownloaded(true) { } @@ -149,11 +152,19 @@ void Sound::downSample(const QByteArray& rawAudioByteArray) { int16_t* sourceSamples = (int16_t*) rawAudioByteArray.data(); int16_t* destinationSamples = (int16_t*) _byteArray.data(); - for (int i = 1; i < numSourceSamples; i += 2) { - if (i + 1 >= numSourceSamples) { - destinationSamples[(i - 1) / 2] = (sourceSamples[i - 1] / 2) + (sourceSamples[i] / 2); - } else { - destinationSamples[(i - 1) / 2] = (sourceSamples[i - 1] / 4) + (sourceSamples[i] / 2) + (sourceSamples[i + 1] / 4); + + if (_isStereo) { + for (int i = 0; i < numSourceSamples; i += 4) { + destinationSamples[i / 2] = (sourceSamples[i] / 2) + (sourceSamples[i + 2] / 2); + destinationSamples[(i / 2) + 1] = (sourceSamples[i + 1] / 2) + (sourceSamples[i + 3] / 2); + } + } else { + for (int i = 1; i < numSourceSamples; i += 2) { + if (i + 1 >= numSourceSamples) { + destinationSamples[(i - 1) / 2] = (sourceSamples[i - 1] / 2) + (sourceSamples[i] / 2); + } else { + destinationSamples[(i - 1) / 2] = (sourceSamples[i - 1] / 4) + (sourceSamples[i] / 2) + (sourceSamples[i + 1] / 4); + } } } } diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index fa2dd97903..b8fdc6b458 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -20,17 +20,19 @@ class Sound : public QObject { Q_PROPERTY(bool downloaded READ hasDownloaded) public: - Sound(const QUrl& sampleURL, QObject* parent = NULL); + Sound(const QUrl& sampleURL, bool isStereo = false, QObject* parent = NULL); Sound(float volume, float frequency, float duration, float decay, QObject* parent = NULL); Sound(const QByteArray byteArray, QObject* parent = NULL); void append(const QByteArray byteArray); + bool isStereo() const { return _isStereo; } bool hasDownloaded() const { return _hasDownloaded; } const QByteArray& getByteArray() { return _byteArray; } private: QByteArray _byteArray; + bool _isStereo; bool _hasDownloaded; void trimFrames(); From 11a5358a6eea8fbec449bed03fc5bb6a982a89da Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 25 Sep 2014 18:12:30 -0700 Subject: [PATCH 4/8] Adapted radio.js to new funciton calls --- examples/radio.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/radio.js b/examples/radio.js index 83e81e7e02..c7a6fdcc97 100644 --- a/examples/radio.js +++ b/examples/radio.js @@ -10,7 +10,7 @@ // -var modelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/entities/radio/Speakers2Finished.fbx"; +var modelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/entities/radio/Speakers2_DeletedPlanes.fbx"; var soundURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/FamilyStereo.raw"; var AudioRotationOffset = Quat.fromPitchYawRollDegrees(0, -90, 0); @@ -20,7 +20,7 @@ audioOptions.loop = true; audioOptions.isStereo = true; var injector = null; -var sound = new Sound(soundURL); +var sound = new Sound(soundURL, audioOptions.isStereo); var entity = null; var properties = null; @@ -38,7 +38,7 @@ function update() { type: "Model", position: position, rotation: rotation, - dimensions: { x: 0.5, y: 0.5, z: 0.5 }, + dimensions: { x: 0.2, y: 0.2, z: 0.2 }, modelURL: modelURL }); properties = Entities.getEntityProperties(entity); From 3baa992bc3b17c1615f38a9e855d0fb2a11d578c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 25 Sep 2014 18:56:37 -0700 Subject: [PATCH 5/8] Fixed radio model --- examples/radio.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/radio.js b/examples/radio.js index c7a6fdcc97..575d9d70c8 100644 --- a/examples/radio.js +++ b/examples/radio.js @@ -10,7 +10,7 @@ // -var modelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/entities/radio/Speakers2_DeletedPlanes.fbx"; +var modelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/entities/radio/Speakers.fbx"; var soundURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/FamilyStereo.raw"; var AudioRotationOffset = Quat.fromPitchYawRollDegrees(0, -90, 0); @@ -31,14 +31,16 @@ function update() { print("Sound file downloaded"); var position = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, - { x: 0, y: 0.3, z: -1 })); + { x: 0, y: -0.3, z: -2 })); var rotation = Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollDegrees(0, -90, 0)); entity = Entities.addEntity({ type: "Model", position: position, rotation: rotation, - dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + dimensions: { x: 0.391, + y: 1.000, + z: 1.701 }, modelURL: modelURL }); properties = Entities.getEntityProperties(entity); From f50b42fd16eb68be60a8e0a55fa306a4cf96df90 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 25 Sep 2014 19:15:16 -0700 Subject: [PATCH 6/8] Read new Sound() arg --- libraries/script-engine/src/ScriptEngine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 545e4709f9..47e0ced6bf 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -48,7 +48,8 @@ EntityScriptingInterface ScriptEngine::_entityScriptingInterface; static QScriptValue soundConstructor(QScriptContext* context, QScriptEngine* engine) { QUrl soundURL = QUrl(context->argument(0).toString()); - QScriptValue soundScriptValue = engine->newQObject(new Sound(soundURL), QScriptEngine::ScriptOwnership); + bool isStereo = context->argument(1).toBool(); + QScriptValue soundScriptValue = engine->newQObject(new Sound(soundURL, isStereo), QScriptEngine::ScriptOwnership); return soundScriptValue; } From 72f5b9b77b752d8abf8d6c8d8d6a55a350183128 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 25 Sep 2014 19:19:03 -0700 Subject: [PATCH 7/8] code cleanup --- libraries/audio/src/AudioInjector.cpp | 12 ++++++++---- libraries/audio/src/InjectedAudioStream.cpp | 7 +++++-- libraries/audio/src/Sound.cpp | 6 ++++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index fe97594803..4facc03e1e 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -77,11 +77,13 @@ void AudioInjector::injectAudio() { // pack the position for injected audio int positionOptionOffset = injectAudioPacket.size(); - packetStream.writeRawData(reinterpret_cast(&_options.getPosition()), sizeof(_options.getPosition())); + packetStream.writeRawData(reinterpret_cast(&_options.getPosition()), + sizeof(_options.getPosition())); // pack our orientation for injected audio int orientationOptionOffset = injectAudioPacket.size(); - packetStream.writeRawData(reinterpret_cast(&_options.getOrientation()), sizeof(_options.getOrientation())); + packetStream.writeRawData(reinterpret_cast(&_options.getOrientation()), + sizeof(_options.getOrientation())); // pack zero for radius float radius = 0; @@ -117,10 +119,12 @@ void AudioInjector::injectAudio() { injectAudioPacket.resize(numPreAudioDataBytes + bytesToCopy); // pack the sequence number - memcpy(injectAudioPacket.data() + numPreSequenceNumberBytes, &outgoingInjectedAudioSequenceNumber, sizeof(quint16)); + memcpy(injectAudioPacket.data() + numPreSequenceNumberBytes, + &outgoingInjectedAudioSequenceNumber, sizeof(quint16)); // copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet - memcpy(injectAudioPacket.data() + numPreAudioDataBytes, soundByteArray.data() + currentSendPosition, bytesToCopy); + memcpy(injectAudioPacket.data() + numPreAudioDataBytes, + soundByteArray.data() + currentSendPosition, bytesToCopy); // grab our audio mixer from the NodeList, if it exists NodeList* nodeList = NodeList::getInstance(); diff --git a/libraries/audio/src/InjectedAudioStream.cpp b/libraries/audio/src/InjectedAudioStream.cpp index d1bbc71898..762a40003a 100644 --- a/libraries/audio/src/InjectedAudioStream.cpp +++ b/libraries/audio/src/InjectedAudioStream.cpp @@ -30,7 +30,9 @@ InjectedAudioStream::InjectedAudioStream(const QUuid& streamIdentifier, const In const uchar MAX_INJECTOR_VOLUME = 255; -int InjectedAudioStream::parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) { +int InjectedAudioStream::parseStreamProperties(PacketType type, + const QByteArray& packetAfterSeqNum, + int& numAudioSamples) { // setup a data stream to read from this packet QDataStream packetStream(packetAfterSeqNum); @@ -38,7 +40,8 @@ int InjectedAudioStream::parseStreamProperties(PacketType type, const QByteArray packetStream.skipRawData(NUM_BYTES_RFC4122_UUID); packetStream >> _isStereo; - _ringBuffer.resizeForFrameSize(isStereo() ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _ringBuffer.resizeForFrameSize(isStereo() ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : + NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); // pull the loopback flag and set our boolean uchar shouldLoopback; diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 3ac433ca31..6fa002a664 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -84,7 +84,8 @@ Sound::Sound(const QUrl& sampleURL, bool isStereo, QObject* parent) : QNetworkReply* soundDownload = networkAccessManager.get(QNetworkRequest(sampleURL)); connect(soundDownload, &QNetworkReply::finished, this, &Sound::replyFinished); - connect(soundDownload, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError))); + connect(soundDownload, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(replyError(QNetworkReply::NetworkError))); } Sound::Sound(const QByteArray byteArray, QObject* parent) : @@ -163,7 +164,8 @@ void Sound::downSample(const QByteArray& rawAudioByteArray) { if (i + 1 >= numSourceSamples) { destinationSamples[(i - 1) / 2] = (sourceSamples[i - 1] / 2) + (sourceSamples[i] / 2); } else { - destinationSamples[(i - 1) / 2] = (sourceSamples[i - 1] / 4) + (sourceSamples[i] / 2) + (sourceSamples[i + 1] / 4); + destinationSamples[(i - 1) / 2] = (sourceSamples[i - 1] / 4) + (sourceSamples[i] / 2) + + (sourceSamples[i + 1] / 4); } } } From 83ad0e4eb0217d31e132f495111dd2a31a0b1f27 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 26 Sep 2014 11:14:27 -0700 Subject: [PATCH 8/8] Fix mono injection --- libraries/audio/src/InjectedAudioStream.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/InjectedAudioStream.cpp b/libraries/audio/src/InjectedAudioStream.cpp index 762a40003a..0cc13eae05 100644 --- a/libraries/audio/src/InjectedAudioStream.cpp +++ b/libraries/audio/src/InjectedAudioStream.cpp @@ -40,8 +40,9 @@ int InjectedAudioStream::parseStreamProperties(PacketType type, packetStream.skipRawData(NUM_BYTES_RFC4122_UUID); packetStream >> _isStereo; - _ringBuffer.resizeForFrameSize(isStereo() ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : - NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + if (isStereo()) { + _ringBuffer.resizeForFrameSize(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO); + } // pull the loopback flag and set our boolean uchar shouldLoopback;