Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for DSP buffer size #96

Merged
merged 6 commits into from
Nov 15, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,17 @@ Fmod.set_driver(id)
var id = Fmod.get_driver()
```

### Reducing audio playback latency

You may encounter that the audio playback has some latency. This may be caused by the DSP buffer size. You can change the value **before** initialisation to adjust it:
```gdscript
Fmod.set_dsp_buffer_size(512, 4)
# retrieve the buffer length
Fmod.get_dsp_buffer_length()
# retrieve the number of buffers
Fmod.get_dsp_num_buffers()
```

### Profiling & querying performance data

`getPerformanceData` returns an object which contains current performance stats for CPU, Memory and File Streaming usage of both FMOD Studio and the Core System.
Expand Down
9 changes: 9 additions & 0 deletions demo/addons/fmod/Fmod.gd
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,15 @@ func get_global_parameter_desc_count() -> int:
func get_global_parameter_desc_list() -> Array:
return godot_fmod.get_global_parameter_desc_list()

func set_dsp_buffer_size(bufferLength: int, numberOfBuffers: int) -> void:
godot_fmod.set_dsp_buffer_size(bufferLength, numberOfBuffers)

func get_dsp_buffer_length() -> int:
return godot_fmod.get_dsp_buffer_length()

func set_dsp_num_buffers() -> int:
return godot_fmod.get_dsp_num_buffers()

###############
###LISTENERS###
###############
Expand Down
21 changes: 21 additions & 0 deletions src/godot_fmod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ void Fmod::_register_methods() {
register_method("get_global_parameter_desc_by_id", &Fmod::getGlobalParameterDescByID);
register_method("get_global_parameter_desc_count", &Fmod::getGlobalParameterDescCount);
register_method("get_global_parameter_desc_list", &Fmod::getGlobalParameterDescList);
register_method("set_dsp_buffer_size", &Fmod::setSystemDSPBufferSize);
register_method("get_dsp_buffer_length", &Fmod::getSystemDSPBufferLength);
register_method("get_dsp_num_buffers", &Fmod::getSystemDSPNumBuffers);
register_method("_process", &Fmod::_process);

register_signal<Fmod>("timeline_beat", "params", GODOT_VARIANT_TYPE_DICTIONARY);
Expand Down Expand Up @@ -1313,6 +1316,24 @@ Node * Fmod::getObjectAttachedToInstance(uint64_t instanceId) {
return node;
}

void Fmod::setSystemDSPBufferSize(unsigned int bufferlength, int numbuffers) {
if (bufferlength > 0 && numbuffers > 0 && ERROR_CHECK(coreSystem->setDSPBufferSize(bufferlength, numbuffers))) {
GODOT_LOG(0, "FMOD Sound System: Successfully set DSP buffer size")
} else {
GODOT_LOG(2, "FMOD Sound System: Failed to set DSP buffer size :|")
}
}

int Fmod::getSystemDSPBufferLength() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we should not return an array containing lenght and num instead of having two getter that does same things but only return partial information ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a long think about this: from a usability perspective, it will be quite confusing to Godot users to suddenly get an Array as return type as it is not very explicit what these values actually mean. On the contrary, it is not performant to request both values separately, however, the FMOD C++ binding forces us to pass in both by reference always.

If you are happy I can make that change to return an Array, however, it may get confusing to users what these values mean.

Copy link
Member

@CedNaru CedNaru Nov 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm more on the side of having 2 getters. It's not like we need performance for that, it's just a simple API call. So it's better to favor usability.
We can also gave both: 2 separate getter returning one value, and one getter getSystemDSPInfo that returns an array or dictionnary with string key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed!

ERROR_CHECK(coreSystem->getDSPBufferSize(&this->bufferlength, &this->numbuffers));
return this->bufferlength;
}

int Fmod::getSystemDSPNumBuffers() {
ERROR_CHECK(coreSystem->getDSPBufferSize(&this->bufferlength, &this->numbuffers));
return this->numbuffers;
}

void Fmod::pauseAllEvents(const bool pause) {
for (int i = 0; i < events.size(); i++) {
auto eventInstance = events.get(i);
Expand Down
5 changes: 5 additions & 0 deletions src/godot_fmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ namespace godot {
int actualListenerNumber = 0;
Listener listeners[FMOD_MAX_LISTENERS];
bool listenerWarning = true;
unsigned int bufferlength = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is no value in storing those variables inside the class.

In the 2 getters, you can just create a local variable, pass its pointers to FMOD, then return it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

int numbuffers = 0;

Vector<LoadingBank *> loadingBanks;
Map<String, FMOD::Studio::Bank *> banks;
Expand Down Expand Up @@ -183,6 +185,9 @@ namespace godot {
void setListenerLock(int index, bool isLocked);
bool getListenerLock(int index);
Node* getObjectAttachedToListener(int index);
void setSystemDSPBufferSize(unsigned int bufferlength, int numbuffers);
int getSystemDSPBufferLength();
int getSystemDSPNumBuffers();

String loadBank(String pathToBank, unsigned int flag);
void unloadBank(String pathToBank);
Expand Down