mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 00:56:48 +02:00
add support for Audio.startDrumSound() to allow drum sound procedural audio in JS
This commit is contained in:
parent
011bc4f6cb
commit
59eefa314c
5 changed files with 72 additions and 4 deletions
|
@ -18,8 +18,6 @@
|
|||
|
||||
#include "AudioInjector.h"
|
||||
|
||||
int abstractAudioPointerMeta = qRegisterMetaType<AbstractAudioInterface*>("AbstractAudioInterface*");
|
||||
|
||||
AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions) :
|
||||
_sound(sound),
|
||||
_options(injectorOptions)
|
||||
|
|
|
@ -25,4 +25,26 @@ void AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions
|
|||
connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater()));
|
||||
|
||||
injectorThread->start();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
|
@ -16,8 +18,51 @@
|
|||
#include <QtNetwork/QNetworkReply>
|
||||
#include <qendian.h>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#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<int16_t>::max();
|
||||
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::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)
|
||||
{
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
Loading…
Reference in a new issue