PortAudio module for godot

portaudio

module for godot

Table of contents

Why?

Pros

  • Audio is not tied to any Godot-Node, it can be controlled from anywhere.
  • Flexibility choose which driver to use at runtime, depending on the system and apis that are available.
  • Full control over input buffer (for recording requirements) and output buffer. (beneficial for audio tools)
  • Lower latency due to more direct access to audio hardware. (beneficial for music rythm games)(*1)

Cons

  • Requires to write your own audio pipeline. (from decoding the file format, to filling the playback buffer)
  • More code to detect and configure the driver.

*1) only applies when utilizing c++ audio callback, not GDScript bindings

Setup:

via submodule

  • open a terminal inside the godot source folder and run the following commands:
    cd modules
    git submodule add https://github.com/sebastian-heinz/portaudio.git
    git submodule update --init --recursive

via download

Building

Edit the SCsub file and comment / uncomment the desired host apis in use_host_api = [. When building godot it will check if the host api is supported for the platform (windows, linux or osx) and available inside the use_host_api-array. Only then the host api will be available.

Driver

Driver windows x11 osx
ASIO Working (*1) Not Tested Not Available
DSOUND Working Not Available Not Available
WASAPI Working (*2) Not Available Not Available
WDM/KS Working Not Available Not Available
WMME Error Not Available Not Available
JACK Not Available Not Tested Not Available
ALSA Not Available Not Tested Not Available
ASIHPI Not Available Not Tested Not Available
COREAUDIO Not Available Not Available Working
OSS Not Available Not Tested Not Available

*1) requires that the enduser has asio drivers installed (ex. ASIO4ALL)
*2) if used godots wasapi driver will be disabled

Godot Integration

  • PortAudio is a singleton class, its purpose is to provide wrapper methods for all PortAudio calls (PA_*) with a godot type friendly interface. For direct access from anywhere

Nodes

A PortAudioTestNode exists, simply add it to a scene via the editor and it will enumerate your host apis and devices and print them out:

Example GDScripts

Tone Generator:

Youtube Video:
Godot - PortAudio Module

extends Node

class_name ToneGenerator

# Member variables
var sample_rate = 8000
var frequenzy_hz = 40
var duration = 1

# Constants
const SAMPLE_SIZE = 4 # float
	
func _ready():
	start_port_audio()
	return

func start_port_audio():
	var samples = duration * sample_rate
	
	var device_index = PortAudio.get_default_output_device()
	
	var out_p = PortAudioStreamParameter.new()
	out_p.set_device_index(device_index)
	out_p.set_channel_count(2)
	
	var stream = PortAudioStream.new()
	stream.set_output_stream_parameter(out_p)
	stream.set_sample_format(PortAudioStreamParameter.FLOAT_32)
	stream.set_frames_per_buffer(samples * SAMPLE_SIZE)

	var audio_callback = funcref(self, "audio_callback")
	var user_data = samples
	var err = PortAudio.open_stream(stream, audio_callback, user_data)
	if(err != PortAudio.NO_ERROR):
		push_error("open_stream: %s" % err)
		
	err = PortAudio.start_stream(stream)	
	if(err != PortAudio.NO_ERROR):
		push_error("start_stream: %s" % err)
		return

# Audio Callback
func audio_callback(data : PortAudioCallbackData):
	var buff = data.get_output_buffer()
	var samples = data.get_user_data()
	for i in range (samples):
		var sample : float = sin(2 * PI * float(i) / ( sample_rate / frequenzy_hz))
		buff.put_float(sample)
	return PortAudio.CONTINUE

C++

This module will add PortAudio to the include path. It allows to work with PortAudio s library directly:

#include <portaudio.h>

For tutorials on how to use PortAudio have a look at the official documentation: http://portaudio.com/docs/v19-doxydocs/initializing_portaudio.html

Gotchas and Tips

Callback Tips

Please refer to https://app.assembla.com/wiki/show/portaudio/Tips_Callbacks for a better understand about the delicate callback function.

Especially:

Regarding crossing language boundaries such as calling Java or Lua:
In general it should be avoided. But, in fact, Lua has a bounded time GC so, 
like the Supercollider language, it could be used in a PortAudio callback 
so long as you make sure it doesn’t violate the points I made above: 
i.e. avoid calling the OS level memory allocator, file I/O, or doing other things 
which violate the above in your Lua user functions. . 
That said, running Lua in a PortAudio callback is definitely at the experimental end of the spectrum.

Exposing PortAudio to GDScript will have some performance overhead and introduces additional audio latency. If you are looking for low latency it would be best to utilzie the CallbackFunction in C++. To get a better understanding of how long the callback took, the duration in μs (Microsecond) can be obtained from the callback data PortAudioCallbackData::get_last_call_duration().

Frames Per Buffer

The callback provides a frames_per_buffer-variable. This does not represent bytes. Depending on the format (FLOAT_32 = 4bytes, INT_16 = 2bytes) and channels the buffer size can be calculated.

bytes_per_channel = (FLOAT_32 = 4 bytes) (INT_16 = 2byte) (INT_8 = 1byte)
buffer_size = frames_per_buffer * channels * bytes_per_channel

Ensure that each callback the buffer is filled up correctly or it could result in slow and crackling audio. The same also applies when utilizing blocking mode via write().

Time spend in Callback

If the execution time of the callback function is longer than the playback data provided to the buffer the audio might also become slow and crackling. To calculate the playback duration of the buffer the requested frames can be divided by the sample rate.

time_request_seconds = frames_per_buffer / sample_rate

The execution time of the audio loop has to be faster than this time.

Callback Result

The return value of the callback indicates if it should continue to be called or it can be signaled to stop.
C++:

enum PortAudioCallbackResult {
	CONTINUE = 0,
	COMPLETE = 1,
	ABORT = 2,
};

GDScript:

PortAudio.CONTINUE
PortAudio.COMPLETE
PortAudio.ABORT

TODO

  • doc_classes need to be written for GDScript documentation.
  • [WIN] [WDMKS]-driver clashes with godot imports. (error LNK2005: KSDATAFORMAT_SUBTYPE_MIDI already defined in dxguid.lib(dxguid.obj))
  • [LINUX] build pipeline untested.

Dependencies

Links

Godot:
https://github.com/godotengine/godot

Portaudio:
https://app.assembla.com/spaces/portaudio/git/source
http://www.portaudio.com/
https://github.com/PortAudio/portaudio

ASIO SDK 2.0:
https://www.steinberg.net/en/company/developers.html

Asio4All Driver:
http://www.asio4all.org/

Similar Resources

💻 PTerm | Pretty Terminal Printer A golang module to print pretty text

💻 PTerm | Pretty Terminal Printer A golang module to print pretty text

✨ PTerm is a modern go module to beautify console output. Featuring charts, progressbars, tables, trees, and many more 🚀 It's completely configurable and 100% cross-platform compatible.

Jan 1, 2023

an SSO and OAuth / OIDC login solution for Nginx using the auth_request module

an SSO and OAuth / OIDC login solution for Nginx using the auth_request module

Vouch Proxy An SSO solution for Nginx using the auth_request module. Vouch Proxy can protect all of your websites at once. Vouch Proxy supports many O

Jan 4, 2023

The mep-agent module provides proxy services for 3rd applications to MEP.

Mep-Agent Introduction Mep-Agent is a middleware that provides proxy services for third-party apps. It can help apps, which do not implement the ETSI

Mar 9, 2022

A sub module of EdgeGallery MECM which responsible for the app lifecycle management

mecm-applcm Description Application life cycle manager is part of MEP manager whose responsibility is to handle the host level life cycle management i

Jan 10, 2022

A sub module of EdgeGallery MECM which responsible for the app rule management

mecm-apprulemgr 介绍 Application rule manager 软件架构 软件架构说明 安装教程 xxxx xxxx xxxx 使用说明 xxxx xxxx xxxx 参与贡献 Fork 本仓库 新建 Feat_xxx 分支 提交代码 新建 Pull Request 特技 使

Jan 24, 2022

uber's ssh certificate pam module

Uber's SSH certificate pam module. This is a pam module that will authenticate a user based on them having an ssh certificate in their ssh-agent signe

Jan 2, 2023

Checks if there are any updates for imports in your module.

Go Up goup checks if there are any updates for imports in your module. It parses go.mod files to get dependencies with their version, uses go-git to r

Jul 7, 2022

A fully self-contained Nmap like parallel port scanning module in pure Golang that supports SYN-ACK (Silent Scans)

gomap What is gomap? Gomap is a fully self-contained nmap like module for Golang. Unlike other projects which provide nmap C bindings or rely on other

Dec 10, 2022

A cross-platform app-development module for Go.

A cross-platform app-development module for Go.

The cross-platform Go module for building apps (pronounced klo-va-seed). Usecases As a lightweight alternative to Electron Write your frontend and nat

Dec 1, 2022

Gohack: mutable checkouts of Go module dependencies

Gohack: mutable checkouts of Go module dependencies The new Go module system is awesome. It ensures repeatable, deterministic builds of Go code.

Dec 12, 2022

UPBit Auto Trading with OpenAPI Golang Module

Go-Bit! UPBit Auto Trading System with OpenAPI 이 레포지토리는 upbit를 위한 자동매매 프로그램을 개발하기 위해 제공하는 go module입니다. Features 구현 작업 진행상황 Sample Code Template shiel

Jun 27, 2022

Gos: Armed Golang 💪 ( solutions for go module, goproxy, cross compilation, etc.)

Gos: Armed Golang 💪 ( solutions for go module, goproxy, cross compilation, etc.)

The current gos is still an alpha version, welcome more heroes to comment and improve it 🍓 , you can add more commands to it, or modify something to make it perform better.

Sep 15, 2022

Terraform utility provider for constructing bash scripts that use data from a Terraform module

Terraform Bash Provider This is a Terraform utility provider which aims to robustly generate Bash scripts which refer to data that originated in Terra

Sep 6, 2022

HTTP rate limiting module for Caddy 2

This module implements both internal and distributed HTTP rate limiting. Requests can be rejected after a specified rate limit is hit.

Jan 3, 2023

Go module for the Cardano Blockchain

cardano-go cardano-go is both a library for creating go applicactions that interact with the Cardano Blockchain as well as a CLI to manage Cardano Wal

Dec 1, 2022

Go module for communicating with the Veryfi OCR API

Go module for communicating with the Veryfi OCR API

veryfi-go is a Go module for communicating with the Veryfi OCR API Installing This package can be installed by cloning this directory: git clone https

Jan 5, 2023

A lightweight Vault client module written in Go, with no dependencies, that is intuitive and user-friendly

libvault A lightweight Hashicorp Vault client written in Go, with no dependencies. It aims to provide an intuitive, simple API that is easy to use. Ju

Sep 18, 2022

Go module to validate Apple app attestations and assertions.

AppAttest Since iOS 14, Apple offers a new way to attest the integrity of a device. This is based on the WebAuthn specification. This go module implem

Nov 22, 2022

🔹 Golang module to move the terminal cursor in any direction on every operating system.

🔹 Golang module to move the terminal cursor in any direction on every operating system.

AtomicGo | cursor Get The Module | Documentation | Contributing | Code of Conduct Description Package cursor contains cross-platform methods to move t

Dec 22, 2022
Comments
  • Sample code in README gives weird squealing

    Sample code in README gives weird squealing

    The sample code in the README, on Linux with ALSA, doesn't seem to work for me (even after fixing #1 and #2).

    First, frequency_hz isn't defined. But let's set it to the Versailles-approved A above Middle C: 435 hz.

    This gives a weird sound. It does seem to have some relation to the frequency value, but it's weirdly noisy: bug.zip

  • sample code in README calls method on wrong object

    sample code in README calls method on wrong object

    The sample code in the README says:

    	
    	var out_p = PortAudioStreamParameter.new()
    	out_p.set_device_index(device_index)
    	out_p.set_channel_count(2)
    	
    	var stream = PortAudioStream.new()
    	stream.set_output_stream_parameter(out_p)
    	stream.set_sample_format(PortAudioStreamParameter.FLOAT_32)
    

    But that should be

    	out_p.set_sample_format(PortAudioStreamParameter.FLOAT_32)
    
  • Compilation fails on Linux

    Compilation fails on Linux

    I'm using the Godot 3 branch against Godot 3.4.5.

    After following the instructions in the README, compilation fails on Linux. This is true whether I use ALSA or Jack as the host API. The reason is that the host library (asound or Jack) isn't added to the linking with -l.

    As a workaround, I did

    diff --git a/platform/x11/detect.py b/platform/x11/detect.py
    index 432801ecac..66f8bb6b16 100644
    --- a/platform/x11/detect.py
    +++ b/platform/x11/detect.py
    @@ -223,6 +223,7 @@ def configure(env):
         env.ParseConfig("pkg-config xrandr --cflags --libs")
         env.ParseConfig("pkg-config xrender --cflags --libs")
         env.ParseConfig("pkg-config xi --cflags --libs")
    +    env.ParseConfig("pkg-config alsa --cflags --libs")
    

    But this is obviously not the real fix -- ideally, this library would work without this.

Kakoune syntax highlighting for the Godot Engine / Godot Scripting Language gdscript
Kakoune syntax highlighting for the Godot Engine / Godot Scripting Language gdscript

gdscript-kak Kakoune syntax highlighting for the Godot Engine / Godot Scripting Language gdscript. Adds basic syntax highlighting to your .gd files fo

Mar 2, 2021
PHP functions implementation to Golang. This package is for the Go beginners who have developed PHP code before. You can use PHP like functions in your app, module etc. when you add this module to your project.

PHP Functions for Golang - phpfuncs PHP functions implementation to Golang. This package is for the Go beginners who have developed PHP code before. Y

Dec 30, 2022
✨ #PTerm is a modern go module to beautify console output. Featuring charts, progressbars, tables, trees, and many more 🚀 It's completely configurable and 100% cross-platform compatible.
✨ #PTerm is a modern go module to beautify console output. Featuring charts, progressbars, tables, trees, and many more 🚀 It's completely configurable and 100% cross-platform compatible.

?? PTerm | Pretty Terminal Printer A golang module to print pretty text Show Demo Code PTerm.sh | Installation | Documentation | Quick Start | Example

Dec 27, 2022
Golang client for redislabs' ReJSON module with support for multilple redis clients (redigo, go-redis)

Go-ReJSON - a golang client for ReJSON (a JSON data type for Redis) Go-ReJSON is a Go client for ReJSON Redis Module. ReJSON is a Redis module that im

Dec 25, 2022
Go module for encoding structs into URL query parameters

qs Package sonh/qs encodes structs into url.Values. Installation go get github.com/sonh/qs Usage import ( "github.com/sonh/qs" ) Package qs export

Jan 7, 2023
The imghdr module determines the type of image contained in a file for go
The imghdr module determines the type of image contained in a file for go

goimghdr Inspired by Python's imghdr Installation go get github.com/corona10/goimghdr List of return value Value Image format "rgb" SGI ImgLib Files

Oct 10, 2022
A simple logging module for go, with a rotating file feature and console logging.

A simple logging module for go, with a rotating file feature and console logging. Installation go get github.com/jbrodriguez/mlog Usage Sample usage W

Dec 14, 2022
Go module to work with Postman Collections

go-postman-collection Go module to work with Postman Collections. This module aims to provide a simple way to work with Postman collections. Using thi

Dec 29, 2022
xmlwriter is a pure-Go library providing procedural XML generation based on libxml2's xmlwriter module

xmlwriter xmlwriter is a pure-Go library providing a procedural XML generation API based on libxml2's xmlwriter module. The package is extensively doc

Sep 27, 2022
go-xss is a module used to filter input from users to prevent XSS attacks

go-xss 根据白名单过滤 HTML(防止 XSS 攻击) go-xss is a module used to filter input from users to prevent XSS attacks go-xss是一个用于对用户输入的内容进行过滤,以避免遭受 XSS 攻击的模块

Nov 3, 2022