Compare commits

..

10 commits

Author SHA1 Message Date
f4d536fd95 main 2023-10-26 23:40:26 +09:00
e70d0d2547 arranged more... 2023-10-23 17:11:09 +09:00
db6b1d3085 added verbose onoff & added new example & added universal or not select
- now use : ./update.sh osx release x86_64 or ./update.sh osx release 
universal

by default, it is universal.
2023-10-23 15:21:00 +09:00
816d0e8e43 added arm64 (apple silicon) support
libpd (pd 0.53-1)
godot-cpp (3.5.3 stable)
2023-10-23 14:48:06 +09:00
52405b50f8 added earplug~ support 2023-10-19 19:21:56 +09:00
d282c21cfd many updates
- libpd gui on/off by setting path
- computeaudio (pd dsp 0/1) added
- streamstart delayed to prevent pops
2023-10-13 14:48:36 +09:00
38de570162 updated ... 2023-10-11 18:39:12 +09:00
0c2fc7d192 updated 2023-09-30 19:46:43 +09:00
BERTHAUT Florent
defc59a5d2 Fixed windows compiling 2020-07-21 15:48:55 +02:00
BERTHAUT Florent
97a4035115 Fixed lost communication when reinit 2020-07-19 18:22:21 +02:00
37 changed files with 3131 additions and 316 deletions

View file

@ -1,37 +1,23 @@
[gd_scene load_steps=2 format=2] [gd_scene load_steps=5 format=2]
[sub_resource type="GDScript" id=1] [ext_resource path="res://main.gd" type="Script" id=1]
script/source = "extends Control
var gdpd = load(\"res://addons/gdpd/bin/gdpd.gdns\") [sub_resource type="PhysicsMaterial" id=3]
#var patch
func _ready(): [sub_resource type="SphereShape" id=1]
#the patch path should be the absolute one [sub_resource type="SphereMesh" id=2]
_load_patch(ProjectSettings.globalize_path(\"res://patch1.pd\")) resource_local_to_scene = true
_load_patch(ProjectSettings.globalize_path(\"res://patch2.pd\"))
[node name="main" type="RigidBody" groups=["sounders"]]
collision_layer = 4
collision_mask = 0
physics_material_override = SubResource( 3 )
gravity_scale = 0.0
script = ExtResource( 1 )
func _load_patch(pd_patch) : [node name="CollisionShape" type="CollisionShape" parent="."]
#separate file name from directory shape = SubResource( 1 )
var patch_name = pd_patch.split(\"/\")[-1]
var patch_dir = pd_patch.trim_suffix(patch_name)
#initialize pd [node name="MeshInstance" type="MeshInstance" parent="."]
var patch = gdpd.new() mesh = SubResource( 2 )
#retrieve
var inps = patch.get_available_input_devices()
var outs = patch.get_available_output_devices()
patch.init_devices(inps[0], outs[0])
#load patch
patch.openfile(patch_name, patch_dir)
"
[node name="Control" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
script = SubResource( 1 )

78
GdpdExample/Player.gd Normal file
View file

@ -0,0 +1,78 @@
extends KinematicBody
var camera_angle = 0
var mouse_sensitivity = 0.3
var camera_change = Vector2()
var velocity = Vector3()
var direction = Vector3()
#fly variables
const FLY_SPEED = 20
const FLY_ACCEL = 4
var mouse_captured = true
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _physics_process(delta):
if mouse_captured:
aim()
fly(delta)
# emit signal - playerinfo_updated
var tf = $Head/Camera.get_global_transform_interpolated()
if tf != Events.player_tf_old:
Events.emit_signal("player_transform_updated", $Head/Camera.get_global_translation(), $Head.global_rotation.y)
Events.player_tf_old = tf
if Input.is_action_just_pressed('toggle_mouse'):
if mouse_captured:
mouse_captured = false
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
mouse_captured = true
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _input(event):
if event is InputEventMouseMotion:
camera_change = event.relative
func fly(delta):
# reset the direction of the player
direction = Vector3()
# get the rotation of the camera
var aim = $Head/Camera.get_global_transform().basis
# check input and change direction
if Input.is_action_pressed("move_forward"):
direction -= aim.z
if Input.is_action_pressed("move_backward"):
direction += aim.z
if Input.is_action_pressed("move_left"):
direction -= aim.x
if Input.is_action_pressed("move_right"):
direction += aim.x
direction = direction.normalized()
# where would the player go at max speed
var target = direction * FLY_SPEED
# calculate a portion of the distance to go
velocity = velocity.linear_interpolate(target, FLY_ACCEL * delta)
# move
move_and_slide(velocity)
func aim():
if camera_change.length() > 0:
$Head.rotate_y(deg2rad(-camera_change.x * mouse_sensitivity))
var change = -camera_change.y * mouse_sensitivity
if change + camera_angle < 90 and change + camera_angle > -90:
$Head/Camera.rotate_x(deg2rad(change))
camera_angle += change
camera_change = Vector2()

21
GdpdExample/Player.tscn Normal file
View file

@ -0,0 +1,21 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://Player.gd" type="Script" id=1]
[sub_resource type="CapsuleShape" id=1]
radius = 0.6
height = 2.0
[node name="Player" type="KinematicBody"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.52113, 0.98772 )
script = ExtResource( 1 )
[node name="Capsule" type="CollisionShape" parent="."]
transform = Transform( 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0 )
shape = SubResource( 1 )
[node name="Head" type="Spatial" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0 )
[node name="Camera" type="Camera" parent="Head"]
far = 10000.0

24
GdpdExample/Region.gd Normal file
View file

@ -0,0 +1,24 @@
extends Spatial
var main = load("res://main.tscn")
var sub = load("res://osc.tscn")
func _ready():
# 'main' at center.
var m = main.instance()
add_child(m)
m.set_size(rand_range(10, 15))
m.audible_range_max = 80
m.set_freq(rand_range(100, 300))
m.set_gain(40)
# many 'sub' surrounds 'main' like satellites
for i in range(18):
var s = sub.instance()
add_child(s)
s.set_size(rand_range(0.2, 1.2))
s.set_color(Color.black)
var d = polar2cartesian(rand_range(20, 24), rand_range(0, 2*PI))
s.translate(Vector3(d.x, rand_range(-2, 2), d.y))
s.set_freq(rand_range(200, 2000))
s.set_gain(0.1)

6
GdpdExample/Region.tscn Normal file
View file

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Region.gd" type="Script" id=1]
[node name="Region" type="Spatial"]
script = ExtResource( 1 )

11
GdpdExample/Scene.gd Normal file
View file

@ -0,0 +1,11 @@
extends Node
#var region = load("res://Region.tscn")
func _ready():
pass
# for i in range(18):
# var oscnode = osctscn.instance()
# oscnode.set_size(randf()*5 + 0.2)
# oscnode.set_freq(randf()*800 + 200)
# add_child(oscnode)

44
GdpdExample/Scene.tscn Normal file
View file

@ -0,0 +1,44 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://Region.tscn" type="PackedScene" id=1]
[ext_resource path="res://Player.tscn" type="PackedScene" id=2]
[ext_resource path="res://Scene.gd" type="Script" id=3]
[sub_resource type="BoxShape" id=1]
extents = Vector3( 300, 1, 300 )
[sub_resource type="CubeMesh" id=2]
size = Vector3( 600, 2, 600 )
[sub_resource type="Environment" id=3]
fog_enabled = true
[node name="Scene" type="Node"]
script = ExtResource( 3 )
[node name="StaticBody" type="StaticBody" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 )
[node name="CollisionShape" type="CollisionShape" parent="StaticBody"]
shape = SubResource( 1 )
[node name="MeshInstance" type="MeshInstance" parent="StaticBody"]
mesh = SubResource( 2 )
[node name="DirectionalLight" type="DirectionalLight" parent="."]
transform = Transform( 1, 0, 0, 0, 0.158589, 0.987345, 0, -0.987345, 0.158589, 0, 57.3999, 0 )
shadow_enabled = true
[node name="Player" parent="." instance=ExtResource( 2 )]
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource( 3 )
[node name="Region" parent="." instance=ExtResource( 1 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 30, 0 )
[node name="Region2" parent="." instance=ExtResource( 1 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -193.573, 78.9511, 112.625 )
[node name="Region3" parent="." instance=ExtResource( 1 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 67.7793, 64.9703, -27.1477 )

View file

@ -6,4 +6,3 @@
resource_name = "gdpd" resource_name = "gdpd"
class_name = "Gdpd" class_name = "Gdpd"
library = ExtResource( 1 ) library = ExtResource( 1 )
_sections_unfolded = [ "Resource" ]

Binary file not shown.

View file

@ -0,0 +1,6 @@
extends Node
var player_tf_old = Transform()
signal player_transform_updated(position, heading)
# position : Vector3
# heading : Vector2 (projected x-z plane, and normalized)

View file

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://autoload/Events.gd" type="Script" id=1]
[node name="Events" type="Node"]
script = ExtResource( 1 )

View file

@ -0,0 +1,93 @@
extends Node
#gdpd (pd interface with godot)
var _gdpd
var _patches = []
export (bool) var _enable_gui = false
export (String) var _gui_path = "/Applications/Pd-0.53-1.app/Contents/Resources"
export (bool) var _verbose = false
export (float) var _sample_rate = 48000
export (int) var _blocksize = 256
func _ready():
_gdpd = load("res://addons/gdpd/bin/gdpd.gdns").new()
if _enable_gui:
# set gui path to activate gui window (otherwise, nogui)
_gdpd.set_gui_path(_gui_path)
_gdpd.set_volume(1) # by default, volume(gain) == 0
_gdpd.set_verbose(_verbose) # by default, suppress 'print'
_gdpd.init(0, 2, _sample_rate, _blocksize)
_gdpd.computeAudio(true) # [; pd dsp 1 (
_gdpd.subscribe("toGodot")
# delayed 'stream start' to prevent start-up 'pop' noise.
yield(get_tree().create_timer(0.3), "timeout")
_gdpd.streamstart()
func _exit_tree():
if _patches.size() != 0:
print()
print("! ======== * purging leftover opened patches ... * ======== !")
print()
for id in _patches:
_gdpd.closePatch(id)
_patches.clear()
_gdpd.stop()
func load_patch(pd_patch) -> int:
#the patch path should be the absolute one
#separate file name from directory
var patch_name = pd_patch.split("/")[-1]
var patch_dir = pd_patch.trim_suffix(patch_name)
var id = _gdpd.openPatch(patch_name, patch_dir)
_patches.append(id)
return id
func close_patch(id):
if id in _patches:
_gdpd.closePatch(id)
_patches.erase(id)
func _process(_delta) :
while _gdpd.has_message():
var msg = _gdpd.get_next()
print(msg)
# if msg[0] == "random":
# print("r")
# ==== archived. ====
# duplicate "res://" into 'user://' ==> we need godot 4 for this approach..
# _copydirectory_recursive("res://", "user://")
## copy directory recursively ==> we need godot 4 for this approach..
#func _copydirectory_recursive(src, dst):
# var dotfolders = RegEx.new()
# dotfolders.compile("^\\.\\w*")
# var pdfiles = RegEx.new()
# pdfiles.compile("\\w+\\.pd$")
# var dir = Directory.new()
# if dir.open(src) == OK:
# dir.list_dir_begin()
# var file_name = dir.get_next()
# while file_name != "":
# if dir.current_is_dir():
# print("Found directory: " + file_name)
# if not dotfolders.search(file_name):
# dir.make_dir(dst + "/" + file_name)
# _copydirectory_recursive(dir.get_current_dir() + "/" + file_name, dst + "/" + file_name)
# else:
# if pdfiles.search(file_name):
# print("Found puredata file: " + file_name)
# dir.copy(src + "/" + file_name, dst + "/" + file_name)
#
# file_name = dir.get_next()
# else:
# print("An error occurred when trying to access the path. : " + src)

View file

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://autoload/Global.gd" type="Script" id=1]
[node name="Global" type="Node"]
script = ExtResource( 1 )

View file

@ -0,0 +1,73 @@
[preset.0]
name="Mac OSX"
platform="Mac OSX"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="./Sands and Waves (worldscene1).dmg"
script_export_mode=1
script_encryption_key=""
[preset.0.options]
custom_template/debug=""
custom_template/release=""
application/name=""
application/info="Made with Godot Engine"
application/icon=""
application/identifier="in.dianaband.worldscene1"
application/signature=""
application/app_category="Games"
application/short_version="1.0"
application/version="1.0"
application/copyright=""
display/high_res=false
privacy/microphone_usage_description=""
privacy/camera_usage_description=""
privacy/location_usage_description=""
privacy/address_book_usage_description=""
privacy/calendar_usage_description=""
privacy/photos_library_usage_description=""
privacy/desktop_folder_usage_description=""
privacy/documents_folder_usage_description=""
privacy/downloads_folder_usage_description=""
privacy/network_volumes_usage_description=""
privacy/removable_volumes_usage_description=""
codesign/enable=true
codesign/identity=""
codesign/timestamp=false
codesign/hardened_runtime=false
codesign/replace_existing_signature=true
codesign/entitlements/custom_file=""
codesign/entitlements/allow_jit_code_execution=false
codesign/entitlements/allow_unsigned_executable_memory=false
codesign/entitlements/allow_dyld_environment_variables=false
codesign/entitlements/disable_library_validation=true
codesign/entitlements/audio_input=false
codesign/entitlements/camera=false
codesign/entitlements/location=false
codesign/entitlements/address_book=false
codesign/entitlements/calendars=false
codesign/entitlements/photos_library=false
codesign/entitlements/apple_events=false
codesign/entitlements/debugging=false
codesign/entitlements/app_sandbox/enabled=false
codesign/entitlements/app_sandbox/network_server=false
codesign/entitlements/app_sandbox/network_client=false
codesign/entitlements/app_sandbox/device_usb=false
codesign/entitlements/app_sandbox/device_bluetooth=false
codesign/entitlements/app_sandbox/files_downloads=0
codesign/entitlements/app_sandbox/files_pictures=0
codesign/entitlements/app_sandbox/files_music=0
codesign/entitlements/app_sandbox/files_movies=0
codesign/custom_options=PoolStringArray( )
notarization/enable=false
notarization/apple_id_name=""
notarization/apple_id_password=""
notarization/apple_team_id=""
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -28,6 +28,7 @@ process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/HDR_as_SRGB=false process/HDR_as_SRGB=false
process/invert_color=false process/invert_color=false
process/normal_map_invert_y=false
stream=false stream=false
size_limit=0 size_limit=0
detect_3d=true detect_3d=true

View file

@ -0,0 +1,55 @@
#N canvas 108 222 456 518 12;
#X obj 361 21 loadbang;
#X msg 361 51 \; pd dsp 1;
#X floatatom 21 198 5 0 0 0 - - - 0;
#X obj 21 22 r fromGodot\$0;
#X obj 21 46 list trim;
#X obj 199 467 dac~ 1 2;
#X obj 199 407 *~;
#X obj 189 264 line~;
#X msg 189 240 \$1 100;
#X obj 189 127 unpack f f;
#X floatatom 189 177 5 0 0 0 - - - 0;
#X obj 21 256 noise~;
#X obj 21 286 bp~ 500 1000;
#X obj 21 70 route freq gain panvol;
#X obj 21 316 *~;
#X msg 296 338 \$1 100;
#X floatatom 296 159 5 0 0 0 - - - 0;
#X obj 199 437 earplug~ 0 0;
#X obj 296 362 line;
#X obj 132 310 switch~;
#X obj 132 286 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 132 262 change;
#X text 89 155 switch on/off before 0 to stop startup pops, f 12;
#X obj 189 216 max 0;
#X obj 132 238 > -0.3;
#X obj 296 248 expr 360-$f1;
#X obj 296 182 expr $f1*180/3.141592;
#X connect 2 0 12 1;
#X connect 3 0 4 0;
#X connect 4 0 13 0;
#X connect 6 0 17 0;
#X connect 7 0 6 1;
#X connect 8 0 7 0;
#X connect 9 0 10 0;
#X connect 9 1 16 0;
#X connect 10 0 23 0;
#X connect 10 0 24 0;
#X connect 11 0 12 0;
#X connect 12 0 14 0;
#X connect 13 0 2 0;
#X connect 13 1 14 1;
#X connect 13 2 9 0;
#X connect 14 0 6 0;
#X connect 15 0 18 0;
#X connect 16 0 26 0;
#X connect 17 0 5 0;
#X connect 17 1 5 1;
#X connect 18 0 17 1;
#X connect 20 0 19 0;
#X connect 21 0 20 0;
#X connect 23 0 8 0;
#X connect 24 0 21 0;
#X connect 25 0 15 0;
#X connect 26 0 25 0;

100
GdpdExample/main.gd Normal file
View file

@ -0,0 +1,100 @@
extends RigidBody
export (float, 0, 100) var audible_range_max = 10.0
export (float, 1, 12) var preset = 1
export (bool) var use_embeded_patch = false
export (String, MULTILINE) var patch = ""
var _my_patch = "res://main.pd"
#var _my_patch = "res://main-earplug.pd"
var _my_id = 0
func set_size(size):
$CollisionShape.shape.radius = size
$MeshInstance.mesh.radius = size
$MeshInstance.mesh.height = size * 2
func set_freq(freq):
Global._gdpd.start_message(2)
Global._gdpd.add_symbol('freq')
Global._gdpd.add_float(freq)
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func set_gain(gain):
Global._gdpd.start_message(2)
Global._gdpd.add_symbol('gain')
Global._gdpd.add_float(gain)
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func set_param(param):
Global._gdpd.start_message(param.size()+1)
Global._gdpd.add_symbol("param")
for i in range(param.size()):
Global._gdpd.add_float(param[i])
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func set_preset(prs):
preset = prs
Global._gdpd.start_message(2)
Global._gdpd.add_symbol("preset")
Global._gdpd.add_float(prs)
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func set_color(color):
$MeshInstance.material_override = SpatialMaterial.new()
$MeshInstance.material_override.albedo_color = color
func _ready():
# save patch (for export)
if use_embeded_patch:
assert(_my_patch.substr(0, 7) == "user://", "use userpath with embeded_patch enabled !")
assert(patch != "", "patch is empty?")
_save_patch()
# load patch
_my_id = Global.load_patch(ProjectSettings.globalize_path(_my_patch))
# listen 'player_transform_updated' event
Events.connect("player_transform_updated", self, "_on_Events_player_transform_updated")
# send 'preset'
set_preset(preset)
func _on_Events_player_transform_updated(playerpos, playerheading):
var mypos = get_global_translation()
var mypos2d = Vector2(mypos.x, mypos.z)
var playerpos2d = Vector2(playerpos.x, playerpos.z)
# calculate distance
var distance = mypos.distance_to(playerpos)
# calculate angle
var angle = fmod(fmod(playerpos2d.angle_to_point(mypos2d) + playerheading - PI/2, PI*2) + PI*2, PI*2)
if angle > PI:
angle = angle - PI*2
# (check)
# print(str(_my_id) +" : ("+ str(distance) +","+ str(angle) +")")
# calculate gain
var gain = 1 - distance/audible_range_max
# send to the patch
Global._gdpd.start_message(3)
Global._gdpd.add_symbol("panvol")
Global._gdpd.add_float(gain)
Global._gdpd.add_float(angle)
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func _exit_tree():
Global.close_patch(_my_id)
func _save_patch():
# save patch
# prepare directory
var patch_name = _my_patch.split("/")[-1]
var patch_dir = _my_patch.trim_suffix(patch_name)
var dir = Directory.new()
dir.make_dir_recursive(patch_dir)
# save to file
var file = File.new()
file.open(_my_patch, File.WRITE)
file.store_string(patch)
file.close()

80
GdpdExample/main.pd Normal file
View file

@ -0,0 +1,80 @@
#N canvas 126 281 456 518 12;
#X obj 361 21 loadbang;
#X msg 361 51 \; pd dsp 1;
#X floatatom 21 198 5 0 0 0 - - - 0;
#X obj 21 22 r fromGodot\$0;
#X obj 21 46 list trim;
#X obj 199 467 dac~ 1 2;
#X obj 199 407 *~;
#X obj 189 264 line~;
#X msg 189 240 \$1 100;
#X obj 189 127 unpack f f;
#X floatatom 189 177 5 0 0 0 - - - 0;
#X obj 21 256 noise~;
#X obj 21 286 bp~ 500 1000;
#X obj 21 70 route freq gain panvol;
#X obj 21 316 *~;
#X obj 132 310 switch~;
#X obj 132 286 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 132 262 change;
#X text 89 155 switch on/off before 0 to stop startup pops, f 12;
#X obj 189 216 max 0;
#X obj 132 238 > -0.3;
#X obj 303 253 hsl 100 20 -1 1 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 300 349 line~;
#X msg 300 325 \$1 100;
#X obj 300 278 expr ($f1 + 1)/8;
#X floatatom 300 302 5 0 0 0 - - - 0;
#N canvas 68 97 450 300 pan2~ 0;
#X obj 51 98 cos~;
#X obj 111 98 cos~;
#X obj 33 128 *~;
#X obj 93 128 *~;
#X obj 33 158 outlet~;
#X obj 93 158 outlet~;
#X obj 33 24 inlet~;
#X obj 111 24 inlet~;
#X obj 111 74 +~ 0.75;
#X connect 0 0 2 1;
#X connect 1 0 3 1;
#X connect 2 0 4 0;
#X connect 3 0 5 0;
#X connect 6 0 2 0;
#X connect 6 0 3 0;
#X connect 7 0 8 0;
#X connect 7 0 0 0;
#X connect 8 0 1 0;
#X restore 199 437 pd pan2~;
#X floatatom 296 159 5 0 0 0 - - - 0;
#X obj 296 182 sin;
#X floatatom 296 206 5 0 0 0 - - - 0;
#X connect 2 0 12 1;
#X connect 3 0 4 0;
#X connect 4 0 13 0;
#X connect 6 0 26 0;
#X connect 7 0 6 1;
#X connect 8 0 7 0;
#X connect 9 0 10 0;
#X connect 9 1 27 0;
#X connect 10 0 19 0;
#X connect 10 0 20 0;
#X connect 11 0 12 0;
#X connect 12 0 14 0;
#X connect 13 0 2 0;
#X connect 13 1 14 1;
#X connect 13 2 9 0;
#X connect 14 0 6 0;
#X connect 16 0 15 0;
#X connect 17 0 16 0;
#X connect 19 0 8 0;
#X connect 20 0 17 0;
#X connect 21 0 24 0;
#X connect 22 0 26 1;
#X connect 23 0 22 0;
#X connect 24 0 25 0;
#X connect 25 0 23 0;
#X connect 26 0 5 0;
#X connect 26 1 5 1;
#X connect 27 0 28 0;
#X connect 28 0 29 0;
#X connect 29 0 21 0;

View file

@ -0,0 +1,53 @@
#N canvas 650 226 456 518 12;
#X obj 361 21 loadbang;
#X msg 361 51 \; pd dsp 1;
#X obj 50 277 osc~ 440;
#X floatatom 21 198 5 0 0 0 - - - 0;
#X obj 21 22 r fromGodot\$0;
#X obj 21 46 list trim;
#X obj 199 467 dac~ 1 2;
#X obj 199 407 *~;
#X obj 189 127 unpack f f;
#X obj 21 70 route freq gain panvol;
#X obj 50 301 *~;
#X msg 296 338 \$1 100;
#X floatatom 296 159 5 0 0 0 - - - 0;
#X obj 199 437 earplug~ 0 0;
#X obj 296 362 line;
#X obj 189 264 line~;
#X msg 189 240 \$1 100;
#X floatatom 189 177 5 0 0 0 - - - 0;
#X obj 132 310 switch~;
#X obj 132 286 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 132 262 change;
#X text 89 155 switch on/off before 0 to stop startup pops, f 12;
#X obj 189 216 max 0;
#X obj 132 238 > -0.3;
#X obj 296 248 expr 360-$f1;
#X obj 296 182 expr $f1*180/3.141592;
#X connect 2 0 10 0;
#X connect 3 0 2 0;
#X connect 4 0 5 0;
#X connect 5 0 9 0;
#X connect 7 0 13 0;
#X connect 8 0 17 0;
#X connect 8 1 12 0;
#X connect 9 0 3 0;
#X connect 9 1 10 1;
#X connect 9 2 8 0;
#X connect 10 0 7 0;
#X connect 11 0 14 0;
#X connect 12 0 25 0;
#X connect 13 0 6 0;
#X connect 13 1 6 1;
#X connect 14 0 13 1;
#X connect 15 0 7 1;
#X connect 16 0 15 0;
#X connect 17 0 22 0;
#X connect 17 0 23 0;
#X connect 19 0 18 0;
#X connect 20 0 19 0;
#X connect 22 0 16 0;
#X connect 23 0 20 0;
#X connect 24 0 11 0;
#X connect 25 0 24 0;

100
GdpdExample/osc.gd Normal file
View file

@ -0,0 +1,100 @@
extends RigidBody
export (float, 0, 100) var audible_range_max = 10.0
export (float, 1, 12) var preset = 1
export (bool) var use_embeded_patch = false
export (String, MULTILINE) var patch = ""
var _my_patch = "res://osc.pd"
#var _my_patch = "res://osc-earplug.pd"
var _my_id = 0
func set_size(size):
$CollisionShape.shape.radius = size
$MeshInstance.mesh.radius = size
$MeshInstance.mesh.height = size * 2
func set_freq(freq):
Global._gdpd.start_message(2)
Global._gdpd.add_symbol('freq')
Global._gdpd.add_float(freq)
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func set_gain(gain):
Global._gdpd.start_message(2)
Global._gdpd.add_symbol('gain')
Global._gdpd.add_float(gain)
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func set_param(param):
Global._gdpd.start_message(param.size()+1)
Global._gdpd.add_symbol("param")
for i in range(param.size()):
Global._gdpd.add_float(param[i])
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func set_preset(prs):
preset = prs
Global._gdpd.start_message(2)
Global._gdpd.add_symbol("preset")
Global._gdpd.add_float(prs)
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func set_color(color):
$MeshInstance.material_override = SpatialMaterial.new()
$MeshInstance.material_override.albedo_color = color
func _ready():
# save patch (for export)
if use_embeded_patch:
assert(_my_patch.substr(0, 7) == "user://", "use userpath with embeded_patch enabled !")
assert(patch != "", "patch is empty?")
_save_patch()
# load patch
_my_id = Global.load_patch(ProjectSettings.globalize_path(_my_patch))
# listen 'player_transform_updated' event
Events.connect("player_transform_updated", self, "_on_Events_player_transform_updated")
# send 'preset'
set_preset(preset)
func _on_Events_player_transform_updated(playerpos, playerheading):
var mypos = get_global_translation()
var mypos2d = Vector2(mypos.x, mypos.z)
var playerpos2d = Vector2(playerpos.x, playerpos.z)
# calculate distance
var distance = mypos.distance_to(playerpos)
# calculate angle
var angle = fmod(fmod(playerpos2d.angle_to_point(mypos2d) + playerheading - PI/2, PI*2) + PI*2, PI*2)
if angle > PI:
angle = angle - PI*2
# (check)
# print(str(_my_id) +" : ("+ str(distance) +","+ str(angle) +")")
# calculate gain
var gain = 1 - distance/audible_range_max
# send to the patch
Global._gdpd.start_message(3)
Global._gdpd.add_symbol("panvol")
Global._gdpd.add_float(gain)
Global._gdpd.add_float(angle)
Global._gdpd.finish_list("fromGodot" + String(_my_id))
func _exit_tree():
Global.close_patch(_my_id)
func _save_patch():
# save patch
# prepare directory
var patch_name = _my_patch.split("/")[-1]
var patch_dir = _my_patch.trim_suffix(patch_name)
var dir = Directory.new()
dir.make_dir_recursive(patch_dir)
# save to file
var file = File.new()
file.open(_my_patch, File.WRITE)
file.store_string(patch)
file.close()

78
GdpdExample/osc.pd Normal file
View file

@ -0,0 +1,78 @@
#N canvas 659 277 456 518 12;
#X obj 361 21 loadbang;
#X msg 361 51 \; pd dsp 1;
#X obj 50 277 osc~ 440;
#X floatatom 21 198 5 0 0 0 - - - 0;
#X obj 21 22 r fromGodot\$0;
#X obj 21 46 list trim;
#X obj 199 467 dac~ 1 2;
#X obj 199 407 *~;
#X obj 189 127 unpack f f;
#X obj 21 70 route freq gain panvol;
#X obj 50 301 *~;
#X obj 189 264 line~;
#X msg 189 240 \$1 100;
#X floatatom 189 177 5 0 0 0 - - - 0;
#X obj 132 310 switch~;
#X obj 132 286 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 132 262 change;
#X text 89 155 switch on/off before 0 to stop startup pops, f 12;
#X obj 189 216 max 0;
#X obj 132 238 > -0.3;
#X obj 303 253 hsl 100 20 -1 1 0 0 empty empty empty -2 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 300 349 line~;
#X msg 300 325 \$1 100;
#X obj 300 278 expr ($f1 + 1)/8;
#X floatatom 300 302 5 0 0 0 - - - 0;
#N canvas 68 97 450 300 pan2~ 0;
#X obj 51 98 cos~;
#X obj 111 98 cos~;
#X obj 33 128 *~;
#X obj 93 128 *~;
#X obj 33 158 outlet~;
#X obj 93 158 outlet~;
#X obj 33 24 inlet~;
#X obj 111 24 inlet~;
#X obj 111 74 +~ 0.75;
#X connect 0 0 2 1;
#X connect 1 0 3 1;
#X connect 2 0 4 0;
#X connect 3 0 5 0;
#X connect 6 0 2 0;
#X connect 6 0 3 0;
#X connect 7 0 8 0;
#X connect 7 0 0 0;
#X connect 8 0 1 0;
#X restore 199 437 pd pan2~;
#X floatatom 296 159 5 0 0 0 - - - 0;
#X obj 296 182 sin;
#X floatatom 296 206 5 0 0 0 - - - 0;
#X connect 2 0 10 0;
#X connect 3 0 2 0;
#X connect 4 0 5 0;
#X connect 5 0 9 0;
#X connect 7 0 25 0;
#X connect 8 0 13 0;
#X connect 8 1 26 0;
#X connect 9 0 3 0;
#X connect 9 1 10 1;
#X connect 9 2 8 0;
#X connect 10 0 7 0;
#X connect 11 0 7 1;
#X connect 12 0 11 0;
#X connect 13 0 18 0;
#X connect 13 0 19 0;
#X connect 15 0 14 0;
#X connect 16 0 15 0;
#X connect 18 0 12 0;
#X connect 19 0 16 0;
#X connect 20 0 23 0;
#X connect 21 0 25 1;
#X connect 22 0 21 0;
#X connect 23 0 24 0;
#X connect 24 0 22 0;
#X connect 25 0 6 0;
#X connect 25 1 6 1;
#X connect 26 0 27 0;
#X connect 27 0 28 0;
#X connect 28 0 20 0;

23
GdpdExample/osc.tscn Normal file
View file

@ -0,0 +1,23 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://osc.gd" type="Script" id=1]
[sub_resource type="PhysicsMaterial" id=3]
[sub_resource type="SphereShape" id=1]
[sub_resource type="SphereMesh" id=2]
resource_local_to_scene = true
[node name="osc" type="RigidBody" groups=["sounders"]]
collision_layer = 4
collision_mask = 0
physics_material_override = SubResource( 3 )
gravity_scale = 0.0
script = ExtResource( 1 )
[node name="CollisionShape" type="CollisionShape" parent="."]
shape = SubResource( 1 )
[node name="MeshInstance" type="MeshInstance" parent="."]
mesh = SubResource( 2 )

View file

@ -1,12 +0,0 @@
#N canvas 2 88 450 300 12;
#X obj 344 82 s pd;
#X obj 344 31 loadbang;
#X msg 344 55 dsp 1;
#X obj 152 134 dac~;
#X obj 152 86 osc~ 440;
#X obj 152 110 *~ 0.1;
#X connect 1 0 2 0;
#X connect 2 0 0 0;
#X connect 4 0 5 0;
#X connect 5 0 3 0;
#X connect 5 0 3 1;

View file

@ -1,12 +0,0 @@
#N canvas 2 88 450 300 12;
#X obj 344 82 s pd;
#X obj 344 31 loadbang;
#X msg 344 55 dsp 1;
#X obj 152 134 dac~;
#X obj 152 110 *~ 0.1;
#X obj 152 86 osc~ 600;
#X connect 1 0 2 0;
#X connect 2 0 0 0;
#X connect 4 0 3 0;
#X connect 4 0 3 1;
#X connect 5 0 4 0;

View file

@ -8,20 +8,59 @@
config_version=4 config_version=4
_global_script_classes=[ ]
_global_script_class_icons={
}
[application] [application]
config/name="GdpdExample" config/name="Sands and Waves (worldscene1)"
run/main_scene="res://Main.tscn" run/main_scene="res://Scene.tscn"
config/icon="res://icon.png" config/icon="res://icon.png"
[autoload]
Global="*res://autoload/Global.tscn"
Events="*res://autoload/Events.tscn"
[gui]
common/drop_mouse_on_gui_input_disabled=true
[input]
move_right={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
move_left={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
move_forward={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
move_backward={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
toggle_mouse={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777217,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
[layer_names]
3d_physics/layer_1="world"
3d_physics/layer_2="player"
3d_physics/layer_3="sounder"
[physics]
common/enable_pause_aware_picking=true
[rendering] [rendering]
quality/driver/driver_name="GLES2"
vram_compression/import_etc=true
vram_compression/import_etc2=false
environment/default_environment="res://default_env.tres" environment/default_environment="res://default_env.tres"

View file

@ -7,18 +7,20 @@ opts = Variables([], ARGUMENTS)
env = DefaultEnvironment() env = DefaultEnvironment()
# Define our options # Define our options
opts.Add(EnumVariable('target', "Compilation target", 'debug', ['d', 'debug', 'r', 'release'])) opts.Add(EnumVariable('target', "Compilation target", 'release', ['d', 'debug', 'r', 'release']))
opts.Add(EnumVariable('platform', "Compilation platform", '', ['', 'windows', 'x11', 'linux', 'osx'])) opts.Add(EnumVariable('platform', "Compilation platform", '', ['', 'windows', 'x11', 'linux', 'osx']))
opts.Add(EnumVariable('p', "Compilation target, alias for 'platform'", '', ['', 'windows', 'x11', 'linux', 'osx'])) opts.Add(EnumVariable('p', "Compilation target, alias for 'platform'", '', ['', 'windows', 'x11', 'linux', 'osx']))
opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no')) opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no'))
opts.Add(BoolVariable('use_mingw', "Use the MingW for cross-compiling", 'no')) opts.Add(BoolVariable('use_mingw', "Use the MingW for cross-compiling", 'no'))
opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'GdpdExample/addons/gdpd/bin/')) opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'GdpdExample/addons/gdpd/bin/'))
opts.Add(PathVariable('target_name', 'The library name.', 'libgdpd', PathVariable.PathAccept)) opts.Add(PathVariable('target_name', 'The library name.', 'libgdpd', PathVariable.PathAccept))
opts.Add(EnumVariable("macos_arch", "Target macOS architecture", "universal", ["universal", "x86_64", "arm64"]))
# Local dependency paths, adapt them to your setup # Local dependency paths, adapt them to your setup
godot_headers_path = "src/godot-cpp/godot_headers/" godot_headers_path = "src/godot-cpp/godot-headers/"
cpp_bindings_path = "src/godot-cpp/" cpp_bindings_path = "src/godot-cpp/"
cpp_library = "libgodot-cpp" cpp_library = "libgodot-cpp"
earplug_headers_path = "src/externals/earplug/"
# only support 64 at this time.. # only support 64 at this time..
bits = 64 bits = 64
@ -52,15 +54,24 @@ if env['platform'] == "osx":
env['target_path'] += 'osx/' env['target_path'] += 'osx/'
cpp_library += '.osx' cpp_library += '.osx'
env.Append(CPPDEFINES=['__MACOSX_CORE__', 'HAVE_UNISTD_H', 'LIBPD_EXTRA']) env.Append(CPPDEFINES=['__MACOSX_CORE__', 'HAVE_UNISTD_H', 'LIBPD_EXTRA'])
env.Append(CXXFLAGS=['-std=c++17'])
env.Append(LINKFLAGS=['-arch', 'x86_64','-framework', if env["macos_arch"] == "universal":
'CoreAudio', '-framework', 'CoreFoundation']) env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"])
if env['target'] in ('debug', 'd'): env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"])
env.Append(CCFLAGS=['-g', '-O2', '-arch', 'x86_64'])
else: else:
env.Append(CCFLAGS=['-g', '-O3', '-arch', 'x86_64']) env.Append(LINKFLAGS=["-arch", env["macos_arch"]])
env.Append(CCFLAGS=["-arch", env["macos_arch"]])
env.Append(LINKFLAGS=['-framework', 'CoreAudio', '-framework', 'CoreFoundation'])
env.Append(CXXFLAGS=['-std=c++17'])
if env['target'] in ('debug', 'd'):
env.Append(CCFLAGS=['-g', '-O2'])
else:
env.Append(CCFLAGS=['-g', '-O3'])
elif env['platform'] in ('x11', 'linux'): elif env['platform'] in ('x11', 'linux'):
env['CC'] = 'gcc-7'
env['CXX'] = 'g++-7'
env['target_path'] += 'x11/' env['target_path'] += 'x11/'
cpp_library += '.linux' cpp_library += '.linux'
env.Append(CPPDEFINES=['__UNIX_JACK__', 'LIBPD_EXTRA']) env.Append(CPPDEFINES=['__UNIX_JACK__', 'LIBPD_EXTRA'])
@ -70,7 +81,7 @@ elif env['platform'] in ('x11', 'linux'):
env.Append(CFLAGS=['-std=c11']) env.Append(CFLAGS=['-std=c11'])
env.Append(CXXFLAGS=['-std=c++17']) env.Append(CXXFLAGS=['-std=c++17'])
else: else:
env.Append(CCFLAGS=['-fPIC', '-g', '-O3']) env.Append(CCFLAGS=['-fPIC', '-O3'])
env.Append(CFLAGS=['-std=c11']) env.Append(CFLAGS=['-std=c11'])
env.Append(CXXFLAGS=['-std=c++17']) env.Append(CXXFLAGS=['-std=c++17'])
@ -83,34 +94,40 @@ elif env['platform'] == "windows":
# MSVC # MSVC
env.Append(LINKFLAGS=['/WX']) env.Append(LINKFLAGS=['/WX'])
if env['target'] == 'debug': if env['target'] == 'debug':
env.Append(CCFLAGS=['/EHsc', '/D_DEBUG', '/MDd']) env.Append(CCFLAGS=['/EHsc', '/D_DEBUG', '/MTd'])
elif env['target'] == 'release': elif env['target'] == 'release':
env.Append(CCFLAGS=['/O2', '/EHsc', '/DNDEBUG', '/MD']) env.Append(CCFLAGS=['/O2', '/EHsc', '/DNDEBUG', '/MD'])
else: else:
# MinGW # MinGW
env['CXX'] = 'x86_64-w64-mingw32-g++-win32' env['CXX'] = 'x86_64-w64-mingw32-g++-win32'
env['CC'] = 'x86_64-w64-mingw32-gcc-win32' env['CC'] = 'x86_64-w64-mingw32-gcc-win32'
env.Append(CCFLAGS=['-g', '-O3', '-std=c++14', '-Wwrite-strings', '-fpermissive']) #env.Append(CXXFLAGS=['-g', '-O3', '-std=c++14', '-Wwrite-strings', '-fpermissive'])
env.Append(CXXFLAGS=['-O3', '-std=c++14', '-Wwrite-strings', '-fpermissive'])
#env.Append(LINKFLAGS=['--static', '-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++']) #env.Append(LINKFLAGS=['--static', '-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++'])
#env.Append(CPPDEFINES=['WIN32', '_WIN32', '_MSC_VER', '_WINDOWS', '_CRT_SECURE_NO_WARNINGS']) #env.Append(CPPDEFINES=['WIN32', '_WIN32', '_MSC_VER', '_WINDOWS', '_CRT_SECURE_NO_WARNINGS'])
env.Append(CFLAGS=['-DWINVER=0x502','-DWIN32','-D_WIN32','-Wno-int-to-pointer-cast', env.Append(CFLAGS=['-DWINVER=0x502', '-DWIN32', '-D_WIN32',
'-Wno-pointer-to-int-cast']) '-Wno-int-to-pointer-cast', '-Wno-pointer-to-int-cast'])
env.Append(CPPDEFINES=['HAVE_UNISTD_H=1','LIBPD_EXTRA=1','PD=1', #env.Append(CPPDEFINES=['HAVE_UNISTD_H=1','LIBPD_EXTRA=1','PD=1',
'PD_INTERNAL','USEAPI_DUMMY=1','libpd_EXPORTS']) #'PD_INTERNAL','USEAPI_DUMMY=1','libpd_EXPORTS'])
#env.Append(CPPDEFINES=['__WINDOWS_DS__', 'LIBPD_EXTRA']) env.Append(CPPDEFINES=['PD_INTERNAL', 'libpd_EXPORTS'])
env.Append(CPPDEFINES=['__RTAUDIO_DUMMY__', 'LIBPD_EXTRA']) env.Append(CPPDEFINES=['__WINDOWS_DS__'])
env.Append(CFLAGS=['-DUSEAPI_DUMMY', '-DPD', '-DHAVE_UNISTD_H', '-D_GNU_SOURCE']) #env.Append(CPPDEFINES=['__WINDOWS_WASAPI__'])
#env.Append(CPPDEFINES=['__RTAUDIO_DUMMY__', 'LIBPD_EXTRA'])
#env.Append(CFLAGS=['-DUSEAPI_DUMMY', '-DPD', '-DHAVE_UNISTD_H', '-D_GNU_SOURCE'])
env.Append(LDPATH=['/usr/x86_64-w64-mingw32/lib/']) env.Append(LDPATH=['/usr/x86_64-w64-mingw32/lib/'])
env.Append(LINKFLAGS=['-Wl,--export-all-symbols', env.Append(LINKFLAGS=['-Wl,--export-all-symbols',
'-static-libgcc','/usr/x86_64-w64-mingw32/lib/libm.a']) '-static-libgcc','/usr/x86_64-w64-mingw32/lib/libm.a'])
#env.Append(LINKFLAGS=['-lkernel32','-luser32', '-lgdi32', #env.Append(LIBS=['-lkernel32','-luser32', '-lgdi32',
# '-lwinspool', '-lshell32', '-lole32', # '-lwinspool', '-lshell32', '-lole32',
# '-loleaut32', '-luuid', '-lcomdlg32', # '-loleaut32', '-luuid', '-lcomdlg32',
# '-ladvapi32','-lws2_32', '-lwsock32']) # '-ladvapi32','-lws2_32', '-lwsock32',
env.Append(LINKFLAGS=['/usr/x86_64-w64-mingw32/lib/libws2_32.a', # '-ldsound', '-lwinmm'])
'/usr/x86_64-w64-mingw32/lib/libwsock32.a']) env.Append(LIBS=['-lws2_32', '-lwsock32','-loleaut32', '-luuid',
'-lole32', '-ldsound', '-lwinmm'])
#env.Append(LIBS=['-lws2_32', '-lwsock32','-loleaut32', '-lmfplat','-lmfuuid',
# '-lole32', '-lwmcodecdspuuid' ,'-luuid','-lksuser'])
env['SHLIBSUFFIX'] = '.dll'
#env.Append(CPPDEFINES=['WINVER=0x502']) #env.Append(CPPDEFINES=['WINVER=0x502'])
#env.Append(CCFLAGS=['-W3', '-GR']) #env.Append(CCFLAGS=['-W3', '-GR'])
@ -134,7 +151,7 @@ else:
cpp_library += '.' + str(bits) cpp_library += '.' + str(bits)
# make sure our binding library is properly included # make sure our binding library is properly included
env.Append(CPPPATH=['.', godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/', 'src/libpd/cpp','src/libpd/pure-data/src', 'src/libpd/libpd_wrapper', 'src/libpd/libpd_wrapper/util', 'src/rtaudio']) env.Append(CPPPATH=['.', earplug_headers_path, godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/', 'src/libpd/cpp', 'src/libpd/libpd_wrapper', 'src/libpd/pure-data/src', 'src/libpd/libpd_wrapper/util', 'src/rtaudio'])
env.Append(LIBPATH=[cpp_bindings_path + 'bin/']) env.Append(LIBPATH=[cpp_bindings_path + 'bin/'])
env.Append(LIBS=[cpp_library]) env.Append(LIBS=[cpp_library])
env.Append(CFLAGS=['-DUSEAPI_DUMMY', '-DPD', '-DHAVE_UNISTD_H', '-D_GNU_SOURCE']) env.Append(CFLAGS=['-DUSEAPI_DUMMY', '-DPD', '-DHAVE_UNISTD_H', '-D_GNU_SOURCE'])
@ -142,7 +159,106 @@ env.Append(CFLAGS=['-DUSEAPI_DUMMY', '-DPD', '-DHAVE_UNISTD_H', '-D_GNU_SOURCE']
# tweak this if you want to use different folders, or more folders, to store your source code in. # tweak this if you want to use different folders, or more folders, to store your source code in.
env.Append(CPPPATH=['src/']) env.Append(CPPPATH=['src/'])
sources = Glob('src/*.cpp') + Glob('src/rtaudio/*.cpp') + Glob('src/libpd/libpd_wrapper/*.c') + Glob('src/libpd/libpd_wrapper/util/*.c') + Glob('src/libpd/pure-data/extra/**/*.c') + Glob('src/libpd/pure-data/src/[xmgz]_*.c') + Glob('src/libpd/pure-data/src/d_[acgmorsu]*.c') + Glob('src/libpd/pure-data/src/d_dac.c') + Glob('src/libpd/pure-data/src/d_delay.c') + Glob('src/libpd/pure-data/src/d_fft.c') + Glob('src/libpd/pure-data/src/d_fft_fftsg.c') + Glob('src/libpd/pure-data/src/d_filter.c') + Glob('src/libpd/pure-data/src/s_audio.c') + Glob('src/libpd/pure-data/src/s_audio_dummy.c') + Glob('src/libpd/pure-data/src/s_print.c') + Glob('src/libpd/pure-data/src/s_path.c') + Glob('src/libpd/pure-data/src/s_main.c') + Glob('src/libpd/pure-data/src/s_inter.c') + Glob('src/libpd/pure-data/src/s_utf8.c') + Glob('src/libpd/pure-data/src/s_loader.c') + Glob('src/libpd/pure-data/extra/*.c') # libpd src list: https://github.com/libpd/libpd/blob/d46caa4918bfe07eec08999146e496eb0f744b95/Makefile#L71
sources = Glob('src/*.cpp') \
+ Glob('src/externals/earplug/*.c') \
+ Glob('src/rtaudio/*.cpp') \
+ Glob('src/libpd/pure-data/src/d_arithmetic.c') \
+ Glob('src/libpd/pure-data/src/d_array.c') \
+ Glob('src/libpd/pure-data/src/d_ctl.c') \
+ Glob('src/libpd/pure-data/src/d_dac.c') \
+ Glob('src/libpd/pure-data/src/d_delay.c') \
+ Glob('src/libpd/pure-data/src/d_fft.c') \
+ Glob('src/libpd/pure-data/src/d_fft_fftsg.c') \
+ Glob('src/libpd/pure-data/src/d_filter.c') \
+ Glob('src/libpd/pure-data/src/d_global.c') \
+ Glob('src/libpd/pure-data/src/d_math.c') \
+ Glob('src/libpd/pure-data/src/d_misc.c') \
+ Glob('src/libpd/pure-data/src/d_osc.c') \
+ Glob('src/libpd/pure-data/src/d_resample.c') \
+ Glob('src/libpd/pure-data/src/d_soundfile.c') \
+ Glob('src/libpd/pure-data/src/d_soundfile_aiff.c') \
+ Glob('src/libpd/pure-data/src/d_soundfile_caf.c') \
+ Glob('src/libpd/pure-data/src/d_soundfile_next.c') \
+ Glob('src/libpd/pure-data/src/d_soundfile_wave.c') \
+ Glob('src/libpd/pure-data/src/d_ugen.c') \
+ Glob('src/libpd/pure-data/src/g_all_guis.c') \
+ Glob('src/libpd/pure-data/src/g_array.c') \
+ Glob('src/libpd/pure-data/src/g_bang.c') \
+ Glob('src/libpd/pure-data/src/g_canvas.c') \
+ Glob('src/libpd/pure-data/src/g_clone.c') \
+ Glob('src/libpd/pure-data/src/g_editor.c') \
+ Glob('src/libpd/pure-data/src/g_editor_extras.c') \
+ Glob('src/libpd/pure-data/src/g_graph.c') \
+ Glob('src/libpd/pure-data/src/g_guiconnect.c') \
+ Glob('src/libpd/pure-data/src/g_io.c') \
+ Glob('src/libpd/pure-data/src/g_mycanvas.c') \
+ Glob('src/libpd/pure-data/src/g_numbox.c') \
+ Glob('src/libpd/pure-data/src/g_radio.c') \
+ Glob('src/libpd/pure-data/src/g_readwrite.c') \
+ Glob('src/libpd/pure-data/src/g_rtext.c') \
+ Glob('src/libpd/pure-data/src/g_scalar.c') \
+ Glob('src/libpd/pure-data/src/g_slider.c') \
+ Glob('src/libpd/pure-data/src/g_template.c') \
+ Glob('src/libpd/pure-data/src/g_text.c') \
+ Glob('src/libpd/pure-data/src/g_toggle.c') \
+ Glob('src/libpd/pure-data/src/g_traversal.c') \
+ Glob('src/libpd/pure-data/src/g_undo.c') \
+ Glob('src/libpd/pure-data/src/g_vumeter.c') \
+ Glob('src/libpd/pure-data/src/m_atom.c') \
+ Glob('src/libpd/pure-data/src/m_binbuf.c') \
+ Glob('src/libpd/pure-data/src/m_class.c') \
+ Glob('src/libpd/pure-data/src/m_conf.c') \
+ Glob('src/libpd/pure-data/src/m_glob.c') \
+ Glob('src/libpd/pure-data/src/m_memory.c') \
+ Glob('src/libpd/pure-data/src/m_obj.c') \
+ Glob('src/libpd/pure-data/src/m_pd.c') \
+ Glob('src/libpd/pure-data/src/m_sched.c') \
+ Glob('src/libpd/pure-data/src/s_audio.c') \
+ Glob('src/libpd/pure-data/src/s_audio_dummy.c') \
+ Glob('src/libpd/pure-data/src/s_inter.c') \
+ Glob('src/libpd/pure-data/src/s_inter_gui.c') \
+ Glob('src/libpd/pure-data/src/s_loader.c') \
+ Glob('src/libpd/pure-data/src/s_main.c') \
+ Glob('src/libpd/pure-data/src/s_net.c') \
+ Glob('src/libpd/pure-data/src/s_path.c') \
+ Glob('src/libpd/pure-data/src/s_print.c') \
+ Glob('src/libpd/pure-data/src/s_utf8.c') \
+ Glob('src/libpd/pure-data/src/x_acoustics.c') \
+ Glob('src/libpd/pure-data/src/x_arithmetic.c') \
+ Glob('src/libpd/pure-data/src/x_array.c') \
+ Glob('src/libpd/pure-data/src/x_connective.c') \
+ Glob('src/libpd/pure-data/src/x_file.c') \
+ Glob('src/libpd/pure-data/src/x_gui.c') \
+ Glob('src/libpd/pure-data/src/x_interface.c') \
+ Glob('src/libpd/pure-data/src/x_list.c') \
+ Glob('src/libpd/pure-data/src/x_midi.c') \
+ Glob('src/libpd/pure-data/src/x_misc.c') \
+ Glob('src/libpd/pure-data/src/x_net.c') \
+ Glob('src/libpd/pure-data/src/x_scalar.c') \
+ Glob('src/libpd/pure-data/src/x_text.c') \
+ Glob('src/libpd/pure-data/src/x_time.c') \
+ Glob('src/libpd/pure-data/src/x_vexp.c') \
+ Glob('src/libpd/pure-data/src/x_vexp_if.c') \
+ Glob('src/libpd/pure-data/src/x_vexp_fun.c') \
+ Glob('src/libpd/libpd_wrapper/s_libpdmidi.c') \
+ Glob('src/libpd/libpd_wrapper/x_libpdreceive.c') \
+ Glob('src/libpd/libpd_wrapper/z_hooks.c') \
+ Glob('src/libpd/libpd_wrapper/z_libpd.c') \
+ Glob('src/libpd/pure-data/extra/bob~/bob~.c') \
+ Glob('src/libpd/pure-data/extra/bonk~/bonk~.c') \
+ Glob('src/libpd/pure-data/extra/choice/choice.c') \
+ Glob('src/libpd/pure-data/extra/fiddle~/fiddle~.c') \
+ Glob('src/libpd/pure-data/extra/loop~/loop~.c') \
+ Glob('src/libpd/pure-data/extra/lrshift~/lrshift~.c') \
+ Glob('src/libpd/pure-data/extra/pique/pique.c') \
+ Glob('src/libpd/pure-data/extra/pd~/pdsched.c') \
+ Glob('src/libpd/pure-data/extra/pd~/pd~.c') \
+ Glob('src/libpd/pure-data/extra/sigmund~/sigmund~.c') \
+ Glob('src/libpd/pure-data/extra/stdout/stdout.c') \
+ Glob('src/libpd/libpd_wrapper/util/z_print_util.c') \
+ Glob('src/libpd/libpd_wrapper/util/z_queued.c') \
+ Glob('src/libpd/libpd_wrapper/util/ringbuffer.c')
library = env.SharedLibrary(target=env['target_path'] + env['target_name'] , source=sources) library = env.SharedLibrary(target=env['target_path'] + env['target_name'] , source=sources)

0
main Normal file
View file

1475
src/externals/earplug/earplug_data.h vendored Normal file

File diff suppressed because it is too large Load diff

281
src/externals/earplug/earplug~.c vendored Normal file
View file

@ -0,0 +1,281 @@
/* RT binaural filter: earplug~ */
/* based on KEMAR impulse measurement */
/* Pei Xiang, summer 2004 */
/* Revised in fall 2006 by Jorge Castellanos */
/* Revised in spring 2009 by Hans-Christoph Steiner to compile in the data file */
/* Updated in 2020-2021 by Dan Wilcox & Chikashi Miyama */
#include "m_pd.h"
#include <math.h>
#include <string.h>
#include <errno.h>
#include "earplug~.h"
/* impulse response data */
#ifdef EARPLUG_DATA_NO_EMBED
t_float earplug_impulses[368][2][128] = {{{0.0f}}};
#else
#include "earplug_data.h"
#endif
#define VERSION "0.3.0"
/* these pragmas only apply to Microsoft's compiler */
#ifdef _MSC_VER
#pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */
#pragma warning( disable : 4305 ) /* uncast const double to float */
#endif
/* elevation degree: -40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 */
/* index array: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 */
/* impulse response number: 29 31 37 37 37 37 37 31 29 23 19 13 7 1 */
/* 0 degree response index: 0 29 60 97 134 171 208 245 276 305 328 347 360 367 */
static t_class *earplug_class;
typedef struct _earplug
{
t_object x_obj;
t_outlet *left_channel;
t_outlet *right_channel;
t_float azi;
t_float ele;
unsigned ch_L;
unsigned ch_R;
t_float azimScale[13];
unsigned int azimOffset[13];
t_float ir[2][128];
t_float convBuffer[128];
t_float (*impulses)[2][128]; /* a 3D array of 368x2x128 */
t_float f; /* dummy float for dsp */
int bufferPin;
} t_earplug;
static t_int *earplug_perform(t_int *w)
{
t_earplug *x = (t_earplug *)(w[1]);
t_float *in = (t_float *)(w[2]);
t_float *right_out = (t_float *)(w[3]);
t_float *left_out = (t_float *)(w[4]);
int blocksize = (int)(w[5]);
unsigned i;
if (x->ele < 8.0) /* if elevation is less than 80 degrees... */
{
/* a quantized version of the elevation */
int elevInt = (int)floor(x->ele);
/* used as the index to the array of scaling factors for the azimuth
(adding 4 because the lowest elevation is -4, so it starts at 0) */
unsigned elevGridIndex = elevInt + 4;
unsigned azimIntUp = (unsigned)(x->azi * x->azimScale[elevGridIndex+1]);
float azimFracUp = azimIntUp + 1.0 - x->azi * x->azimScale[elevGridIndex+1];
float azimFracUpInv = 1.0 - azimFracUp;
float elevFracUp = x->ele - elevInt * 1.0;
unsigned azimIntDown = (unsigned)(x->azi * x->azimScale[elevGridIndex]);
float azimFracDown = azimIntDown + 1.0 - x->azi * x->azimScale[elevGridIndex];
float azimFracDownInv = 1.0 - azimFracDown;
float elevFracDown = 1.0 - elevFracUp;
unsigned lowerIdx = x->azimOffset[elevGridIndex] + azimIntDown;
unsigned upperIdx = x->azimOffset[elevGridIndex + 1] + azimIntUp;
for (i = 0; i < 128; i++)
{
/* elevFracDown: interpolate the lower two HRIRs and multiply them by their "fraction"
elevFracUp: interpolate the upper two HRIRs and multiply them by their "fraction" */
x->ir[x->ch_L][i] = elevFracDown *
(azimFracDown * x->impulses[lowerIdx][0][i] +
azimFracDownInv * x->impulses[lowerIdx + 1][0][i]) +
elevFracUp *
(azimFracUp * x->impulses[upperIdx][0][i] +
azimFracUpInv * x->impulses[upperIdx + 1][0][i]);
x->ir[x->ch_R][i] = elevFracDown *
(azimFracDown * x->impulses[lowerIdx][1][i] +
azimFracDownInv * x->impulses[lowerIdx + 1][1][i]) +
elevFracUp *
(azimFracUp * x->impulses[upperIdx][1][i] +
azimFracUpInv * x->impulses[upperIdx + 1][1][i]);
}
}
else
{
/* if elevation is 80 degrees or more the interpolation requires only
three points (because there's only one HRIR at 90 deg) */
/* scale the azimuth to 12 (the number of HRIRs at 80 deg) discreet points */
unsigned azimIntDown = (unsigned)(x->azi * 0.033333);
float azimFracDown = azimIntDown + 1.0 - x->azi * 0.033333;
float elevFracUp = x->ele - 8.0;
float elevFracDown = 9.0 - x->ele;
for (i = 0; i < 128; i++)
{
/* elevFracDown: these two lines interpolate the lower two HRIRs
elevFracUp: multiply the 90 degree HRIR with its corresponding fraction */
x->ir[x->ch_L][i] = elevFracDown *
(azimFracDown * x->impulses[360+azimIntDown][0][i] +
(1.0 - azimFracDown) * x->impulses[361+azimIntDown][0][i])
+ elevFracUp * x->impulses[367][0][i];
x->ir[x->ch_R][i] = elevFracDown *
(azimFracDown * x->impulses[360+azimIntDown][1][i] +
(1.0 - azimFracDown) * x->impulses[361+azimIntDown][1][i])
+ elevFracUp * x->impulses[367][1][i];
}
}
float inSample;
float convSum[2]; /* to accumulate the sum during convolution */
/* convolve the interpolated HRIRs (left and right) with the input signal */
while (blocksize--)
{
convSum[0] = 0;
convSum[1] = 0;
inSample = *(in++);
x->convBuffer[x->bufferPin] = inSample;
for (i = 0; i < 128; i++)
{
convSum[0] += x->ir[0][i] * x->convBuffer[(x->bufferPin - i) &127];
convSum[1] += x->ir[1][i] * x->convBuffer[(x->bufferPin - i) &127];
}
x->bufferPin = (x->bufferPin + 1) & 127;
*left_out++ = convSum[0];
*right_out++ = convSum[1];
}
return w + 6;
}
static void earplug_azimuth(t_earplug *x, float value) {
if (value < 0 || value > 360)
value = 0;
if (value <= 180){
x->ch_L = 0;
x->ch_R = 1;
}
else{
x->ch_L = 1;
x->ch_R = 0;
value = 360.0 - value;
}
x->azi = value;
}
static void earplug_elevation(t_earplug *x, float value) {
if (value < -40)
value = -40;
if (value > 90)
value = 90;
/* divided by 10 since each elevation is 10 degrees apart */
x->ele = value * 0.1;
}
static void earplug_dsp(t_earplug *x, t_signal **sp)
{
/* callback, params, userdata, in_samples, out_L, out_R, blocksize */
dsp_add(earplug_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}
static void *earplug_new(t_floatarg azimArg, t_floatarg elevArg)
{
t_earplug *x = (t_earplug *)pd_new(earplug_class);
x->left_channel = outlet_new(&x->x_obj, gensym("signal"));
x->right_channel = outlet_new(&x->x_obj, gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("azimuth"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("elevation"));
x->azi = azimArg;
x->ele = elevArg;
x->ch_L = 0;
x->ch_R = 1;
int i, j;
FILE *fp;
t_symbol *canvasdir = canvas_getdir(canvas_getcurrent());
char buff[MAXPDSTRING], *bufptr;
int filedesc;
filedesc = open_via_path(canvasdir->s_name, "earplug_data.txt", "", buff, &bufptr, MAXPDSTRING, 0);
if (filedesc >= 0) /* if there was no error opening the text file... */
{
int ret;
fp = fdopen(filedesc, "r");
for (i = 0; i < 368; i++)
{
do {ret = fgetc(fp);}
while (ret != 10 && ret != EOF);
if (ret != EOF)
{
for (j = 0; j < 128; j++)
{
ret = fscanf(fp, "%f %f ", &earplug_impulses[i][0][j],
&earplug_impulses[i][1][j]);
if (ret == EOF) {break;}
}
}
if (ret == EOF)
{
pd_error(x, "earplug~: could not load %s/earplug_data.txt, check format?", buff);
break;
}
}
fclose(fp);
if (ret != EOF) {logpost(x, 3, "earplug~: loaded %s/earplug_data.txt", buff);}
}
x->impulses = earplug_impulses;
for (i = 0; i < 128; i++)
x->convBuffer[i] = 0.f;
x->bufferPin = 0;
/* this is the scaling factor for the azimuth so that it
corresponds to an HRTF in the KEMAR database */
x->azimScale[0] = x->azimScale[8] = 0.153846153; /* -40 and 40 degree */
x->azimScale[1] = x->azimScale[7] = 0.166666666; /* -30 and 30 degree */
x->azimScale[2] = x->azimScale[3] = x->azimScale[4]
= x->azimScale[5] = x->azimScale[6] = 0.2; /* -20 to 20 degree */
x->azimScale[9] = 0.125; /* 50 degree */
x->azimScale[10] = 0.1; /* 60 degree */
x->azimScale[11] = 0.066666666; /* 70 degree */
x->azimScale[12] = 0.033333333; /* 80 degree */
x->azimOffset[0] = 0;
x->azimOffset[1] = 29;
x->azimOffset[2] = 60;
x->azimOffset[3] = 97;
x->azimOffset[4] = 134;
x->azimOffset[5] = 171;
x->azimOffset[6] = 208;
x->azimOffset[7] = 245;
x->azimOffset[8] = 276;
x->azimOffset[9] = 305;
x->azimOffset[10] = 328;
x->azimOffset[11] = 347;
x->azimOffset[12] = 360;
return x;
}
void earplug_tilde_setup(void)
{
earplug_class = class_new(gensym("earplug~"), (t_newmethod)earplug_new, 0,
sizeof(t_earplug), CLASS_DEFAULT, A_DEFFLOAT, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(earplug_class, t_earplug, f);
class_addmethod(earplug_class, (t_method)earplug_dsp, gensym("dsp"), A_CANT, 0);
class_addmethod(earplug_class, (t_method)earplug_azimuth, gensym("azimuth"), A_FLOAT, 0);
class_addmethod(earplug_class, (t_method)earplug_elevation, gensym("elevation"), A_FLOAT, 0);
post("earplug~ %s: binaural filter with measured responses", VERSION);
post(" elevation: -40 to 90 degrees, azimuth: 360 degrees");
post(" do not use a blocksize > 8192");
}

16
src/externals/earplug/earplug~.h vendored Normal file
View file

@ -0,0 +1,16 @@
#ifndef __EARPLUG_H__
#define __EARPLUG_H__
#ifdef __cplusplus
extern "C"
{
#endif
EXTERN void earplug_tilde_setup(void);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -3,15 +3,14 @@
using namespace godot; using namespace godot;
void Gdpd::_register_methods() { void Gdpd::_register_methods() {
register_method("get_available_input_devices", register_method("get_available_input_devices", &Gdpd::get_available_input_devices);
&Gdpd::get_available_input_devices); register_method("get_available_output_devices", &Gdpd::get_available_output_devices);
register_method("get_available_output_devices",
&Gdpd::get_available_output_devices);
register_method("init_devices", &Gdpd::init_devices); register_method("init_devices", &Gdpd::init_devices);
register_method("init", &Gdpd::init); register_method("init", &Gdpd::init);
register_method("streamstart", &Gdpd::streamstart);
register_method("stop", &Gdpd::stop); register_method("stop", &Gdpd::stop);
register_method("openfile", &Gdpd::openfile); register_method("openPatch", &Gdpd::openPatch);
register_method("closefile", &Gdpd::closefile); register_method("closePatch", &Gdpd::closePatch);
register_method("subscribe", &Gdpd::subscribe); register_method("subscribe", &Gdpd::subscribe);
register_method("has_message", &Gdpd::has_message); register_method("has_message", &Gdpd::has_message);
register_method("get_next", &Gdpd::get_next); register_method("get_next", &Gdpd::get_next);
@ -19,7 +18,10 @@ void Gdpd::_register_methods() {
register_method("add_symbol", &Gdpd::add_symbol); register_method("add_symbol", &Gdpd::add_symbol);
register_method("add_float", &Gdpd::add_float); register_method("add_float", &Gdpd::add_float);
register_method("finish_list", &Gdpd::finish_list); register_method("finish_list", &Gdpd::finish_list);
register_method("computeAudio", &Gdpd::computeAudio);
register_method("set_volume", &Gdpd::set_volume); register_method("set_volume", &Gdpd::set_volume);
register_method("set_gui_path", &Gdpd::set_gui_path);
register_method("set_verbose", &Gdpd::set_verbose);
} }
int Gdpd::audioCallback(void *outputBuffer, void *inputBuffer, int Gdpd::audioCallback(void *outputBuffer, void *inputBuffer,
@ -31,7 +33,10 @@ int Gdpd::audioCallback(void *outputBuffer, void *inputBuffer,
return 0; return 0;
} }
Gdpd::Gdpd(): m_vol(1) { Gdpd::Gdpd() : m_vol(0), m_gui_path(""), m_verbose(false) {
//create message array
m_messages = new Array();
m_init=false;
} }
void Gdpd::_init() { void Gdpd::_init() {
@ -39,6 +44,7 @@ void Gdpd::_init() {
} }
Gdpd::~Gdpd() { Gdpd::~Gdpd() {
} }
Array Gdpd::get_available_input_devices() { Array Gdpd::get_available_input_devices() {
@ -108,23 +114,23 @@ int Gdpd::start() {
print("Output channels = "+std::to_string(outParams.nChannels)); print("Output channels = "+std::to_string(outParams.nChannels));
print("Input channels = "+std::to_string(inpParams.nChannels)); print("Input channels = "+std::to_string(inpParams.nChannels));
if(!m_pd.init(m_nbInputs, m_nbOutputs, m_sampleRate, true)) { if(!m_pd.init(m_nbInputs, m_nbOutputs, m_sampleRate, true)) {
Godot::print("GDPD : Error starting libpd"); print("GDPD : Error starting libpd");
return 1; return 1;
} }
//libpd_set_verbose(1); //libpd_set_verbose(1);
//create message array if (m_gui_path != "") {
m_messages = new Array(); libpd_start_gui((char*)m_gui_path.c_str());
}
//create message hook //load externals
m_pd.subscribe("to_gdpd"); //earplug~
m_pd.setReceiver(this); earplug_tilde_setup();
//start dsp //start dsp
m_pd.computeAudio(true); // m_pd.computeAudio(true);
//intialize rtaudio //intialize rtaudio
if(m_audio.getDeviceCount()==0){ if(m_audio.getDeviceCount()==0){
@ -137,28 +143,54 @@ int Gdpd::start() {
if(m_audio.getCurrentApi() != RtAudio::MACOSX_CORE) { if(m_audio.getCurrentApi() != RtAudio::MACOSX_CORE) {
options.flags |= RTAUDIO_MINIMIZE_LATENCY; options.flags |= RTAUDIO_MINIMIZE_LATENCY;
} }
if (m_nbInputs == 0) {
try { try {
m_audio.openStream(&outParams, &inpParams, RTAUDIO_FLOAT32, m_audio.openStream(&outParams, NULL, RTAUDIO_FLOAT32,
m_sampleRate, &m_bufferFrames, &audioCallback, m_sampleRate, &m_bufferFrames, &audioCallback,
this, &options); this, &options);
m_audio.startStream(); // m_audio.startStream();
// print("Stream started");
} }
catch(RtAudioError& e) { catch(RtAudioError& e) {
Godot::print(e.getMessage().c_str()); Godot::print(e.getMessage().c_str());
} }
} else {
try {
m_audio.openStream(&outParams, &inpParams, RTAUDIO_FLOAT32,
m_sampleRate, &m_bufferFrames, &audioCallback,
this, &options);
// m_audio.startStream();
// print("Stream started");
}
catch(RtAudioError& e) {
Godot::print(e.getMessage().c_str());
}
}
//create message hook
m_pd.subscribe("to_gdpd");
m_pd.setReceiver(this);
m_init=true;
print("Initialized"); print("Initialized");
return 0; return 0;
} }
void Gdpd::streamstart() {
m_audio.startStream();
print("Stream started");
}
void Gdpd::stop() { void Gdpd::stop() {
m_audio.stopStream(); m_audio.stopStream();
m_audio.closeStream(); m_audio.closeStream();
m_pd.clear();
m_pd.computeAudio(false); m_pd.computeAudio(false);
print("Stopped"); print("Stopped");
if (m_gui_path != "") {
libpd_stop_gui();
}
} }
void Gdpd::processAudio(void *outputBuffer, void *inputBuffer, void Gdpd::processAudio(void *outputBuffer, void *inputBuffer,
@ -174,23 +206,32 @@ void Gdpd::processAudio(void *outputBuffer, void *inputBuffer,
} }
} }
void Gdpd::openfile(godot::String baseStr, godot::String dirStr) { int Gdpd::openPatch(godot::String baseStr, godot::String dirStr) {
std::wstring baseWs = baseStr.unicode_str(); std::wstring baseWs = baseStr.unicode_str();
std::string baseS(baseWs.begin(), baseWs.end()); std::string baseS(baseWs.begin(), baseWs.end());
std::wstring dirWs = dirStr.unicode_str(); std::wstring dirWs = dirStr.unicode_str();
std::string dirS(dirWs.begin(), dirWs.end()); std::string dirS(dirWs.begin(), dirWs.end());
//libpd_openfile(baseS.c_str(), dirS.c_str()); pd::Patch p1 = m_pd.openPatch(baseS.c_str(), dirS.c_str());
//m_patch = m_pd.openPatch(baseS.c_str(), dirS.c_str()); if(!p1.isValid()) {
m_pd.openPatch(baseS.c_str(), dirS.c_str()); print("Could not open patch "+baseS);
}
else {
print("Opened patch "+baseS+ " [" + std::to_string(p1.dollarZero()) + "]");
m_patchsMap[p1.dollarZero()] = p1;
}
print("Opened patch"); return p1.dollarZero();
} }
void Gdpd::closefile(godot::String baseStr) { void Gdpd::closePatch(int id) {
std::wstring baseWs = baseStr.unicode_str(); if(m_patchsMap.find(id) != m_patchsMap.end()) {
std::string baseS(baseWs.begin(), baseWs.end()); // print("Closing patch, id: "+ std::to_string(id));
m_pd.closePatch(baseS.c_str()); std::string baseS = m_patchsMap[id].filename();
m_pd.closePatch(m_patchsMap[id]);
m_patchsMap.erase(id);
print("Closed patch "+baseS+ " ["+ std::to_string(id) + "]");
}
} }
void Gdpd::subscribe(String symbStr) { void Gdpd::subscribe(String symbStr) {
@ -240,9 +281,10 @@ int Gdpd::finish_list(String destStr) {
return res; return res;
} }
void Gdpd::print(const std::string& message) { void Gdpd::print(const std::string& message) {
if (m_verbose) {
Godot::print((std::string("GDPD : ")+message).c_str()); Godot::print((std::string("GDPD : ")+message).c_str());
}
} }
void Gdpd::receiveList(const std::string& dest, const pd::List& list) { void Gdpd::receiveList(const std::string& dest, const pd::List& list) {
@ -265,3 +307,17 @@ void Gdpd::set_volume(float vol) {
m_vol=vol; m_vol=vol;
} }
void Gdpd::set_gui_path(godot::String pathStr) {
std::wstring pathWs = pathStr.unicode_str();
std::string pathS(pathWs.begin(), pathWs.end());
m_gui_path = pathS;
}
void Gdpd::computeAudio(bool state) { //[; pd dsp 0/1 (
m_pd.computeAudio(state);
}
void Gdpd::set_verbose(bool verbose) {
m_verbose = verbose;
}

View file

@ -4,6 +4,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <map>
#include <Godot.hpp> #include <Godot.hpp>
#include <AudioStreamPlayer.hpp> #include <AudioStreamPlayer.hpp>
@ -12,6 +13,8 @@
#include "PdReceiver.hpp" #include "PdReceiver.hpp"
#include "RtAudio.h" #include "RtAudio.h"
#include "earplug~.h"
namespace godot { namespace godot {
class Gdpd : public godot::AudioStreamPlayer, public pd::PdReceiver { class Gdpd : public godot::AudioStreamPlayer, public pd::PdReceiver {
@ -31,6 +34,11 @@ private:
int m_sampleRate; int m_sampleRate;
int m_inputDevice; int m_inputDevice;
int m_outputDevice; int m_outputDevice;
std::map<int, pd::Patch> m_patchsMap;
std::string m_gui_path;
bool m_verbose;
bool m_init;
public: public:
static void _register_methods(); static void _register_methods();
@ -46,9 +54,10 @@ public:
int init_devices(String inputDevice, String outputDevice); int init_devices(String inputDevice, String outputDevice);
int init(int nbInputs, int nbOutputs, int sampleRate, int bufferSize); int init(int nbInputs, int nbOutputs, int sampleRate, int bufferSize);
int start(); int start();
void streamstart();
void stop(); void stop();
void openfile(String basename, String dirname); int openPatch(String basename, String dirname);
void closefile(String basename); void closePatch(int id);
bool has_message(); bool has_message();
Array get_next(); Array get_next();
int blocksize(); int blocksize();
@ -63,9 +72,13 @@ public:
void receiveList(const std::string& dest, const pd::List& list); void receiveList(const std::string& dest, const pd::List& list);
//godot functions //godot functions
void computeAudio(bool state); //[; pd dsp 0/1 (
void set_gui_path(godot::String path);
void set_volume(float vol); void set_volume(float vol);
inline const float& get_volume(){return m_vol;} inline const float& get_volume(){
return m_vol;
}
void set_verbose(bool verbose);
//rtaudio //rtaudio
static int audioCallback(void *outputBuffer, void *inputBuffer, static int audioCallback(void *outputBuffer, void *inputBuffer,

@ -1 +1 @@
Subproject commit 3ee07f652bbbe91630a8346e3fe39a05f0f1d76a Subproject commit 76d6ad5d8db23b086b175d785812744d2bacf62a

@ -1 +1 @@
Subproject commit e07d211d7b7e5f8dd6d2e3ddce557ae453161a14 Subproject commit f1f8967e663027937e7934a357aff5fb116367c4

Binary file not shown.

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
git submodule update --init --recursive git submodule update --init --recursive
cd src/godot-cpp cd src/godot-cpp
scons platform=$1 generate_bindings=yes scons platform=$1 target=$2 macos_arch=$3 generate_bindings=yes
cd ../.. cd ../..
scons platform=$1 scons platform=$1 target=$2 macos_arch=$3