From 2d755adfc05f623a8fe33b132c93222bf7ac3278 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 9 Apr 2014 10:46:20 -0700 Subject: [PATCH] repairs to good code blown away by regex --- assignment-client/src/avatars/AvatarMixer.h | 3 + interface/src/Audio.cpp | 75 +++++++-- libraries/audio/src/Sound.cpp | 158 +++++++++++++++++- .../embedded-webserver/src/HTTPConnection.h | 4 + libraries/octree/src/CoverageMap.h | 2 + libraries/octree/src/CoverageMapV2.cpp | 36 +++- libraries/script-engine/src/Vec3.h | 2 + libraries/shared/src/CapsuleShape.cpp | 2 +- libraries/shared/src/CollisionInfo.cpp | 2 +- libraries/shared/src/CollisionInfo.h | 2 +- libraries/shared/src/ListShape.cpp | 2 +- libraries/shared/src/PacketSender.h | 2 + libraries/shared/src/ShapeCollider.cpp | 2 +- libraries/shared/src/ShapeCollider.h | 2 +- 14 files changed, 261 insertions(+), 33 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index af25a6f0e2..b9add245a6 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -5,6 +5,9 @@ // Created by Stephen Birarda on 9/5/13. // Copyright 2013 High Fidelity, Inc. // +// The avatar mixer receives head, hand and positional data from all connected +// nodes, and broadcasts that data back to them, every BROADCAST_INTERVAL ms. +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 719bfd8aa1..90797c7eef 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -18,6 +18,15 @@ #include #endif +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#endif + #include #include #include @@ -150,24 +159,56 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { #endif #ifdef WIN32 QString deviceName; - if (mode == QAudio::AudioInput) { - WAVEINCAPS wic; - // first use WAVE_MAPPER to get the default devices manufacturer ID - waveInGetDevCaps(WAVE_MAPPER, &wic, sizeof(wic)); - //Use the received manufacturer id to get the device's real name - waveInGetDevCaps(wic.wMid, &wic, sizeof(wic)); - qDebug() << "input device:" << wic.szPname; - deviceName = wic.szPname; + //Check for Windows Vista or higher, IMMDeviceEnumerator doesn't work below that. + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + const DWORD VISTA_MAJOR_VERSION = 6; + if (osvi.dwMajorVersion < VISTA_MAJOR_VERSION) {// lower then vista + if (mode == QAudio::AudioInput) { + WAVEINCAPS wic; + // first use WAVE_MAPPER to get the default devices manufacturer ID + waveInGetDevCaps(WAVE_MAPPER, &wic, sizeof(wic)); + //Use the received manufacturer id to get the device's real name + waveInGetDevCaps(wic.wMid, &wic, sizeof(wic)); + qDebug() << "input device:" << wic.szPname; + deviceName = wic.szPname; + } else { + WAVEOUTCAPS woc; + // first use WAVE_MAPPER to get the default devices manufacturer ID + waveOutGetDevCaps(WAVE_MAPPER, &woc, sizeof(woc)); + //Use the received manufacturer id to get the device's real name + waveOutGetDevCaps(woc.wMid, &woc, sizeof(woc)); + qDebug() << "output device:" << woc.szPname; + deviceName = woc.szPname; + } } else { - WAVEOUTCAPS woc; - // first use WAVE_MAPPER to get the default devices manufacturer ID - waveOutGetDevCaps(WAVE_MAPPER, &woc, sizeof(woc)); - //Use the received manufacturer id to get the device's real name - waveOutGetDevCaps(woc.wMid, &woc, sizeof(woc)); - qDebug() << "output device:" << woc.szPname; - deviceName = woc.szPname; + HRESULT hr = S_OK; + CoInitialize(NULL); + IMMDeviceEnumerator* pMMDeviceEnumerator = NULL; + CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pMMDeviceEnumerator); + IMMDevice* pEndpoint; + pMMDeviceEnumerator->GetDefaultAudioEndpoint(mode == QAudio::AudioOutput ? eRender : eCapture, eMultimedia, &pEndpoint); + IPropertyStore* pPropertyStore; + pEndpoint->OpenPropertyStore(STGM_READ, &pPropertyStore); + pEndpoint->Release(); + pEndpoint = NULL; + PROPVARIANT pv; + PropVariantInit(&pv); + hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv); + pPropertyStore->Release(); + pPropertyStore = NULL; + //QAudio devices seems to only take the 31 first characters of the Friendly Device Name. + const DWORD QT_WIN_MAX_AUDIO_DEVICENAME_LEN = 31; + deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal).left(QT_WIN_MAX_AUDIO_DEVICENAME_LEN); + qDebug() << (mode == QAudio::AudioOutput ? "output" : "input") << " device:" << deviceName; + PropVariantClear(&pv); + pMMDeviceEnumerator->Release(); + pMMDeviceEnumerator = NULL; + CoUninitialize(); } - qDebug() << "DEBUG [" << deviceName << "] [" << getNamedAudioDeviceForMode(mode, deviceName).deviceName() << "]"; + qDebug() << "DEBUG [" << deviceName << "] [" << getNamedAudioDeviceForMode(mode, deviceName).deviceName() << "]"; return getNamedAudioDeviceForMode(mode, deviceName); #endif @@ -988,4 +1029,4 @@ float Audio::calculateDeviceToNetworkInputRatio(int numBytes) { int Audio::calculateNumberOfFrameSamples(int numBytes) { int frameSamples = (int)(numBytes * CALLBACK_ACCELERATOR_RATIO + 0.5f) / sizeof(int16_t); return frameSamples; -} +} \ No newline at end of file diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 4e657f3302..420576ece9 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -9,20 +9,162 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -struct chunk +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "AudioRingBuffer.h" +#include "Sound.h" + +// procedural audio version of Sound +Sound::Sound(float volume, float frequency, float duration, float decay, QObject* parent) : + QObject(parent) { + static char monoAudioData[MAX_PACKET_SIZE]; + static int16_t* monoAudioSamples = (int16_t*)(monoAudioData); + + float t; + const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float)SAMPLE_RATE * 1000.0; + const float MAX_VOLUME = 32000.f; + const float MAX_DURATION = 2.f; + const float MIN_AUDIBLE_VOLUME = 0.001f; + const float NOISE_MAGNITUDE = 0.02f; + const int MAX_SAMPLE_VALUE = std::numeric_limits::max(); + const int MIN_SAMPLE_VALUE = std::numeric_limits::min(); + int numSamples = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; // we add sounds in chunks of this many samples + + int chunkStartingSample = 0; + float waveFrequency = (frequency / SAMPLE_RATE) * TWO_PI; + while (volume > 0.f) { + for (int i = 0; i < numSamples; i++) { + t = (float)chunkStartingSample + (float)i; + float sample = sinf(t * waveFrequency); + sample += ((randFloat() - 0.5f) * NOISE_MAGNITUDE); + sample *= volume * MAX_VOLUME; + + monoAudioSamples[i] = glm::clamp((int)sample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); + volume *= (1.f - decay); + } + // add the monoAudioSamples to our actual output Byte Array + _byteArray.append(monoAudioData, numSamples * sizeof(int16_t)); + chunkStartingSample += numSamples; + duration = glm::clamp(duration - (AUDIO_CALLBACK_MSECS / 1000.f), 0.f, MAX_DURATION); + //qDebug() << "decaying... _duration=" << _duration; + if (duration == 0.f || (volume < MIN_AUDIBLE_VOLUME)) { + volume = 0.f; + } + } +} + +Sound::Sound(const QUrl& sampleURL, QObject* parent) : + QObject(parent) +{ + // assume we have a QApplication or QCoreApplication instance and use the + // QNetworkAccess manager to grab the raw audio file at the given URL + + QNetworkAccessManager *manager = new QNetworkAccessManager(this); + connect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(replyFinished(QNetworkReply*))); + + qDebug() << "Requesting audio file" << sampleURL.toDisplayString(); + manager->get(QNetworkRequest(sampleURL)); +} + +void Sound::replyFinished(QNetworkReply* reply) { + + // replace our byte array with the downloaded data + QByteArray rawAudioByteArray = reply->readAll(); + + // foreach(QByteArray b, reply->rawHeaderList()) + // qDebug() << b.constData() << ": " << reply->rawHeader(b).constData(); + + if (reply->hasRawHeader("Content-Type")) { + + QByteArray headerContentType = reply->rawHeader("Content-Type"); + + // WAV audio file encountered + if (headerContentType == "audio/x-wav" + || headerContentType == "audio/wav" + || headerContentType == "audio/wave") { + + QByteArray outputAudioByteArray; + + interpretAsWav(rawAudioByteArray, outputAudioByteArray); + downSample(outputAudioByteArray); + } else { + // Process as RAW file + downSample(rawAudioByteArray); + } + } else { + qDebug() << "Network reply without 'Content-Type'."; + } +} + +void Sound::downSample(const QByteArray& rawAudioByteArray) { + + // assume that this was a RAW file and is now an array of samples that are + // signed, 16-bit, 48Khz, mono + + // we want to convert it to the format that the audio-mixer wants + // which is signed, 16-bit, 24Khz, mono + + _byteArray.resize(rawAudioByteArray.size() / 2); + + int numSourceSamples = rawAudioByteArray.size() / sizeof(int16_t); + 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); + } + } +} + +// +// Format description from https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ +// +// The header for a WAV file looks like this: +// Positions Sample Value Description +// 00-03 "RIFF" Marks the file as a riff file. Characters are each 1 byte long. +// 04-07 File size (int) Size of the overall file - 8 bytes, in bytes (32-bit integer). +// 08-11 "WAVE" File Type Header. For our purposes, it always equals "WAVE". +// 12-15 "fmt " Format chunk marker. +// 16-19 16 Length of format data as listed above +// 20-21 1 Type of format: (1=PCM, 257=Mu-Law, 258=A-Law, 259=ADPCM) - 2 byte integer +// 22-23 2 Number of Channels - 2 byte integer +// 24-27 44100 Sample Rate - 32 byte integer. Sample Rate = Number of Samples per second, or Hertz. +// 28-31 176400 (Sample Rate * BitsPerSample * Channels) / 8. +// 32-33 4 (BitsPerSample * Channels) / 8 - 8 bit mono2 - 8 bit stereo/16 bit mono4 - 16 bit stereo +// 34-35 16 Bits per sample +// 36-39 "data" Chunk header. Marks the beginning of the data section. +// 40-43 File size (int) Size of the data section. +// 44-?? Actual sound data +// Sample values are given above for a 16-bit stereo source. +// + +struct chunk { char id[4]; quint32 size; }; -struct RIFFHeader -{ +struct RIFFHeader { chunk descriptor; // "RIFF" char type[4]; // "WAVE" }; -struct WAVEHeader -{ +struct WAVEHeader { chunk descriptor; quint16 audioFormat; // Format type: 1=PCM, 257=Mu-Law, 258=A-Law, 259=ADPCM quint16 numChannels; // Number of channels: 1=mono, 2=stereo @@ -32,13 +174,11 @@ struct WAVEHeader quint16 bitsPerSample; }; -struct DATAHeader -{ +struct DATAHeader { chunk descriptor; }; -struct CombinedHeader -{ +struct CombinedHeader { RIFFHeader riff; WAVEHeader wave; }; diff --git a/libraries/embedded-webserver/src/HTTPConnection.h b/libraries/embedded-webserver/src/HTTPConnection.h index 2da4027334..7eb0c6108d 100644 --- a/libraries/embedded-webserver/src/HTTPConnection.h +++ b/libraries/embedded-webserver/src/HTTPConnection.h @@ -5,6 +5,10 @@ // Created by Stephen Birarda on 1/16/14. // Copyright 2014 High Fidelity, Inc. // +// Heavily based on Andrzej Kapolka's original HTTPConnection class +// found from another one of his projects. +// https://github.com/ey6es/witgap/tree/master/src/cpp/server/http +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // diff --git a/libraries/octree/src/CoverageMap.h b/libraries/octree/src/CoverageMap.h index d1fada141e..e06696ff66 100644 --- a/libraries/octree/src/CoverageMap.h +++ b/libraries/octree/src/CoverageMap.h @@ -5,6 +5,8 @@ // Created by Brad Hefta-Gaub on 06/11/13. // Copyright 2013 High Fidelity, Inc. // +// 2D CoverageMap Quad tree for storage of OctreeProjectedPolygons +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // diff --git a/libraries/octree/src/CoverageMapV2.cpp b/libraries/octree/src/CoverageMapV2.cpp index 6535066eed..1ad800ab6b 100644 --- a/libraries/octree/src/CoverageMapV2.cpp +++ b/libraries/octree/src/CoverageMapV2.cpp @@ -9,6 +9,40 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include + +#include + +#include + +#include "CoverageMapV2.h" + +int CoverageMapV2::_mapCount = 0; +int CoverageMapV2::_checkMapRootCalls = 0; +int CoverageMapV2::_notAllInView = 0; +bool CoverageMapV2::wantDebugging = false; + +const BoundingBox CoverageMapV2::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.f,-1.f), glm::vec2(2.f,2.f)); + +// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space. +// +// (0,0) (windowWidth, 0) +// -1,1 1,1 +// +-----------------------+ +// | | | +// | | | +// | -1,0 | | +// |-----------+-----------| +// | 0,0 | +// | | | +// | | | +// | | | +// +-----------------------+ +// -1,-1 1,-1 +// (0,windowHeight) (windowWidth,windowHeight) +// + // Choosing a minimum sized polygon. Since we know a typical window is approximately 1500 pixels wide // then a pixel on our screen will be ~ 2.0/1500 or 0.0013 "units" wide, similarly pixels are typically // about that tall as well. If we say that polygons should be at least 10x10 pixels to be considered "big enough" @@ -214,4 +248,4 @@ void CoverageMapV2::recurseMap(const OctreeProjectedPolygon* polygon, bool store } // normal exit case... return... -} +} \ No newline at end of file diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index 9e962ca4fd..7d420adca3 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -5,6 +5,8 @@ // Created by Brad Hefta-Gaub on 1/29/14. // Copyright 2014 High Fidelity, Inc. // +// Scriptable Vec3 class library. +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // diff --git a/libraries/shared/src/CapsuleShape.cpp b/libraries/shared/src/CapsuleShape.cpp index 15586c4938..be3a165082 100644 --- a/libraries/shared/src/CapsuleShape.cpp +++ b/libraries/shared/src/CapsuleShape.cpp @@ -2,7 +2,7 @@ // CapsuleShape.cpp // libraries/shared/src // -// Created by Andrew Meadows on 2014. +// Created by Andrew Meadows on 02/20/2014. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/shared/src/CollisionInfo.cpp b/libraries/shared/src/CollisionInfo.cpp index bf986705f5..5a4188a1ef 100644 --- a/libraries/shared/src/CollisionInfo.cpp +++ b/libraries/shared/src/CollisionInfo.cpp @@ -2,7 +2,7 @@ // CollisionInfo.cpp // libraries/shared/src // -// Created by Andrew Meadows on 2014. +// Created by Andrew Meadows on 02/14/2014. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index fb7450671b..b8c4aa6523 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -2,7 +2,7 @@ // CollisionInfo.h // libraries/shared/src // -// Created by Andrew Meadows on 2014. +// Created by Andrew Meadows on 02/14/2014. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/shared/src/ListShape.cpp b/libraries/shared/src/ListShape.cpp index 26d1c7fea5..dcea97826e 100644 --- a/libraries/shared/src/ListShape.cpp +++ b/libraries/shared/src/ListShape.cpp @@ -2,7 +2,7 @@ // ListShape.cpp // libraries/shared/src // -// Created by Andrew Meadows on 2014. +// Created by Andrew Meadows on 02/20/2014. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/shared/src/PacketSender.h b/libraries/shared/src/PacketSender.h index 01023f8ca3..d517da6d17 100644 --- a/libraries/shared/src/PacketSender.h +++ b/libraries/shared/src/PacketSender.h @@ -5,6 +5,8 @@ // Created by Brad Hefta-Gaub on 8/12/13. // Copyright 2013 High Fidelity, Inc. // +// Threaded or non-threaded packet sender. +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 2462663405..b13775dfa8 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -2,7 +2,7 @@ // ShapeCollider.cpp // libraries/shared/src // -// Created by Andrew Meadows on 2014. +// Created by Andrew Meadows on 02/20/2014. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/shared/src/ShapeCollider.h b/libraries/shared/src/ShapeCollider.h index 7154a158d0..c1018bec42 100644 --- a/libraries/shared/src/ShapeCollider.h +++ b/libraries/shared/src/ShapeCollider.h @@ -2,7 +2,7 @@ // ShapeCollider.h // libraries/shared/src // -// Created by Andrew Meadows on 2014. +// Created by Andrew Meadows on 02/20/2014. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0.