diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 2d4074f125..d15852e11f 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -18,8 +18,6 @@ #include "AudioInjector.h" -int abstractAudioPointerMeta = qRegisterMetaType("AbstractAudioInterface*"); - AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions) : _sound(sound), _options(injectorOptions) diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index d09a4eef86..1fe2c19922 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -25,4 +25,26 @@ void AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater())); injectorThread->start(); -} \ No newline at end of file +} + +void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay, + const AudioInjectorOptions* injectorOptions) { + + Sound* sound = new Sound(volume, frequency, duration, decay); + AudioInjector* injector = new AudioInjector(sound, *injectorOptions); + sound->setParent(injector); + + QThread* injectorThread = new QThread(); + + injector->moveToThread(injectorThread); + + // start injecting when the injector thread starts + connect(injectorThread, SIGNAL(started()), injector, SLOT(injectAudio())); + + // connect the right slots and signals so that the AudioInjector is killed once the injection is complete + connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater())); + connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit())); + connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater())); + + injectorThread->start(); +} diff --git a/libraries/audio/src/AudioScriptingInterface.h b/libraries/audio/src/AudioScriptingInterface.h index bded426cbd..f758923513 100644 --- a/libraries/audio/src/AudioScriptingInterface.h +++ b/libraries/audio/src/AudioScriptingInterface.h @@ -18,6 +18,8 @@ class AudioScriptingInterface : public QObject { Q_OBJECT public slots: static void playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL); + static void startDrumSound(float volume, float frequency, float duration, float decay, + const AudioInjectorOptions* injectorOptions = NULL); }; #endif /* defined(__hifi__AudioScriptingInterface__) */ diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 07eec031b5..83b4d8a79c 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -9,6 +9,8 @@ #include +#include + #include #include #include @@ -16,8 +18,51 @@ #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) * PI_TIMES_TWO; + 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) { diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index c17bae2582..7956343d46 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -17,7 +17,8 @@ class QNetworkReply; class Sound : public QObject { Q_OBJECT public: - Sound(const QUrl& sampleURL, QObject* parent = 0); + Sound(const QUrl& sampleURL, QObject* parent = NULL); + Sound(float volume, float frequency, float duration, float decay, QObject* parent = NULL); const QByteArray& getByteArray() { return _byteArray; }