2014-02-10 02:10:30 +01:00
|
|
|
/*************************************************************************/
|
|
|
|
/* audio_server.cpp */
|
|
|
|
/*************************************************************************/
|
|
|
|
/* This file is part of: */
|
|
|
|
/* GODOT ENGINE */
|
|
|
|
/* http://www.godotengine.org */
|
|
|
|
/*************************************************************************/
|
2017-01-01 22:01:57 +01:00
|
|
|
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
2014-02-10 02:10:30 +01:00
|
|
|
/* */
|
|
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
|
|
/* a copy of this software and associated documentation files (the */
|
|
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
|
|
/* the following conditions: */
|
|
|
|
/* */
|
|
|
|
/* The above copyright notice and this permission notice shall be */
|
|
|
|
/* included in all copies or substantial portions of the Software. */
|
|
|
|
/* */
|
|
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
|
|
/*************************************************************************/
|
|
|
|
#include "audio_server.h"
|
|
|
|
#include "globals.h"
|
|
|
|
|
|
|
|
void AudioMixer::audio_mixer_chunk_call(int p_frames) {
|
|
|
|
|
|
|
|
AudioServer::get_singleton()->audio_mixer_chunk_callback(p_frames);
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioMixer *AudioServer::EventStream::get_mixer() const {
|
|
|
|
|
|
|
|
return AudioServer::get_singleton()->get_mixer();
|
|
|
|
}
|
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
AudioServer *AudioServer::singleton = NULL;
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
AudioServer *AudioServer::get_singleton() {
|
|
|
|
|
|
|
|
return singleton;
|
|
|
|
}
|
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
void AudioServer::sample_set_signed_data(RID p_sample, const DVector<float> &p_buffer) {
|
2014-02-10 02:10:30 +01:00
|
|
|
|
2016-01-21 14:40:35 +01:00
|
|
|
SampleFormat format = sample_get_format(p_sample);
|
|
|
|
|
|
|
|
ERR_EXPLAIN("IMA ADPCM is not supported.");
|
2017-03-19 00:36:26 +01:00
|
|
|
ERR_FAIL_COND(format == SAMPLE_FORMAT_IMA_ADPCM);
|
2016-01-21 14:40:35 +01:00
|
|
|
|
2014-02-10 02:10:30 +01:00
|
|
|
int len = p_buffer.size();
|
2017-03-19 00:36:26 +01:00
|
|
|
ERR_FAIL_COND(len == 0);
|
2014-02-10 02:10:30 +01:00
|
|
|
|
|
|
|
DVector<uint8_t> data;
|
2016-01-21 14:40:35 +01:00
|
|
|
DVector<uint8_t>::Write w;
|
2014-02-10 02:10:30 +01:00
|
|
|
DVector<float>::Read r = p_buffer.read();
|
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
switch (format) {
|
2016-01-21 14:40:35 +01:00
|
|
|
case SAMPLE_FORMAT_PCM8: {
|
|
|
|
data.resize(len);
|
2017-03-19 00:36:26 +01:00
|
|
|
w = data.write();
|
2016-01-21 14:40:35 +01:00
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
int8_t *samples8 = (int8_t *)w.ptr();
|
2016-01-21 14:40:35 +01:00
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
for (int i = 0; i < len; i++) {
|
2016-01-21 14:40:35 +01:00
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
float sample = Math::floor(r[i] * (1 << 8));
|
|
|
|
if (sample < -128)
|
|
|
|
sample = -128;
|
|
|
|
else if (sample > 127)
|
|
|
|
sample = 127;
|
|
|
|
samples8[i] = sample;
|
2016-01-21 14:40:35 +01:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case SAMPLE_FORMAT_PCM16: {
|
2017-03-19 00:36:26 +01:00
|
|
|
data.resize(len * 2);
|
|
|
|
w = data.write();
|
2016-01-21 14:40:35 +01:00
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
int16_t *samples16 = (int16_t *)w.ptr();
|
2016-01-21 14:40:35 +01:00
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
for (int i = 0; i < len; i++) {
|
2016-01-21 14:40:35 +01:00
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
float sample = Math::floor(r[i] * (1 << 16));
|
|
|
|
if (sample < -32768)
|
|
|
|
sample = -32768;
|
|
|
|
else if (sample > 32767)
|
|
|
|
sample = 32767;
|
|
|
|
samples16[i] = sample;
|
2016-01-21 14:40:35 +01:00
|
|
|
}
|
|
|
|
} break;
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
w = DVector<uint8_t>::Write();
|
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
sample_set_data(p_sample, data);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AudioServer::_bind_methods() {
|
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
ObjectTypeDB::bind_method(_MD("sample_create", "format", "stereo", "length"), &AudioServer::sample_create);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_set_description", "sample", "description"), &AudioServer::sample_set_description);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_get_description", "sample"), &AudioServer::sample_get_description);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_get_format", "sample"), &AudioServer::sample_get_format);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_is_stereo", "sample"), &AudioServer::sample_is_stereo);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_get_length", "sample"), &AudioServer::sample_get_length);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_set_signed_data", "sample", "data"), &AudioServer::sample_set_signed_data);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_set_data", "sample", "data"), &AudioServer::sample_set_data);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_get_data", "sample"), &AudioServer::sample_get_data);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_set_mix_rate", "sample", "mix_rate"), &AudioServer::sample_set_mix_rate);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_get_mix_rate", "sample"), &AudioServer::sample_get_mix_rate);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_set_loop_format", "sample", "loop_format"), &AudioServer::sample_set_loop_format);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_get_loop_format", "sample"), &AudioServer::sample_get_loop_format);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_set_loop_begin", "sample", "pos"), &AudioServer::sample_set_loop_begin);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_get_loop_begin", "sample"), &AudioServer::sample_get_loop_begin);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_set_loop_end", "sample", "pos"), &AudioServer::sample_set_loop_end);
|
|
|
|
ObjectTypeDB::bind_method(_MD("sample_get_loop_end", "sample"), &AudioServer::sample_get_loop_end);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_create"), &AudioServer::voice_create);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_play", "voice", "sample"), &AudioServer::voice_play);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_set_volume", "voice", "volume"), &AudioServer::voice_set_volume);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_set_pan", "voice", "pan", "depth", "height"), &AudioServer::voice_set_pan, DEFVAL(0), DEFVAL(0));
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_set_filter", "voice", "type", "cutoff", "resonance", "gain"), &AudioServer::voice_set_filter, DEFVAL(0));
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_set_chorus", "voice", "chorus"), &AudioServer::voice_set_chorus);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_set_reverb", "voice", "room", "reverb"), &AudioServer::voice_set_reverb);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_set_mix_rate", "voice", "rate"), &AudioServer::voice_set_mix_rate);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_set_positional", "voice", "enabled"), &AudioServer::voice_set_positional);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_volume", "voice"), &AudioServer::voice_get_volume);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_pan", "voice"), &AudioServer::voice_get_pan);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_pan_height", "voice"), &AudioServer::voice_get_pan_height);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_pan_depth", "voice"), &AudioServer::voice_get_pan_depth);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_filter_type", "voice"), &AudioServer::voice_get_filter_type);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_filter_cutoff", "voice"), &AudioServer::voice_get_filter_cutoff);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_filter_resonance", "voice"), &AudioServer::voice_get_filter_resonance);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_chorus", "voice"), &AudioServer::voice_get_chorus);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_reverb_type", "voice"), &AudioServer::voice_get_reverb_type);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_reverb", "voice"), &AudioServer::voice_get_reverb);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_get_mix_rate", "voice"), &AudioServer::voice_get_mix_rate);
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_is_positional", "voice"), &AudioServer::voice_is_positional);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("voice_stop", "voice"), &AudioServer::voice_stop);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("free_rid", "rid"), &AudioServer::free);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("set_stream_global_volume_scale", "scale"), &AudioServer::set_stream_global_volume_scale);
|
|
|
|
ObjectTypeDB::bind_method(_MD("get_stream_global_volume_scale"), &AudioServer::get_stream_global_volume_scale);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("set_fx_global_volume_scale", "scale"), &AudioServer::set_fx_global_volume_scale);
|
|
|
|
ObjectTypeDB::bind_method(_MD("get_fx_global_volume_scale"), &AudioServer::get_fx_global_volume_scale);
|
|
|
|
|
|
|
|
ObjectTypeDB::bind_method(_MD("set_event_voice_global_volume_scale", "scale"), &AudioServer::set_event_voice_global_volume_scale);
|
|
|
|
ObjectTypeDB::bind_method(_MD("get_event_voice_global_volume_scale"), &AudioServer::get_event_voice_global_volume_scale);
|
|
|
|
|
|
|
|
BIND_CONSTANT(SAMPLE_FORMAT_PCM8);
|
|
|
|
BIND_CONSTANT(SAMPLE_FORMAT_PCM16);
|
|
|
|
BIND_CONSTANT(SAMPLE_FORMAT_IMA_ADPCM);
|
|
|
|
|
|
|
|
BIND_CONSTANT(SAMPLE_LOOP_NONE);
|
|
|
|
BIND_CONSTANT(SAMPLE_LOOP_FORWARD);
|
|
|
|
BIND_CONSTANT(SAMPLE_LOOP_PING_PONG);
|
|
|
|
|
|
|
|
BIND_CONSTANT(FILTER_NONE);
|
|
|
|
BIND_CONSTANT(FILTER_LOWPASS);
|
|
|
|
BIND_CONSTANT(FILTER_BANDPASS);
|
|
|
|
BIND_CONSTANT(FILTER_HIPASS);
|
|
|
|
BIND_CONSTANT(FILTER_NOTCH);
|
|
|
|
BIND_CONSTANT(FILTER_BANDLIMIT); ///< cutoff is LP resonace is HP
|
|
|
|
|
|
|
|
BIND_CONSTANT(REVERB_SMALL);
|
|
|
|
BIND_CONSTANT(REVERB_MEDIUM);
|
|
|
|
BIND_CONSTANT(REVERB_LARGE);
|
|
|
|
BIND_CONSTANT(REVERB_HALL);
|
|
|
|
|
|
|
|
GLOBAL_DEF("audio/stream_buffering_ms", 500);
|
|
|
|
GLOBAL_DEF("audio/video_delay_compensation_ms", 300);
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
AudioServer::AudioServer() {
|
|
|
|
|
2017-03-19 00:36:26 +01:00
|
|
|
singleton = this;
|
2014-02-10 02:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
AudioServer::~AudioServer() {
|
|
|
|
}
|