Compare commits
10 Commits
df36499be1
...
07340588f4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07340588f4 | ||
|
|
e8e6d683d4 | ||
|
|
6c8abfbade | ||
|
|
c1b9da418e | ||
|
|
70fc7019dc | ||
|
|
88595d288f | ||
|
|
b6d78aaa8c | ||
|
|
abf505668e | ||
|
|
ccbc76c2fa | ||
|
|
7298fa66e1 |
2
AUTEURS
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
BATISTA CARDOSO,TIAGO,tiago.batista-cardoso@etu.u-paris.fr
|
||||||
|
LOTENBERG, Rayane, rayane.lotenberg@etu.u-paris.fr
|
||||||
73
Makefile
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
include Makefile.version
|
||||||
|
ASSET_DIR_PATH="\"$(shell pwd)/assets\""
|
||||||
|
CC?=gcc
|
||||||
|
CFLAGS=-Wall `pkg-config --cflags sdl2` -I `heptc -where`/c \
|
||||||
|
-D ASSET_DIR_PATH=$(ASSET_DIR_PATH) -D YEAR=$(ANNEE) \
|
||||||
|
-D VERSION=$(VERSION) -g -fsanitize=undefined
|
||||||
|
LDFLAGS=`pkg-config --libs sdl2` -lm -fsanitize=undefined
|
||||||
|
HEPTC?=heptc
|
||||||
|
|
||||||
|
HEPT_OBJ=\
|
||||||
|
src/challenge.o \
|
||||||
|
src/city.o \
|
||||||
|
src/globals.o \
|
||||||
|
src/vehicle.o \
|
||||||
|
src/control.o \
|
||||||
|
src/utilities.o \
|
||||||
|
src/challenge_types.o \
|
||||||
|
src/city_types.o \
|
||||||
|
src/globals_types.o \
|
||||||
|
src/vehicle_types.o \
|
||||||
|
src/control_types.o \
|
||||||
|
src/utilities_types.o
|
||||||
|
OBJ=$(HEPT_OBJ) \
|
||||||
|
src/buffer.o \
|
||||||
|
src/trace_lib.o \
|
||||||
|
src/trace.o \
|
||||||
|
src/debug.o \
|
||||||
|
src/mathext.o \
|
||||||
|
src/map.o \
|
||||||
|
src/cutils.o \
|
||||||
|
src/simulation_loop.o \
|
||||||
|
src/challenge.o \
|
||||||
|
src/main.o
|
||||||
|
TARGET=scontest
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.PHONY: all clean test
|
||||||
|
.PRECIOUS: %.epci %.c %.h
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) $(TARGET)
|
||||||
|
rm -f $(foreach ext, mls obc epci epo log, $(wildcard src/*.$(ext)))
|
||||||
|
rm -rf src/*_c
|
||||||
|
rm -f $(subst .o,.c,$(HEPT_OBJ))
|
||||||
|
rm -f $(subst .o,.h,$(HEPT_OBJ))
|
||||||
|
|
||||||
|
test: $(TARGET)
|
||||||
|
./$< -o logs.txt assets/00.map
|
||||||
|
|
||||||
|
$(TARGET): $(OBJ)
|
||||||
|
$(CC) $^ $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
%_types.c %.c %.h %.epci : %.ept src/mathext.epci src/debug.epci src/trace.epci
|
||||||
|
cd `dirname $<` && $(HEPTC) -c -target c `basename $<`
|
||||||
|
cp $(foreach ext,c h,$(basename $<)_c/*.$(ext)) src
|
||||||
|
|
||||||
|
%.epci: %.epi
|
||||||
|
cd `dirname $<` && $(HEPTC) `basename $<`
|
||||||
|
|
||||||
|
src/vehicle.epci: src/globals.epci src/utilities.epci src/control.epci
|
||||||
|
src/utilities.epci: src/globals.epci
|
||||||
|
src/control.epci: src/globals.epci src/utilities.epci
|
||||||
|
src/city.epci: src/globals.epci src/utilities.epci src/vehicle.epci src/map.epci
|
||||||
|
src/map.epci: src/map.epi src/globals.epci
|
||||||
|
src/challenge.epci: src/globals.epci src/vehicle.epci src/city.epci src/map.epci
|
||||||
|
src/main.o src/map.o: src/globals.h src/globals_types.h
|
||||||
|
src/simulation_loop.o: src/globals.h src/globals_types.h src/challenge.h
|
||||||
2
Makefile.version
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
VERSION="\"1.1.0\""
|
||||||
|
ANNEE="\"2025-2026\""
|
||||||
69
README.md
@@ -1,67 +1,6 @@
|
|||||||
# Programmation Synchrone 2025-2026 (M2 Info & EIDD)
|
# Projet de Programmation synchrone
|
||||||
|
|
||||||
## Présentation
|
Ce répertoire contient le projet du cours de Programmation synchrone du M2
|
||||||
|
Informatique de l'Université de Paris et de l'École d'Ingénieur Denis Diderot.
|
||||||
|
|
||||||
Le [syllabus](cours/syllabus-progsync.pdf) (résumé) du module est disponible.
|
Le [sujet](sujet/sujet-projet.pdf) contient tous les détails.
|
||||||
|
|
||||||
### Contenu et objectifs
|
|
||||||
|
|
||||||
Le module de *Programmation synchrone* propose une introduction à la
|
|
||||||
programmation des **systèmes réactifs** par le biais de langages spécialisés,
|
|
||||||
les **langages synchrones**.
|
|
||||||
|
|
||||||
- Les **systèmes réactifs** sont des systèmes informatiques en interaction
|
|
||||||
continue avec un environnement extérieur. Le pilote automatique d'un avion
|
|
||||||
moderne (_fly-by-wire_), le contrôleur d'une machine à laver, ou le logiciel
|
|
||||||
de commande d'un ascenseur constituent des exemples de systèmes réactifs.
|
|
||||||
|
|
||||||
- Les **langages synchrones** sont des langages spécialement conçus pour la
|
|
||||||
programmation des systèmes réactifs. Ils offrent une expressivité élevée tout
|
|
||||||
en garantissant statiquement certaines propriétés de sûreté. Leur usage est
|
|
||||||
désormais routinier dans les tâches conception et de développement dans
|
|
||||||
certains secteurs industriels, comme l'avionique ou le ferroviaire.
|
|
||||||
|
|
||||||
L'enseignement des langages synchrones vise deux objectifs. D'abord, **renforcer
|
|
||||||
vos compétences de programmation**, en vous faisant découvrir une famille de
|
|
||||||
langages à la fois originaux et utilisés dans l'industrie. Ensuite, **enrichir
|
|
||||||
votre culture scientifique**, en illustrant comment les systèmes réactifs
|
|
||||||
fournissent un exemple de point de jonction entre l'informatique et d'autres
|
|
||||||
disciplines comme l'automatique ou le traitement du signal.
|
|
||||||
|
|
||||||
Pour atteindre ces objectifs, on utilisera le langage universitaire
|
|
||||||
[*Heptagon*](https://gitlab.inria.fr/synchrone/heptagon), aussi bien durant le
|
|
||||||
cours magistral, pour illustrer les principes généraux des langages synchrones,
|
|
||||||
que durant les séances de travaux pratiques. Les autres langages synchrones
|
|
||||||
(notamment d'origines industrielles) seront aussi régulièrement évoqués durant
|
|
||||||
le cours.
|
|
||||||
|
|
||||||
## Organisation du cours
|
|
||||||
|
|
||||||
Le cours magistral a lieu le *lundi de 10h45 à 12h45*, dans la salle 1009 du
|
|
||||||
bâtiment Sophie Germain.
|
|
||||||
|
|
||||||
Les séances de travaux pratiques ont lieu en salle 2003 du bâtiment Sophie
|
|
||||||
Germain, avec deux groupes disponibles :
|
|
||||||
|
|
||||||
- le *mardi de 10h45 à 12h45*,
|
|
||||||
|
|
||||||
- le *jeudi de 08h30 à 10h30*.
|
|
||||||
|
|
||||||
Nous vous demandons **d'apporter votre ordinateur portable**.
|
|
||||||
|
|
||||||
## Modalités de contrôle des connaissances
|
|
||||||
|
|
||||||
La note du cours sera composée pour 50% de celle du projet et pour 50% de celle
|
|
||||||
de l'examen final. Les cours de master 2 n'offrent pas de deuxième session.
|
|
||||||
|
|
||||||
## Organisation de ce dépôt
|
|
||||||
|
|
||||||
Ce dépôt contiendra tout le matériel pédagogique du cours :
|
|
||||||
|
|
||||||
- le **support du cours**, dans les sous-répertoire [cours](cours/) et surtout
|
|
||||||
[notes](notes/),
|
|
||||||
|
|
||||||
- les **énoncés de TP**, dans le sous-répertoire [TP](tp/),
|
|
||||||
|
|
||||||
- l'**énoncé du projet, ainsi que son squelette**, seront ultérieurement
|
|
||||||
disponibles dans le sous-répertoire [projet](projet/).
|
|
||||||
|
|||||||
2
assets/00.iti
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
go 20
|
||||||
|
stop 0.
|
||||||
17
assets/00.map
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
map "oneway_line"
|
||||||
|
graphics "map_00_oneway_line.bmp"
|
||||||
|
guide "b-00.bmp"
|
||||||
|
init 50. 50. 23.703
|
||||||
|
rd 1
|
||||||
|
line 1 30 50. 50. 550. 250.
|
||||||
|
wp 1
|
||||||
|
0 550. 250.
|
||||||
|
tl 0
|
||||||
|
st 0
|
||||||
|
obst 2
|
||||||
|
30. 30. 1. 10.
|
||||||
|
200. 200. 8. 30.
|
||||||
|
iti 2
|
||||||
|
go 20.
|
||||||
|
stop
|
||||||
|
end
|
||||||
8
assets/01.iti
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
go 20
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
30
assets/01.map
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
map "oneway_square"
|
||||||
|
graphics "map_01_oneway_square.bmp"
|
||||||
|
guide "b-01.bmp"
|
||||||
|
init 550. 200. 90.
|
||||||
|
rd 4
|
||||||
|
line 1 30 50. 50. 550. 50.
|
||||||
|
line 1 20 550. 50. 550. 250.
|
||||||
|
line 1 30 550. 250. 50. 250.
|
||||||
|
line 1 20 50. 250. 50. 50.
|
||||||
|
wp 5
|
||||||
|
0 548. 50.
|
||||||
|
1 550. 148.
|
||||||
|
1 550. 248.
|
||||||
|
2 52. 250.
|
||||||
|
3 50. 52.
|
||||||
|
tl 0
|
||||||
|
st 0
|
||||||
|
obst 2
|
||||||
|
30. 30. 1. 10.
|
||||||
|
200. 200. 8. 30.
|
||||||
|
iti 8
|
||||||
|
go 20
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
2
assets/02.iti
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
go 20
|
||||||
|
stop 0.
|
||||||
20
assets/02.map
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
map "oneway_olympic"
|
||||||
|
graphics "map_02_oneway_olympic.bmp"
|
||||||
|
guide "b-02.bmp"
|
||||||
|
init 480. 100. 0.
|
||||||
|
rd 4
|
||||||
|
line 1 30 100. 100. 500. 100.
|
||||||
|
arc 1 20 500. 150. 50. -90. 90.
|
||||||
|
line 1 30 500. 200. 100. 200.
|
||||||
|
arc 1 20 100. 150. 50. 90. 270.
|
||||||
|
wp 1
|
||||||
|
0 449. 100.
|
||||||
|
tl 0
|
||||||
|
st 0
|
||||||
|
obst 2
|
||||||
|
30. 30. 1. 10.
|
||||||
|
200. 200. 8. 30.
|
||||||
|
iti 2
|
||||||
|
go 20
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
5
assets/03.iti
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
go 20
|
||||||
|
go 15.
|
||||||
|
turn -44.
|
||||||
|
go 25.
|
||||||
|
stop 0.
|
||||||
29
assets/03.map
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
map "oneway_ea"
|
||||||
|
graphics "map_03_oneway_ea.bmp"
|
||||||
|
guide "b-03.bmp"
|
||||||
|
init 20. 20. 35.
|
||||||
|
rd 5
|
||||||
|
line 1 20 5. 5. 100. 100.
|
||||||
|
line 1 20 100. 100. 160. 130.
|
||||||
|
line 1 20 160. 130. 230. 130.
|
||||||
|
arc 1 20 230. 230. 100. -90. 0.
|
||||||
|
line 1 20 230. 130. 330. 30.
|
||||||
|
wp 4
|
||||||
|
0 100. 100.
|
||||||
|
2 229. 130.
|
||||||
|
3 330. 230.
|
||||||
|
4 329. 31.
|
||||||
|
tl 2
|
||||||
|
0 60. 50. 5 3 5 7
|
||||||
|
2 220. 120. 5 3 5 10
|
||||||
|
st 2
|
||||||
|
0 0 50. 50.
|
||||||
|
2 1 220. 130.
|
||||||
|
obst 0
|
||||||
|
iti 5
|
||||||
|
go 20
|
||||||
|
go 15.
|
||||||
|
turn -44.
|
||||||
|
go 25.
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
6
assets/04.iti
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
go 10
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 10.
|
||||||
|
stop 0.
|
||||||
27
assets/04.map
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
map "olympic_cut"
|
||||||
|
graphics "map_04_olympic_cut.bmp"
|
||||||
|
guide "b-04.bmp"
|
||||||
|
init 10. 150. 0.
|
||||||
|
rd 5
|
||||||
|
line 1 10 5. 150. 500. 150.
|
||||||
|
arc 1 20 100. 150. 50. 270. 90.
|
||||||
|
line 1 30 100. 200. 400. 200.
|
||||||
|
arc 1 20 400. 150. 50. 90. -90.
|
||||||
|
line 1 30 400. 100. 100. 100.
|
||||||
|
wp 4
|
||||||
|
0 48. 150.
|
||||||
|
0 448. 150.
|
||||||
|
0 498. 150.
|
||||||
|
3 449. 152.
|
||||||
|
tl 0
|
||||||
|
st 0
|
||||||
|
obst 0
|
||||||
|
iti 6
|
||||||
|
go 10
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 10.
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
|
|
||||||
13
assets/05.iti
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
go 10
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 20.
|
||||||
|
go 30.
|
||||||
|
turn -90.
|
||||||
|
go 20
|
||||||
|
turn -90.
|
||||||
|
go 10
|
||||||
|
go 10
|
||||||
|
go 10
|
||||||
|
stop 0.
|
||||||
42
assets/05.map
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
map "olympic_cut_tl"
|
||||||
|
graphics "map_05_olympic_cut_tl.bmp"
|
||||||
|
guide "b-05.bmp"
|
||||||
|
init 10. 150. 0.
|
||||||
|
rd 6
|
||||||
|
line 1 10 5. 150. 500. 150.
|
||||||
|
arc 1 20 100. 150. 50. 270. 90.
|
||||||
|
line 1 30 100. 200. 400. 200.
|
||||||
|
arc 1 20 400. 150. 50. 90. -90.
|
||||||
|
line 1 30 400. 100. 100. 100.
|
||||||
|
line 1 20 250. 200. 250. 100.
|
||||||
|
wp 8
|
||||||
|
0 48. 150.
|
||||||
|
0 448. 150.
|
||||||
|
0 498. 150.
|
||||||
|
3 450. 152.
|
||||||
|
2 248. 200.
|
||||||
|
5 250. 102.
|
||||||
|
5 250. 152.
|
||||||
|
0 248. 150.
|
||||||
|
tl 2
|
||||||
|
5 245. 160. 5 3 5 3
|
||||||
|
0 240. 145. 5 3 5 8
|
||||||
|
st 2
|
||||||
|
5 0 250. 160.
|
||||||
|
0 1 240. 150.
|
||||||
|
obst 0
|
||||||
|
iti 12
|
||||||
|
go 10
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 20.
|
||||||
|
go 25.
|
||||||
|
turn -90.
|
||||||
|
go 20
|
||||||
|
turn -90.
|
||||||
|
go 10
|
||||||
|
go 10
|
||||||
|
go 10
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
13
assets/06.iti
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
go 10.
|
||||||
|
go 10.
|
||||||
|
turn -90.
|
||||||
|
go 30.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
turn 90.
|
||||||
|
go 25.
|
||||||
|
stop 0.
|
||||||
|
|
||||||
44
assets/06.map
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
map "roundabout"
|
||||||
|
graphics "map_06_roundabout.bmp"
|
||||||
|
guide "b-06.bmp"
|
||||||
|
init 60. 150. 0.
|
||||||
|
rd 10
|
||||||
|
line 1 20 50. 150. 100. 150.
|
||||||
|
arc 1 10 150. 150. 50. 180. 270.
|
||||||
|
line 1 30 150. 100. 150. 50.
|
||||||
|
arc 1 10 150. 150. 50. -90. 0.
|
||||||
|
line 1 30 200. 150. 250. 150.
|
||||||
|
arc 1 10 150. 150. 50. 0. 90.
|
||||||
|
line 1 30 150. 200. 150. 250.
|
||||||
|
arc 1 20 150. 150. 75. 0. -90.
|
||||||
|
arc 1 20 150. 150. 75. 90. 0.
|
||||||
|
arc 1 10 150. 150. 50. 90. 180.
|
||||||
|
wp 11
|
||||||
|
0 98. 150.
|
||||||
|
1 148. 100.4
|
||||||
|
2 150. 77.
|
||||||
|
2 150. 52.
|
||||||
|
3 199.9 148.
|
||||||
|
4 248. 150.
|
||||||
|
5 152. 199.9
|
||||||
|
6 150. 223.
|
||||||
|
6 150. 248.
|
||||||
|
8 224.8 153.
|
||||||
|
7 153. 75.2
|
||||||
|
tl 0
|
||||||
|
st 0
|
||||||
|
obst 0
|
||||||
|
iti 12
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
go 10.
|
||||||
|
go 10.
|
||||||
|
turn -90.
|
||||||
|
go 25.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
turn 90.
|
||||||
|
go 25.
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
13
assets/07.iti
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
go 10.
|
||||||
|
go 10.
|
||||||
|
turn -90.
|
||||||
|
go 30.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
|
|
||||||
53
assets/07.map
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
map "roundabout_tl"
|
||||||
|
graphics "map_07_roundabout_tl.bmp"
|
||||||
|
guide "b-07.bmp"
|
||||||
|
init 60. 150. 0.
|
||||||
|
rd 10
|
||||||
|
line 1 20 50. 150. 100. 150.
|
||||||
|
arc 1 10 150. 150. 50. 180. 270.
|
||||||
|
line 1 30 150. 100. 150. 50.
|
||||||
|
arc 1 10 150. 150. 50. -90. 0.
|
||||||
|
line 1 30 200. 150. 250. 150.
|
||||||
|
arc 1 10 150. 150. 50. 0. 90.
|
||||||
|
line 1 30 150. 200. 150. 250.
|
||||||
|
arc 1 20 150. 150. 75. 0. -90.
|
||||||
|
arc 1 20 150. 150. 75. 90. 0.
|
||||||
|
arc 1 10 150. 150. 50. 90. 180.
|
||||||
|
wp 11
|
||||||
|
0 98. 150.
|
||||||
|
1 148. 100.4
|
||||||
|
2 150. 77.
|
||||||
|
2 150. 52.
|
||||||
|
3 199.9 148.
|
||||||
|
4 223. 150.
|
||||||
|
4 248. 150.
|
||||||
|
5 152. 199.9
|
||||||
|
6 150. 223.
|
||||||
|
6 150. 248.
|
||||||
|
8 224.8 153.
|
||||||
|
7 153. 75.2
|
||||||
|
tl 4
|
||||||
|
2 145. 85. 5 3 5 3
|
||||||
|
7 165. 70.9 5 3 5 8
|
||||||
|
4 215. 145. 5 3 5 3
|
||||||
|
8 218.5 164.9 5 3 5 8
|
||||||
|
st 4
|
||||||
|
2 0 150. 85.
|
||||||
|
7 1 165. 76.5
|
||||||
|
4 2 215. 150.
|
||||||
|
8 3 223.5 164.9
|
||||||
|
obst 0
|
||||||
|
iti 12
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
go 10.
|
||||||
|
go 10.
|
||||||
|
turn -90.
|
||||||
|
go 25.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
12
assets/08.iti
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
go 10.
|
||||||
|
turn -90.
|
||||||
|
go 30.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
go 10.
|
||||||
|
turn -90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 25.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
72
assets/08.map
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
map "nycity"
|
||||||
|
graphics "map_08_nycity.bmp"
|
||||||
|
guide "b-08.bmp"
|
||||||
|
init 20. 250. 0.
|
||||||
|
|
||||||
|
rd 20
|
||||||
|
line 1 30 5. 250. 50. 250.
|
||||||
|
line 1 30 50. 250. 150. 250.
|
||||||
|
|
||||||
|
line 1 30 150. 250. 200. 250.
|
||||||
|
line 1 20 50. 250. 50. 150.
|
||||||
|
|
||||||
|
line 1 20 150. 250. 150. 150.
|
||||||
|
line 1 20 200. 250. 200. 150.
|
||||||
|
|
||||||
|
line 1 30 50. 150. 150. 150.
|
||||||
|
line 1 30 150. 150. 200. 150.
|
||||||
|
|
||||||
|
line 1 20 50. 150. 50. 50.
|
||||||
|
line 1 20 150. 150. 150. 50.
|
||||||
|
|
||||||
|
line 1 20 200. 150. 200. 50.
|
||||||
|
line 1 30 50. 50. 150. 50.
|
||||||
|
|
||||||
|
line 1 30 150. 50. 200. 50.
|
||||||
|
line 1 30 250. 50. 275. 50.
|
||||||
|
|
||||||
|
line 1 30 200. 250. 250. 250.
|
||||||
|
line 1 20 250. 250. 250. 150.
|
||||||
|
|
||||||
|
line 1 30 200. 150. 250. 150.
|
||||||
|
line 1 20 250. 150. 250. 100.
|
||||||
|
line 1 20 250. 150. 250. 50.
|
||||||
|
line 1 30 200. 50. 250. 50.
|
||||||
|
wp 20
|
||||||
|
0 48. 250.
|
||||||
|
1 148. 250.
|
||||||
|
2 198. 250.
|
||||||
|
3 50. 152.
|
||||||
|
4 150. 152.
|
||||||
|
5 200. 152.
|
||||||
|
6 148. 150.
|
||||||
|
7 198. 150.
|
||||||
|
8 50. 52.
|
||||||
|
9 150. 52.
|
||||||
|
10 200. 52.
|
||||||
|
11 148. 50.
|
||||||
|
12 198. 50.
|
||||||
|
13 273. 50.
|
||||||
|
14 248. 250.
|
||||||
|
15 250. 152.
|
||||||
|
16 248. 150.
|
||||||
|
17 250. 102.
|
||||||
|
18 250. 52.
|
||||||
|
19 248. 50.
|
||||||
|
tl 0
|
||||||
|
st 0
|
||||||
|
obst 0
|
||||||
|
iti 12
|
||||||
|
go 10.
|
||||||
|
turn -90.
|
||||||
|
go 25.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
go 10.
|
||||||
|
turn -90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 25.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
14
assets/09.iti
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
go 20.
|
||||||
|
go 20.
|
||||||
|
go 20.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
turn 30.
|
||||||
|
go 20.
|
||||||
|
turn 100.
|
||||||
|
go 10.
|
||||||
|
stop 0.
|
||||||
105
assets/09.map
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
map "paris"
|
||||||
|
graphics "map_09_paris.bmp"
|
||||||
|
guide "b-09.bmp"
|
||||||
|
init 40. 275. 0.
|
||||||
|
|
||||||
|
rd 31
|
||||||
|
line 1 30 25. 275. 100. 275.
|
||||||
|
line 1 20 100. 275. 175. 275.
|
||||||
|
line 1 30 175. 275. 250. 275.
|
||||||
|
line 1 20 250. 275. 400. 275.
|
||||||
|
line 1 30 400. 275. 475. 275.
|
||||||
|
line 1 20 50. 225. 25. 275.
|
||||||
|
line 1 20 100. 275. 100. 225.
|
||||||
|
line 1 20 175. 275. 175. 225.
|
||||||
|
line 1 20 250. 275. 250. 225.
|
||||||
|
line 1 20 400. 275. 400. 175.
|
||||||
|
line 1 30 100. 225. 50. 225.
|
||||||
|
line 1 30 175. 225. 100. 225.
|
||||||
|
line 1 20 250. 225. 175. 225.
|
||||||
|
line 1 20 400. 175. 250. 225.
|
||||||
|
line 1 30 475. 175. 400. 175.
|
||||||
|
line 1 20 50. 225. 175. 100.
|
||||||
|
line 1 30 100. 225. 100. 175.
|
||||||
|
line 1 30 175. 225. 175. 100.
|
||||||
|
line 1 30 250. 225. 250. 100.
|
||||||
|
line 1 30 400. 175. 400. 100.
|
||||||
|
line 1 20 250. 100. 175. 100.
|
||||||
|
line 1 20 400. 100. 250. 100.
|
||||||
|
line 1 30 450. 100. 400. 100.
|
||||||
|
line 1 20 175. 100. 225. 50.
|
||||||
|
line 1 20 325. 100. 225. 50.
|
||||||
|
line 1 20 400. 100. 400. 75.
|
||||||
|
line 1 20 400. 75. 325. 50.
|
||||||
|
line 1 20 400. 75. 450. 25.
|
||||||
|
line 1 30 325. 50. 225. 50.
|
||||||
|
line 1 10 225. 50. 175. 25.
|
||||||
|
line 1 10 225. 50. 250. 25.
|
||||||
|
wp 32
|
||||||
|
0 98. 275.
|
||||||
|
1 173. 275.
|
||||||
|
2 248. 275.
|
||||||
|
3 398. 275.
|
||||||
|
4 473. 275.
|
||||||
|
5 23. 273.
|
||||||
|
6 100. 227.
|
||||||
|
7 175. 227.
|
||||||
|
8 250. 227.
|
||||||
|
9 400. 177.
|
||||||
|
10 52. 225.
|
||||||
|
11 102. 225.
|
||||||
|
12 177. 225.
|
||||||
|
13 260. 223.
|
||||||
|
14 402. 175.
|
||||||
|
15 173. 102.
|
||||||
|
16 100. 177.
|
||||||
|
17 175. 102.
|
||||||
|
18 250. 102.
|
||||||
|
19 400. 102.
|
||||||
|
20 177. 100.
|
||||||
|
21 252. 100.
|
||||||
|
21 327. 100.
|
||||||
|
22 402. 100.
|
||||||
|
23 223. 52.
|
||||||
|
24 227. 51.
|
||||||
|
25 400. 77.
|
||||||
|
26 340. 55.
|
||||||
|
27 448. 27.
|
||||||
|
28 235. 50.
|
||||||
|
29 187. 30.
|
||||||
|
30 240. 35.
|
||||||
|
|
||||||
|
tl 6
|
||||||
|
15 165. 105. 5 3 5 3
|
||||||
|
17 170. 115. 5 3 5 8
|
||||||
|
20 185. 105. 5 3 5 13
|
||||||
|
23 215. 55. 5 3 5 3
|
||||||
|
24 240. 60. 5 3 5 8
|
||||||
|
28 240. 53. 5 3 5 13
|
||||||
|
|
||||||
|
st 6
|
||||||
|
15 0 165. 110.
|
||||||
|
17 1 175. 115.
|
||||||
|
20 2 185. 100.
|
||||||
|
23 3 215. 60.
|
||||||
|
24 4 245. 60.
|
||||||
|
28 5 240. 50.
|
||||||
|
|
||||||
|
obst 0
|
||||||
|
|
||||||
|
iti 14
|
||||||
|
go 20.
|
||||||
|
go 20.
|
||||||
|
go 20.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 10.
|
||||||
|
turn 30.
|
||||||
|
go 20.
|
||||||
|
turn 100.
|
||||||
|
go 10.
|
||||||
|
stop 0.
|
||||||
|
end
|
||||||
20
assets/11.iti
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
go 30.
|
||||||
|
turn 90.
|
||||||
|
go 30.
|
||||||
|
turn 45.
|
||||||
|
go 30.
|
||||||
|
turn -45.
|
||||||
|
go 30.
|
||||||
|
turn -70.
|
||||||
|
go 20.
|
||||||
|
turn 120.
|
||||||
|
go 20.
|
||||||
|
turn -110.
|
||||||
|
go 20.
|
||||||
|
turn -45.
|
||||||
|
go 30.
|
||||||
|
turn -45.
|
||||||
|
go 30.
|
||||||
|
turn 135.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
40
assets/11.map
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
map "hamburg"
|
||||||
|
rd 14
|
||||||
|
line 1 20 15. 270. 30. 210.
|
||||||
|
arc 1 20 120. 210. 90. 180. 270.
|
||||||
|
line 1 20 120. 120. 60. 60.
|
||||||
|
line 1 20 60. 60. 15. 60.
|
||||||
|
|
||||||
|
line 1 20 120. 120. 300. 90.
|
||||||
|
line 1 20 300. 90. 480. 120.
|
||||||
|
arc 1 20 360. 120. 120. 0. 90.
|
||||||
|
line 1 20 360. 240. 240. 240.
|
||||||
|
|
||||||
|
arc 1 20 240. 120. 120. 90. 180.
|
||||||
|
line 1 20 240. 240. 120. 120.
|
||||||
|
arc 1 20 360. 150. 90. 90. 180.
|
||||||
|
line 1 20 270. 150. 300. 90.
|
||||||
|
|
||||||
|
line 1 20 410. 280. 360. 240.
|
||||||
|
line 1 20 480. 120. 585. 120.
|
||||||
|
wp 11
|
||||||
|
1 118. 120.9
|
||||||
|
2 62. 62.
|
||||||
|
3 20. 60.
|
||||||
|
5 478. 119.3
|
||||||
|
|
||||||
|
6 362. 239.1
|
||||||
|
7 242. 240.
|
||||||
|
8 120.9 122.
|
||||||
|
9 122. 122.
|
||||||
|
|
||||||
|
11 299. 92.
|
||||||
|
12 362. 241.6
|
||||||
|
13 570. 120.
|
||||||
|
|
||||||
|
tl 1
|
||||||
|
12 365. 248. 5 3 5 7
|
||||||
|
|
||||||
|
st 1
|
||||||
|
12 0 370. 248.
|
||||||
|
end
|
||||||
21
assets/12.iti
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
go 30.
|
||||||
|
go 20.
|
||||||
|
turn -45.
|
||||||
|
go 30.
|
||||||
|
turn -45.
|
||||||
|
go 30.
|
||||||
|
turn -90.
|
||||||
|
go 30.
|
||||||
|
turn -60.
|
||||||
|
go 20.
|
||||||
|
turn 120.
|
||||||
|
go 20.
|
||||||
|
turn -110.
|
||||||
|
go 20.
|
||||||
|
turn -45.
|
||||||
|
go 30.
|
||||||
|
turn -45.
|
||||||
|
go 30.
|
||||||
|
turn 135.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
42
assets/12.map
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
map "PRG"
|
||||||
|
rd 14
|
||||||
|
line 1 30 585. 60. 480. 120.
|
||||||
|
line 1 30 480. 120. 420. 180.
|
||||||
|
line 1 20 420. 180. 300. 240.
|
||||||
|
line 1 20 300. 240. 300. 120.
|
||||||
|
|
||||||
|
line 1 20 300. 120. 180. 120.
|
||||||
|
line 1 20 300. 240. 180. 240.
|
||||||
|
line 1 20 180. 120. 180. 240.
|
||||||
|
line 1 20 180. 120. 120. 60.
|
||||||
|
|
||||||
|
line 1 20 180. 30. 120. 60.
|
||||||
|
line 1 20 120. 60. 60. 120.
|
||||||
|
arc 1 10 180. 120. 120. 90. 180.
|
||||||
|
line 1 20 60. 120. 15. 30.
|
||||||
|
|
||||||
|
line 1 20 180. 240. 180. 290.
|
||||||
|
line 1 20 300. 290. 300. 240.
|
||||||
|
|
||||||
|
wp 11
|
||||||
|
2 302. 238.5
|
||||||
|
3 300. 122.
|
||||||
|
4 182. 120.
|
||||||
|
5 182. 240.
|
||||||
|
|
||||||
|
6 180. 238.
|
||||||
|
7 122. 62.
|
||||||
|
8 122. 59.
|
||||||
|
9 62. 118.
|
||||||
|
|
||||||
|
11 20. 40.
|
||||||
|
12 180. 280.
|
||||||
|
13 300. 242.
|
||||||
|
|
||||||
|
tl 2
|
||||||
|
2 310. 240. 5 3 5 7
|
||||||
|
13 295. 250. 8 3 5 7
|
||||||
|
st 2
|
||||||
|
2 0 310. 235.
|
||||||
|
13 1 300. 250.
|
||||||
|
end
|
||||||
12
assets/13.iti
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
go 20.
|
||||||
|
turn 15.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
go 20.
|
||||||
|
turn 45.
|
||||||
|
go 20.
|
||||||
|
go 20.
|
||||||
|
turn -45.
|
||||||
|
go 20.
|
||||||
|
stop.
|
||||||
52
assets/13.map
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
map "PRD"
|
||||||
|
rd 18
|
||||||
|
line 1 20 300.0 60.0 300.0 15.0
|
||||||
|
line 1 20 180.0 15.0 180.0 60.0
|
||||||
|
line 1 20 300.0 60.0 585.0 60.0
|
||||||
|
line 1 20 30.0 20.0 120.0 180.0
|
||||||
|
|
||||||
|
line 1 20 180.0 60.0 120.0 60.0
|
||||||
|
line 1 20 180.0 60.0 300.0 60.0
|
||||||
|
line 1 20 300.0 60.0 300.0 120.0
|
||||||
|
line 1 20 120.0 180.0 300.0 60.0
|
||||||
|
|
||||||
|
line 1 20 300.0 120.0 480.0 240.0
|
||||||
|
line 1 20 300.0 120.0 210.0 180.0
|
||||||
|
line 1 20 210.0 180.0 120.0 180.0
|
||||||
|
line 1 20 15.0 180.0 120.0 180.0
|
||||||
|
|
||||||
|
line 1 20 120.0 60.0 120.0 180.0
|
||||||
|
line 1 20 70.0 280.0 120.0 180.0
|
||||||
|
line 1 20 120.0 180.0 120.0 280.0
|
||||||
|
line 1 20 120.0 180.0 210.0 240.0
|
||||||
|
|
||||||
|
line 1 20 210.0 240.0 480.0 240.0
|
||||||
|
line 1 20 480.0 240.0 585.0 240.0
|
||||||
|
|
||||||
|
wp 16
|
||||||
|
0 300. 20.
|
||||||
|
1 180. 56.
|
||||||
|
2 570. 60.
|
||||||
|
3 117.75 176.
|
||||||
|
|
||||||
|
4 124. 60.
|
||||||
|
5 296. 60.
|
||||||
|
6 300. 116.
|
||||||
|
7 297. 62.
|
||||||
|
|
||||||
|
8 477 238.
|
||||||
|
10 124. 180.
|
||||||
|
11 116. 180.
|
||||||
|
12 120. 176.
|
||||||
|
|
||||||
|
13 118. 184.
|
||||||
|
14 120. 260.
|
||||||
|
15 206. 238.
|
||||||
|
17 570. 240.
|
||||||
|
|
||||||
|
tl 1
|
||||||
|
16 465. 235. 5 3 5 7
|
||||||
|
st 1
|
||||||
|
16 0 465. 240.
|
||||||
|
end
|
||||||
|
|
||||||
12
assets/14.iti
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
go 30.
|
||||||
|
turn 120.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 20.
|
||||||
|
turn 45.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 20.
|
||||||
|
turn 130.
|
||||||
|
go 20.
|
||||||
|
stop.
|
||||||
61
assets/14.map
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
map "seine"
|
||||||
|
rd 22
|
||||||
|
line 1 20 420. 10. 300. 70.
|
||||||
|
line 1 20 300. 70. 180. 70.
|
||||||
|
line 1 20 180. 70. 100. 10.
|
||||||
|
line 1 20 300. 70. 300. 10.
|
||||||
|
|
||||||
|
line 1 20 180. 70. 180. 10.
|
||||||
|
line 1 20 300. 70. 300. 120.
|
||||||
|
line 1 20 180. 70. 180. 120.
|
||||||
|
line 1 20 580. 30. 300. 120.
|
||||||
|
|
||||||
|
line 1 20 300. 120. 180. 120.
|
||||||
|
line 1 20 180. 120. 120. 120.
|
||||||
|
line 1 20 120. 120. 120. 240.
|
||||||
|
line 1 20 120. 240. 300. 120.
|
||||||
|
|
||||||
|
line 1 20 210. 240. 120. 240.
|
||||||
|
line 1 20 300. 180. 210. 240.
|
||||||
|
line 1 20 300. 120. 300. 180.
|
||||||
|
line 1 20 300. 180. 500. 280.
|
||||||
|
|
||||||
|
line 1 20 120. 240. 160. 280.
|
||||||
|
line 1 20 100. 280. 120. 240.
|
||||||
|
line 1 20 20. 240. 120. 240.
|
||||||
|
line 1 20 20. 40. 120. 240.
|
||||||
|
|
||||||
|
line 1 20 120. 240. 120. 280.
|
||||||
|
line 1 20 120. 120. 20. 40.
|
||||||
|
wp 20
|
||||||
|
0 304. 67.
|
||||||
|
1 176. 70.
|
||||||
|
2 108. 16.
|
||||||
|
3 300. 20.
|
||||||
|
|
||||||
|
4 180. 20.
|
||||||
|
5 300. 116.
|
||||||
|
6 180. 116.
|
||||||
|
7 304. 118.
|
||||||
|
|
||||||
|
9 124. 120.
|
||||||
|
10 210. 236.
|
||||||
|
11 297. 122.
|
||||||
|
12 124. 240.
|
||||||
|
|
||||||
|
14 300. 176.
|
||||||
|
15 490. 275.
|
||||||
|
16 155. 275.
|
||||||
|
17 118. 244.
|
||||||
|
|
||||||
|
18 116. 240.
|
||||||
|
19 118. 236.
|
||||||
|
20 120. 270.
|
||||||
|
21 30. 48.
|
||||||
|
tl 2
|
||||||
|
5 295. 110. 5 3 5 8
|
||||||
|
11 285. 125. 5 3 5 13
|
||||||
|
st 2
|
||||||
|
5 0 300. 110.
|
||||||
|
11 1 285. 130.
|
||||||
|
end
|
||||||
8
assets/15.iti
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
go 20.
|
||||||
|
go 30.
|
||||||
|
go 10.
|
||||||
|
turn -15.
|
||||||
|
go 20.
|
||||||
|
turn 75.
|
||||||
|
stop 0.
|
||||||
|
|
||||||
47
assets/15.map
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
map "scade"
|
||||||
|
rd 22
|
||||||
|
line 1 30 20. 20. 70. 20.
|
||||||
|
arc 1 20 70. 80. 60. -90. 90.
|
||||||
|
arc 1 20 70. 200. 60. 270. 90.
|
||||||
|
line 1 30 70. 260. 200. 260.
|
||||||
|
|
||||||
|
line 1 30 200. 260. 300. 260.
|
||||||
|
line 1 30 200. 240. 300. 240.
|
||||||
|
arc 1 20 200. 210. 50. 180. 90.
|
||||||
|
arc 1 20 200. 210. 30. 180. 90.
|
||||||
|
|
||||||
|
line 1 30 150. 110. 150. 210.
|
||||||
|
line 1 30 170. 110. 170. 210.
|
||||||
|
arc 1 20 200. 110. 50. 270. 180.
|
||||||
|
arc 1 20 200. 110. 30. 270. 180.
|
||||||
|
|
||||||
|
line 1 30 250. 60. 200. 60.
|
||||||
|
line 1 30 250. 80. 200. 80.
|
||||||
|
|
||||||
|
arc 1 20 300. 210. 50. 90. 0.
|
||||||
|
arc 1 20 300. 210. 30. 90. 0.
|
||||||
|
line 1 30 350. 210. 413.3 20.
|
||||||
|
line 1 30 330. 210. 380. 60.
|
||||||
|
|
||||||
|
arc 1 30 350. 140. 120. 90. -50.
|
||||||
|
line 1 30 300. 260. 550. 260.
|
||||||
|
line 1 30 413.3 20. 550. 20.
|
||||||
|
line 1 30 470. 140. 550. 140.
|
||||||
|
|
||||||
|
wp 11
|
||||||
|
3 115. 260.
|
||||||
|
4 290. 260.
|
||||||
|
16 412.3 23.
|
||||||
|
17 372. 84.
|
||||||
|
|
||||||
|
18 469.9 142.5
|
||||||
|
18 434.85 56.15
|
||||||
|
19 305. 260.
|
||||||
|
19 359. 260.
|
||||||
|
|
||||||
|
19 520. 260.
|
||||||
|
20 520. 20.
|
||||||
|
21 520. 140.
|
||||||
|
tl 0
|
||||||
|
st 0
|
||||||
|
end
|
||||||
10
assets/16.iti
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
go 20.
|
||||||
|
turn -34.
|
||||||
|
go 30.
|
||||||
|
turn 146.
|
||||||
|
go 20.
|
||||||
|
turn -56.
|
||||||
|
go 30.
|
||||||
|
turn -34.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
15
assets/17.iti
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
go 20.
|
||||||
|
turn 47.
|
||||||
|
go 20.
|
||||||
|
turn -90.
|
||||||
|
go 20.
|
||||||
|
turn 90.
|
||||||
|
go 20.
|
||||||
|
turn 124.
|
||||||
|
go 30.
|
||||||
|
turn 124.
|
||||||
|
go 20.
|
||||||
|
turn -60.
|
||||||
|
go 30.
|
||||||
|
stop 0.
|
||||||
|
|
||||||
8
assets/18.iti
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
go 20.
|
||||||
|
turn -34.
|
||||||
|
go 30.
|
||||||
|
turn -146.
|
||||||
|
go 20.
|
||||||
|
turn -51.
|
||||||
|
go 20.
|
||||||
|
stop 0.
|
||||||
BIN
assets/b-00.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-01.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-02.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-03.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-04.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-05.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-06.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-07.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-08.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/b-09.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/collision.wav
Normal file
BIN
assets/ctl_10.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/ctl_11.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/ctl_12.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/ctl_13.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/ctl_14.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/direction.wav
Normal file
BIN
assets/exit.wav
Normal file
BIN
assets/game_10.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/game_11.bmp
Normal file
|
After Width: | Height: | Size: 696 KiB |
BIN
assets/game_12.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/game_13.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/game_14.bmp
Normal file
|
After Width: | Height: | Size: 703 KiB |
BIN
assets/light.wav
Normal file
BIN
assets/map_00_oneway_line.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_01_oneway_square.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_02_oneway_olympic.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_03_oneway_ea.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_04_olympic_cut.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_05_olympic_cut_tl.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_06_roundabout.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_07_roundabout_tl.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_08_nycity.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/map_09_paris.bmp
Normal file
|
After Width: | Height: | Size: 698 KiB |
BIN
assets/obst.bmp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
assets/orange.bmp
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
assets/speed.wav
Normal file
@@ -1,2 +0,0 @@
|
|||||||
Le [journal](journal.org) contient un bref résumé de notre progression à travers
|
|
||||||
les notes de cours, ainsi que quelques informations logistiques.
|
|
||||||
44
cours/audio/Makefile
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
HEPTC=heptc
|
||||||
|
HEPTLIB=$(shell heptc -where)
|
||||||
|
CC=gcc
|
||||||
|
CFLAGS=-g $(shell pkg-config --cflags --libs sdl2 sndfile) -I$(HEPTLIB)/c -lm
|
||||||
|
PYGMENTS=python -m pygments -x
|
||||||
|
|
||||||
|
TARGET=audio
|
||||||
|
SOURCES=audio_c/audio_types.c \
|
||||||
|
audio_c/audio.c \
|
||||||
|
buffer.c \
|
||||||
|
vcd_lib.c \
|
||||||
|
mathext.c \
|
||||||
|
vcd.c \
|
||||||
|
main.c
|
||||||
|
|
||||||
|
.PHONY: all clean test
|
||||||
|
|
||||||
|
all: $(TARGET) audio.html main.html
|
||||||
|
|
||||||
|
%.html: %.ept
|
||||||
|
$(PYGMENTS) -l ../../../notes/heptagon.py:HeptagonLexer -O full -o $@ $^
|
||||||
|
|
||||||
|
%.html: %.c
|
||||||
|
$(PYGMENTS) -O full -o $@ $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET) *.{epci,log,mls,obc,html} $(TARGET).{pdf,tex}
|
||||||
|
rm -rf audio_c
|
||||||
|
|
||||||
|
test: $(TARGET)
|
||||||
|
./$(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(SOURCES)
|
||||||
|
@pkg-config --exists sdl2 || \
|
||||||
|
( echo "La bibliothèque SDL2 est absente."; exit 1 )
|
||||||
|
@pkg-config --exists sndfile || \
|
||||||
|
( echo "La bibliothèque sndfile est absente."; exit 1 )
|
||||||
|
$(CC) $(CFLAGS) -o $@ -I audio_c -I. $^
|
||||||
|
|
||||||
|
audio_c/audio_types.c audio_c/audio.c: audio.ept main.c mathext.epci vcd.epci
|
||||||
|
$(HEPTC) -target c $<
|
||||||
|
|
||||||
|
%.epci: %.epi
|
||||||
|
$(HEPTC) $<
|
||||||
14
cours/audio/README.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Synthèse sonore élémentaire en Heptagon
|
||||||
|
|
||||||
|
Ce dossier contient quelques noeuds Heptagon élementaires qui produisent du son.
|
||||||
|
|
||||||
|
Il utilise les bibliothèques SDL2 et sndfile. Elles doivent être installées via
|
||||||
|
le gestionnaire de paquet de votre système d'exploitation (`apt-get` sous
|
||||||
|
GNU/Linux Debian ou Ubuntu, `pacman` sous Arch Linux, `brew` sous macOS, etc.).
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ make
|
||||||
|
$ ./audio
|
||||||
|
```
|
||||||
|
|
||||||
|
Pour essayer différents codes, il faut éditer le noeud `main` dans `audio.ept`.
|
||||||
515
cours/audio/audio.ept
Normal file
@@ -0,0 +1,515 @@
|
|||||||
|
(******************************************************************************)
|
||||||
|
(* SYNTHÈSE SONORE ÉLÉMENTAIRE EN HEPTAGON *)
|
||||||
|
(******************************************************************************)
|
||||||
|
|
||||||
|
(* Le but de ce fichier est de démontrer quelques techniques élémentaires de
|
||||||
|
génération de son en Heptagon, à travers de modestes expérimentations. Il n'a
|
||||||
|
bien sûr pas vocation à se substituer à un cours de traitement du signal ou
|
||||||
|
d'acoustique. En revanche, il peut facilement servir d'illustration de
|
||||||
|
diverses techniques de programmation en Heptagon. *)
|
||||||
|
|
||||||
|
(* Le flot d'échantillons sonores produits par ce programme synchrone est
|
||||||
|
branché à un petit bout de code C qui les envoie au système sonore de votre
|
||||||
|
système d'exploitation par le biais de la bibliothèque SDL2. Votre OS les
|
||||||
|
transmet à la carte son qui elle même les envoie à vos enceintes, casque ou
|
||||||
|
écouteurs. *)
|
||||||
|
|
||||||
|
(* Les langages synchrones ont été utilisés pour la synthèse sonore. Si ce sujet
|
||||||
|
vous intéresse, vous pouvez par exemple consulter la page du langage Faust, à
|
||||||
|
la syntaxe rudimentaire mais aux bibliothèques acoustiques, sonores et
|
||||||
|
musicales très développées : http://faust.grame.fr *)
|
||||||
|
|
||||||
|
(* On va utiliser une petite bibliothèque de composants mathématiques. Les
|
||||||
|
curieuses et curieux pourront aller voir mathext.epci. *)
|
||||||
|
|
||||||
|
open Mathext
|
||||||
|
|
||||||
|
(* Avant de commencer, on a besoin de quelques définitions et outils. *)
|
||||||
|
|
||||||
|
(* Le nombre d'échantillons, c'est à dire ici de pas synchrones, que le système
|
||||||
|
sonore va consommer une seconde. *)
|
||||||
|
|
||||||
|
const period : int = 44100
|
||||||
|
|
||||||
|
(* Un signal mono est un simple flot de nombres à virgule flottante. *)
|
||||||
|
|
||||||
|
type mono = float
|
||||||
|
|
||||||
|
(* Un signal stéréo fournit deux échantillons, gauche et droit, la carte son se
|
||||||
|
chargeant de les mixer pour donner l'impression d'un son 'surround'. *)
|
||||||
|
|
||||||
|
type stereo = { l : float; r : float }
|
||||||
|
|
||||||
|
(* Le signal constant silencieux. *)
|
||||||
|
|
||||||
|
const silence : stereo = { l = 0.0; r = 0.0 }
|
||||||
|
|
||||||
|
(* On peut dupliquer un signal mono pour obtenir un signal stéréo
|
||||||
|
inintéressant, les deux canaux portant la même valeur. *)
|
||||||
|
|
||||||
|
fun stereo_of_mono(a : mono) returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = { l = a; r = a }
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* On peut appliquer un gain à un signal stéréo, c'est à dire le multiplier par
|
||||||
|
un flottant pour l'amener à une amplitude différente. *)
|
||||||
|
|
||||||
|
fun stereo_gain(g : float; s : stereo) returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = { l = g *. s.l; r = g *. s.r };
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Étant donné deux signaux, on peut les combiner via leur somme. *)
|
||||||
|
|
||||||
|
fun stereo_sum(s1, s2 : stereo) returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = { l = s1.l +. s2.l; r = s1.r +. s2.r }
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Quand on utilise les deux fonctions qu'on vient de définir, gare à
|
||||||
|
l'amplitude en sortie ! Une amplitude trop élevée risque de dépasser la
|
||||||
|
capacité de votre carte son, enceintes ou écouteurs, ce qui cause un
|
||||||
|
phénomène de saturation : tous les échantillons d'amplitude trop élevée sont
|
||||||
|
écrasés sur l'amplitude maximale. *)
|
||||||
|
|
||||||
|
(* La fonction mix ci-dessous pallie le défaut de la fonction stereo_sum en
|
||||||
|
renormalisant le résultat. De plus, elle traite un tableau de signaux, et
|
||||||
|
donc moralement un nombre d'entrées arbitraires. *)
|
||||||
|
|
||||||
|
fun stereo_mix<<n : int>>(s : stereo^n) returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = stereo_gain(1.0 /. float(n), fold<<n>> stereo_sum(s, silence));
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* On peut commencer à écouter un peu de son, par exemple celui du silence. *)
|
||||||
|
|
||||||
|
node main0() returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = silence;
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Quid du noeud suivant ? *)
|
||||||
|
|
||||||
|
node cracks() returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = { l = 4200.0; r = 4200.0 };
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* On entendu un craquement, puis plus rien, puis un craquement lorsqu'on
|
||||||
|
interromp le programme. Pourquoi ?
|
||||||
|
|
||||||
|
Physiquement, le son est une vibration produit par une onde acoustique, c'est
|
||||||
|
à dire une oscillation de la pression de l'air. Autrement dit, il s'agit
|
||||||
|
d'une *variation*. Donc, le signal constant ne peut pas donner lieu à un son,
|
||||||
|
sauf au premier instant (passage de 0 à 4200) puis lorsqu'on interromp le
|
||||||
|
programme (passage de 4200 à 0).
|
||||||
|
|
||||||
|
Et si on essayait un signal qui varie ? Par exemple, un signal carré qui
|
||||||
|
passe de 1 à 0 toutes les demi-secondes. *)
|
||||||
|
|
||||||
|
node periodic(p : int) returns (o : int)
|
||||||
|
var n : int;
|
||||||
|
let
|
||||||
|
o = 0 fby (if n = p then 0 else n);
|
||||||
|
n = o + 1;
|
||||||
|
tel
|
||||||
|
|
||||||
|
node beats_1() returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = stereo_of_mono(if periodic(period) <= period / 2 then 1.0 else -. 1.0);
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* On obtient une série de battements simples. Faire en sorte que le canal droit
|
||||||
|
soit l'opposé du canal gauche produit un effet intéressant. *)
|
||||||
|
|
||||||
|
node beats_2() returns (o : stereo)
|
||||||
|
var l : float;
|
||||||
|
let
|
||||||
|
l = if periodic(period) <= period / 2 then 1.0 else -. 1.0;
|
||||||
|
o = { l = l; r = -. l };
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Essayons maintenant de générer un signal qui croît indéfiniment. *)
|
||||||
|
|
||||||
|
node fcnt(ini : float; step : float) returns (o : float)
|
||||||
|
let
|
||||||
|
o = ini fby (o +. step);
|
||||||
|
tel
|
||||||
|
|
||||||
|
node sawtooth_1() returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = stereo_of_mono(fcnt(0.0, 1.0));
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* On entend quelques craquements, puis plus rien. Normal : ce signal n'oscille
|
||||||
|
pas vraiment, ou du moins pas avant d'atteindre l'overflow. Pourquoi ne pas
|
||||||
|
tester un signal périodique en dents de scie, dans ce cas ? *)
|
||||||
|
|
||||||
|
node sawtooth_2() returns (o : stereo)
|
||||||
|
var t : float;
|
||||||
|
let
|
||||||
|
t = float(periodic(128));
|
||||||
|
o = stereo_of_mono(t);
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Tiens, un son à peu près constant ! Pas très harmonieux cependant. *)
|
||||||
|
|
||||||
|
(* Est-ce qu'appliquer un gain ferait une différence ? Pour bien observer la
|
||||||
|
différence, on n'a qu'à faire passer le gain de 0 à 1 à chaque seconde.
|
||||||
|
C'est très facile à programmer en Heptagon. *)
|
||||||
|
|
||||||
|
node sawtooth_3() returns (o : stereo)
|
||||||
|
var t : float; g : float;
|
||||||
|
let
|
||||||
|
t = float(periodic(128));
|
||||||
|
g = float(periodic(period)) /. float(period);
|
||||||
|
o = stereo_gain(g, stereo_of_mono(t));
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* On entend nettement le signal en dent de scie, avec un pic à la fin de la
|
||||||
|
seconde. De façon intéressante, si on augmente le gain, le son apparaît comme
|
||||||
|
plus pincé, un peu comme les notes d'une guitare. *)
|
||||||
|
|
||||||
|
node sawtooth_4() returns (o : stereo)
|
||||||
|
var t : float; g : float;
|
||||||
|
let
|
||||||
|
t = float(periodic(128));
|
||||||
|
g = 3.0 *. float(periodic(period)) /. float(period);
|
||||||
|
o = stereo_gain(g, stereo_of_mono(t));
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* En augmentant la période, les pics s'éloignent, en la diminuant, les
|
||||||
|
pics se rapprochent. *)
|
||||||
|
|
||||||
|
node period_per_sec(a : int) returns (o : float)
|
||||||
|
let
|
||||||
|
o = float(periodic(period / a)) /. float(period / a);
|
||||||
|
tel
|
||||||
|
|
||||||
|
node sawtooth_5() returns (o : stereo)
|
||||||
|
var t : float; g : float;
|
||||||
|
let
|
||||||
|
t = float(periodic(128));
|
||||||
|
g = period_per_sec(2);
|
||||||
|
o = stereo_gain(g, stereo_of_mono(t));
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* On peut aussi appliquer des gains différents sur le canal mono et stéréo. *)
|
||||||
|
|
||||||
|
node every_sec(s : int) returns (c : bool)
|
||||||
|
let
|
||||||
|
c = periodic(period * s) = ((- 1) fby 0);
|
||||||
|
tel
|
||||||
|
|
||||||
|
node sawtooth_6() returns (o : stereo)
|
||||||
|
var t : float; g1, g2 : float;
|
||||||
|
let
|
||||||
|
t = float(periodic(128));
|
||||||
|
o = { l = g1 *. t; r = g2 *. t };
|
||||||
|
automaton
|
||||||
|
state FastLeftSlowRight
|
||||||
|
do g1 = period_per_sec(1);
|
||||||
|
g2 = period_per_sec(8);
|
||||||
|
until every_sec(5) then SlowLeftFastRight
|
||||||
|
|
||||||
|
state SlowLeftFastRight
|
||||||
|
do g1 = period_per_sec(5);
|
||||||
|
g2 = period_per_sec(1);
|
||||||
|
until every_sec(5) then FastLeftSlowRight
|
||||||
|
end
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Tous ces sons ne sont pas très harmonieux. Peut-on en obtenir de plus purs ?
|
||||||
|
|
||||||
|
Le traitement du signal nous enseigne, via la théorie de la transformée de
|
||||||
|
Fourier, que tout signal raisonnablement régulier peut se décomposer en une
|
||||||
|
somme (infinie) de sinusoïde. Autrement dit, les signaux sinusoïdaux peuvent
|
||||||
|
servir de briques de base élémentaires mais universelles. Considérés comme
|
||||||
|
des signaux audio, ils forment des tons purs, élémentaires.
|
||||||
|
*)
|
||||||
|
|
||||||
|
node pure_tone(p : float) returns (o : float)
|
||||||
|
var t : float;
|
||||||
|
let
|
||||||
|
t = fcnt(0.0, 1.0);
|
||||||
|
o = sin(t *. (p /. float(period)) *. 2.0 *. Mathext.pi);
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Par exemple, la sinusoïde de fréquence 440.1 Hz, communément désignée sous le
|
||||||
|
nom de La 440, devrait vous être familière. *)
|
||||||
|
|
||||||
|
node main_pure_1() returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = stereo_of_mono(pure_tone(440.0));
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* En plus d'être la tonalité du téléphone, elle sert de référence pour
|
||||||
|
l'accordage des pianos, violons et d'autres instruments.
|
||||||
|
|
||||||
|
https://fr.wikipedia.org/wiki/La_440 *)
|
||||||
|
|
||||||
|
(* En mélangeant plusieurs sinusoïdes ensembles, on peut obtenir des effets
|
||||||
|
rétro assez amusants. *)
|
||||||
|
|
||||||
|
node some_pure_tone(p : float; i : int) returns (s : stereo)
|
||||||
|
let
|
||||||
|
s = stereo_gain(period_per_sec(i + 1), stereo_of_mono(pure_tone(p)));
|
||||||
|
tel
|
||||||
|
|
||||||
|
node oscillating_counter<<m : int>>(i : int) returns (last o : int = 0)
|
||||||
|
var step : int;
|
||||||
|
let
|
||||||
|
step = if every_sec(1) then 1 else 0;
|
||||||
|
automaton
|
||||||
|
state Init
|
||||||
|
do o = i
|
||||||
|
until true then Increase
|
||||||
|
|
||||||
|
state Increase
|
||||||
|
do o = last o + step
|
||||||
|
until o >= m then Decrease
|
||||||
|
|
||||||
|
state Decrease
|
||||||
|
do o = last o - step
|
||||||
|
until o <= 0 then Increase
|
||||||
|
end
|
||||||
|
tel
|
||||||
|
|
||||||
|
node main_pure_2() returns (o : stereo)
|
||||||
|
var periods : float^3; speeds : int^3;
|
||||||
|
let
|
||||||
|
periods = [440.0, 261.6256, 4186.009];
|
||||||
|
speeds = map<<3>>(oscillating_counter<<10>>)([1, 3, 7]);
|
||||||
|
o = stereo_mix<<3>>(map<<3>> some_pure_tone(periods, speeds));
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Enfin, les amatrices et amateurs de piano pourront trouver sur la page
|
||||||
|
|
||||||
|
https://en.wikipedia.org/wiki/Piano_key_frequencies
|
||||||
|
|
||||||
|
une formule associant une fréquence de sinusoïde à une note de piano. On peut
|
||||||
|
l'utiliser comme suit. *)
|
||||||
|
|
||||||
|
fun piano_freq_of_key(k : int) returns (f : float)
|
||||||
|
let
|
||||||
|
f = Mathext.pow(2.0, (Mathext.float(k) -. 49.0) /. 12.0) *. 440.0;
|
||||||
|
tel
|
||||||
|
|
||||||
|
node tone_of_piano_key(k : int) returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = stereo_of_mono(pure_tone(piano_freq_of_key(k)));
|
||||||
|
tel
|
||||||
|
|
||||||
|
node maintain(c : bool; x : int on c; ini : int) returns (o : int)
|
||||||
|
let
|
||||||
|
o = merge c x ((ini fby o) whenot c);
|
||||||
|
tel
|
||||||
|
|
||||||
|
node main_pure_3() returns (o : stereo)
|
||||||
|
var k : int; c : bool;
|
||||||
|
let
|
||||||
|
o = tone_of_piano_key(k);
|
||||||
|
k = maintain(c, 40 + periodic(53 - 40), 40);
|
||||||
|
c = periodic(period) = 0;
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* On peut essayer de programmer un piano midi. *)
|
||||||
|
|
||||||
|
(* Pour générer des transitions propres entre les notes, on a besoin de modifier
|
||||||
|
nos tons à travers une "enveloppe". La plus classique est l'enveloppe dite
|
||||||
|
"Attack-Decay-Sustain-Release", cf. Wikipédia.
|
||||||
|
|
||||||
|
https://en.wikipedia.org/wiki/Envelope_(music)#ADSR
|
||||||
|
|
||||||
|
Le noeud ci-dessous produit une telle enveloppe périodiquement, tous les t
|
||||||
|
instants. L'enveloppe prend la forme d'un gain entre 0 et 1.
|
||||||
|
|
||||||
|
Les paramètres a, d et s doivent-être tels que 0.0 < a + d + s < 1.0. Ils
|
||||||
|
expriment la fraction de t correspondant à chacune des quatre phases, la
|
||||||
|
phase d étant la fraction de t définie comme 1 - a - d - s.
|
||||||
|
|
||||||
|
Le paramètre s_level est le niveau de la phase S, entre 0 et 1 donc.
|
||||||
|
|
||||||
|
*)
|
||||||
|
|
||||||
|
node adsr_envelope(t : int; a, d, s : float; s_level : float)
|
||||||
|
returns (e : float)
|
||||||
|
var c, a_stop, d_stop, s_stop : int;
|
||||||
|
let
|
||||||
|
a_stop = int(float(t) *. a);
|
||||||
|
d_stop = a_stop + int(float(t) *. d);
|
||||||
|
s_stop = d_stop + int(float(t) *. s);
|
||||||
|
c = periodic(t);
|
||||||
|
automaton
|
||||||
|
state Attack
|
||||||
|
do e = float(c) /. float(a_stop);
|
||||||
|
unless c >= a_stop continue Decay
|
||||||
|
|
||||||
|
state Decay
|
||||||
|
var f : float;
|
||||||
|
do e = 1.0 -. (1.0 -. s_level) *. f;
|
||||||
|
f = float(c - a_stop) /. float(d_stop - a_stop);
|
||||||
|
unless c >= d_stop continue Sustain
|
||||||
|
|
||||||
|
state Sustain
|
||||||
|
do e = s_level;
|
||||||
|
unless c >= s_stop continue Release
|
||||||
|
|
||||||
|
state Release
|
||||||
|
do e = s_level *. (1.0 -. float(c - s_stop) /. float(t - s_stop));
|
||||||
|
until c + 1 >= t continue Attack
|
||||||
|
end
|
||||||
|
tel
|
||||||
|
|
||||||
|
node midi_piano<<n : int>>(keys : int^2^n; time : int^n) returns (o : stereo)
|
||||||
|
var i, j : int; next : bool; duree_mesure : int; e : float;
|
||||||
|
let
|
||||||
|
duree_mesure = 2 * period; (* 1 mesure = 8 noires = 4 sec à 120 BPM. *)
|
||||||
|
|
||||||
|
i = periodic(n);
|
||||||
|
j = maintain(next, i, 0);
|
||||||
|
o = stereo_gain(e, stereo_mix<<2>>(map<<2>> tone_of_piano_key(keys[>j<])));
|
||||||
|
e = adsr_envelope(duree_mesure / time[> j <], 0.3, 0.1, 0.4, 0.5);
|
||||||
|
|
||||||
|
automaton
|
||||||
|
state Next
|
||||||
|
do next = true
|
||||||
|
until true then Wait
|
||||||
|
|
||||||
|
state Wait
|
||||||
|
var c : int;
|
||||||
|
do next = false;
|
||||||
|
c = 0 fby (c + 1);
|
||||||
|
until c >= (duree_mesure / time[> j <]) then Next
|
||||||
|
end
|
||||||
|
tel
|
||||||
|
|
||||||
|
const num_keys : int = 82
|
||||||
|
|
||||||
|
node main_pure_4() returns (o : stereo)
|
||||||
|
var keys : int^2^num_keys; time : int^num_keys;
|
||||||
|
let
|
||||||
|
keys = [
|
||||||
|
[44, 00], [37, 00], [40, 00], [42, 00],
|
||||||
|
[44, 00], [37, 00], [40, 00], [42, 00],
|
||||||
|
[44, 00], [37, 00], [40, 00], [42, 00],
|
||||||
|
[44, 00], [37, 00], [40, 00], [42, 00],
|
||||||
|
[44, 00], [37, 00], [41, 00], [42, 00],
|
||||||
|
[44, 00], [37, 00], [41, 00], [42, 00],
|
||||||
|
[44, 00], [37, 00], [41, 00], [42, 00],
|
||||||
|
[44, 00], [37, 00], [41, 00], [42, 00],
|
||||||
|
|
||||||
|
[44, 00],
|
||||||
|
[37, 00],
|
||||||
|
[40, 37], [42, 00], [44, 00],
|
||||||
|
[37, 00], [40, 00], [42, 00],
|
||||||
|
|
||||||
|
[35, 39], [32, 00], [35, 00], [37, 00],
|
||||||
|
[39, 00], [32, 00], [35, 00], [37, 00],
|
||||||
|
[35, 39], [32, 00], [35, 00], [37, 00],
|
||||||
|
[39, 00], [32, 00], [35, 00],
|
||||||
|
|
||||||
|
[42, 00],
|
||||||
|
[35, 00],
|
||||||
|
[35, 40], [39, 00], [42, 00],
|
||||||
|
[35, 00], [40, 00], [39, 00],
|
||||||
|
[33, 37], [30, 00], [33, 00], [35, 00],
|
||||||
|
[33, 00], [30, 00], [33, 00], [35, 00],
|
||||||
|
[33, 37], [30, 00], [33, 00], [35, 00],
|
||||||
|
[37, 00], [30, 00], [33, 00],
|
||||||
|
|
||||||
|
[0, 0], [0, 0], [0, 0], [0, 0] (* silence *)
|
||||||
|
];
|
||||||
|
time = [
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
8, 8, 2,
|
||||||
|
2, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 4,
|
||||||
|
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
8, 8, 2,
|
||||||
|
2, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 8, 8,
|
||||||
|
4, 4, 4,
|
||||||
|
|
||||||
|
1, 1, 1, 1 (* silence *)
|
||||||
|
];
|
||||||
|
o = midi_piano<<num_keys>>(keys, time);
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Bonus : la méthode de Karplus-Strong pour la synthèse de son de guitare.
|
||||||
|
|
||||||
|
https://en.wikipedia.org/wiki/Karplus%E2%80%93Strong_string_synthesis
|
||||||
|
|
||||||
|
http://sites.music.columbia.edu/cmc/MusicAndComputers/chapter4/04_09.php
|
||||||
|
*)
|
||||||
|
|
||||||
|
node flip(i: int) returns (o: float)
|
||||||
|
let
|
||||||
|
o = if (i % 2 = 0) then 1.0 else -.1.0
|
||||||
|
tel
|
||||||
|
|
||||||
|
node karplus_strong<<l:int>>() returns (y : float)
|
||||||
|
var b : float^l; i: int;
|
||||||
|
let
|
||||||
|
i = 0 fby ((i+1) % l);
|
||||||
|
y = 0.5 *. (b[>i<] +. 0.0 fby y);
|
||||||
|
b = (mapi<<l>> flip ()) fby ([b with [i] = y]);
|
||||||
|
tel
|
||||||
|
|
||||||
|
node repeat<<n : int>>(x : stereo) returns (o : stereo)
|
||||||
|
var last t : stereo^n = silence^n;
|
||||||
|
let
|
||||||
|
automaton
|
||||||
|
state Fill
|
||||||
|
do o = x;
|
||||||
|
t = [ last t with [ periodic(n) ] = x ]
|
||||||
|
until periodic(n) = n - 1 then Repeat
|
||||||
|
|
||||||
|
state Repeat
|
||||||
|
do o = t[> periodic(n) <]
|
||||||
|
end
|
||||||
|
tel
|
||||||
|
|
||||||
|
node saturating_counter(max : int) returns (o : int)
|
||||||
|
var c : int;
|
||||||
|
let
|
||||||
|
c = 0 fby (c + 1);
|
||||||
|
o = if c < max then c else max;
|
||||||
|
tel
|
||||||
|
|
||||||
|
node main_kp() returns (o : stereo)
|
||||||
|
var s : stereo;
|
||||||
|
let
|
||||||
|
s = repeat<<period>>({ l = karplus_strong<<115>>();
|
||||||
|
r = karplus_strong<<55>>() });
|
||||||
|
o = stereo_gain(float(saturating_counter(5 * period)) /. float(5 * period),
|
||||||
|
s);
|
||||||
|
tel
|
||||||
|
|
||||||
|
(* Le noeud principal du programme. *)
|
||||||
|
|
||||||
|
(* Vous pouvez choisir un des noeuds principaux main_XXX écrits ci-dessus, ou
|
||||||
|
bien écrire le votre. *)
|
||||||
|
|
||||||
|
node main() returns (o : stereo)
|
||||||
|
let
|
||||||
|
o = main_pure_4();
|
||||||
|
tel
|
||||||
61
cours/audio/buffer.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define max(a, b) ((a) <= (b) ? (a) : (b))
|
||||||
|
|
||||||
|
void *malloc_checked(size_t size) {
|
||||||
|
void *result = malloc(size);
|
||||||
|
if (!result) {
|
||||||
|
perror("malloc()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strdup_checked(const char *s) {
|
||||||
|
char *result = strdup(s);
|
||||||
|
if (!result) {
|
||||||
|
perror("strdup()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_t *buffer_alloc(size_t initial_size) {
|
||||||
|
buffer_t *buff = malloc_checked(sizeof *buff);
|
||||||
|
buff->data = malloc_checked(initial_size * sizeof *buff->data);
|
||||||
|
buff->size = initial_size;
|
||||||
|
buff->occupancy = 0;
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void buffer_free(buffer_t *buffer) {
|
||||||
|
assert (buffer);
|
||||||
|
|
||||||
|
free(buffer->data);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void buffer_resize(buffer_t *buff, size_t new_size) {
|
||||||
|
assert (buff);
|
||||||
|
assert (new_size >= buff->size);
|
||||||
|
|
||||||
|
unsigned char *new_data = malloc_checked(new_size);
|
||||||
|
memcpy(new_data, buff->data, buff->occupancy);
|
||||||
|
free(buff->data);
|
||||||
|
buff->data = new_data;
|
||||||
|
buff->size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void buffer_write(buffer_t *buff, void *data, size_t data_size) {
|
||||||
|
assert (buff);
|
||||||
|
if (buff->occupancy + data_size > buff->size)
|
||||||
|
buffer_resize(buff, max(buff->size + data_size, 2 * buff->size));
|
||||||
|
memcpy(buff->data + buff->occupancy, data, data_size);
|
||||||
|
buff->occupancy += data_size;
|
||||||
|
}
|
||||||
27
cours/audio/buffer.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef BUFFER_H
|
||||||
|
#define BUFFER_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/* A simple type of append-only buffers. */
|
||||||
|
|
||||||
|
typedef struct buffer {
|
||||||
|
unsigned char *data;
|
||||||
|
size_t size;
|
||||||
|
size_t occupancy;
|
||||||
|
} buffer_t;
|
||||||
|
|
||||||
|
void *malloc_checked(size_t size);
|
||||||
|
char *strdup_checked(const char *);
|
||||||
|
|
||||||
|
buffer_t *buffer_alloc(size_t initial_size);
|
||||||
|
void buffer_free(buffer_t *buff);
|
||||||
|
|
||||||
|
void buffer_write(buffer_t *buff, void *data, size_t data_size);
|
||||||
|
|
||||||
|
#define buffer_foreach(ty, var, buffer) \
|
||||||
|
for (ty *var = (ty *)buffer->data; \
|
||||||
|
var < (ty *)(buffer->data + buffer->occupancy); \
|
||||||
|
var++)
|
||||||
|
|
||||||
|
#endif /* BUFFER_H */
|
||||||
52
cours/audio/hept_ffi.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef HEPT_FFI_H
|
||||||
|
#define HEPT_FFI_H
|
||||||
|
|
||||||
|
#define UNPAREN(...) __VA_ARGS__
|
||||||
|
|
||||||
|
#define DECLARE_HEPT_FUN(module, name, inputs, outputs) \
|
||||||
|
typedef struct { outputs; } module ## __ ## name ## _out; \
|
||||||
|
void module ## __ ## name ##_step(UNPAREN inputs, \
|
||||||
|
module ## __ ## name ## _out *)
|
||||||
|
|
||||||
|
#define DECLARE_HEPT_FUN_NULLARY(module, name, outputs) \
|
||||||
|
typedef struct { outputs; } module ## __ ## name ## _out; \
|
||||||
|
void module ## __ ## name ##_step(module ## __ ## name ## _out *)
|
||||||
|
|
||||||
|
#define DEFINE_HEPT_FUN(module, name, inputs) \
|
||||||
|
void module ## __ ## name ##_step(UNPAREN inputs, \
|
||||||
|
module ## __ ## name ## _out *out)
|
||||||
|
|
||||||
|
#define DEFINE_HEPT_FUN_NULLARY(module, name, inputs) \
|
||||||
|
void module ## __ ## name ##_step(module ## __ ## name ## _out *out)
|
||||||
|
|
||||||
|
#define DECLARE_HEPT_NODE(module, name, inputs, outputs, state) \
|
||||||
|
typedef struct { outputs; } module ## __ ## name ## _out; \
|
||||||
|
typedef struct { state; } module ## __ ## name ## _mem; \
|
||||||
|
void module ## __ ## name ##_step(UNPAREN inputs, \
|
||||||
|
module ## __ ## name ## _out *, \
|
||||||
|
module ## __ ## name ## _mem *); \
|
||||||
|
void module ## __ ## name ##_reset(module ## __ ## name ## _mem *)
|
||||||
|
|
||||||
|
#define DECLARE_HEPT_NODE_NULLARY(module, name, outputs, state) \
|
||||||
|
typedef struct { outputs; } module ## __ ## name ## _out; \
|
||||||
|
typedef struct { state; } module ## __ ## name ## _mem; \
|
||||||
|
void module ## __ ## name ##_step(module ## __ ## name ## _out *, \
|
||||||
|
module ## __ ## name ## _mem *); \
|
||||||
|
void module ## __ ## name ##_reset(module ## __ ## name ## _mem *)
|
||||||
|
|
||||||
|
#define DEFINE_HEPT_NODE_RESET(module, name) \
|
||||||
|
void module ## __ ## name ##_reset(module ## __ ## name ## _mem *mem)
|
||||||
|
|
||||||
|
#define DEFINE_HEPT_NODE_STEP(module, name, inputs) \
|
||||||
|
void module ## __ ## name ##_step(UNPAREN inputs, \
|
||||||
|
module ## __ ## name ## _out *out, \
|
||||||
|
module ## __ ## name ## _mem *mem)
|
||||||
|
|
||||||
|
#define DEFINE_HEPT_NODE_NULLARY_STEP(module, name, inputs) \
|
||||||
|
void module ## __ ## name ##_step(module ## __ ## name ## _out *out, \
|
||||||
|
module ## __ ## name ## _mem *mem)
|
||||||
|
|
||||||
|
/* FIXME remove when Heptagon's pervasives.h has been fixed. */
|
||||||
|
typedef char * string;
|
||||||
|
|
||||||
|
#endif /* HEPT_FFI */
|
||||||
153
cours/audio/main.c
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <sndfile.h>
|
||||||
|
|
||||||
|
#include "audio.h"
|
||||||
|
#include "vcd.h"
|
||||||
|
|
||||||
|
const size_t sample_rate = Audio__period;
|
||||||
|
|
||||||
|
void die(const char *message) {
|
||||||
|
fprintf(stderr, message);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SNDFILE *file_out = NULL;
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
Audio__main_mem mem;
|
||||||
|
Audio__main_out res;
|
||||||
|
SDL_AudioSpec spec;
|
||||||
|
SDL_AudioDeviceID dev;
|
||||||
|
int opt = -1;
|
||||||
|
bool quiet = false;
|
||||||
|
size_t max_sec = SIZE_MAX; /* largest value of type size_t */
|
||||||
|
const char *filename = NULL;
|
||||||
|
Uint32 buffered;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "ho:qm:t:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'h':
|
||||||
|
printf("Usage: %s OPTIONS\n", argv[0]);
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" -o <file.wav> write samples to <file.wav>\n");
|
||||||
|
printf(" -q do not play sound\n");
|
||||||
|
printf(" -m <sec> play for <sec> seconds\n");
|
||||||
|
printf(" -t <file.vcd> dump traces in <file.vcd>\n");
|
||||||
|
printf(" -h display this message\n");
|
||||||
|
return 0;
|
||||||
|
case 'q':
|
||||||
|
quiet = true;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
max_sec = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
hept_vcd_init(optarg, VCD_TIME_UNIT_US, 20);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown option '%c'\n", opt);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_Init(SDL_INIT_AUDIO) < 0)
|
||||||
|
die("Could not initialize SDL2\n");
|
||||||
|
|
||||||
|
/* Specification of requested output device. */
|
||||||
|
bzero(&spec, sizeof spec);
|
||||||
|
spec.freq = sample_rate; /* Samples per second */
|
||||||
|
spec.format = AUDIO_F32; /* Sample format: IEEE-754 32 bits */
|
||||||
|
spec.channels = 2; /* Two channels */
|
||||||
|
spec.samples = 4096; /* Buffers sized 4 KiB */
|
||||||
|
spec.callback = NULL;
|
||||||
|
|
||||||
|
if (!(dev = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0)))
|
||||||
|
die("Could not open audio device\n");
|
||||||
|
|
||||||
|
if (filename != NULL) {
|
||||||
|
/* Specification of requested output file, if any. */
|
||||||
|
SF_INFO info_out;
|
||||||
|
bzero(&info_out, sizeof info_out);
|
||||||
|
info_out.channels = 2; /* Two channels */
|
||||||
|
info_out.samplerate = sample_rate; /* Samples per second */
|
||||||
|
info_out.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; /* File format */
|
||||||
|
|
||||||
|
if (!(file_out = sf_open(filename, SFM_WRITE, &info_out))) {
|
||||||
|
fprintf(stderr, "Could not open WAV file %s for writing\n", argv[1]);
|
||||||
|
SDL_Quit();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Audio__main_reset(&mem);
|
||||||
|
float *buffer = calloc(spec.samples, sizeof *buffer);
|
||||||
|
SDL_PauseAudioDevice(dev, 0);
|
||||||
|
|
||||||
|
/* Loop until we've produced the requested amount of samples, that is the
|
||||||
|
duration in seconds multiplied by the number of samples per second. This
|
||||||
|
number of samples shall be sent on each of both stereo channels.
|
||||||
|
|
||||||
|
Each iteration sends spec.samples stereo samples to the audio device,
|
||||||
|
hence we halve it to get the number of generated samples per-channel. */
|
||||||
|
for (size_t samples = 0;
|
||||||
|
samples < max_sec * sample_rate;
|
||||||
|
samples += spec.samples / 2) {
|
||||||
|
|
||||||
|
/* Print sound progress. */
|
||||||
|
printf("\rSent %08zu samples", samples);
|
||||||
|
if (max_sec != SIZE_MAX) {
|
||||||
|
printf(" (%2.0f%)", 100. * (double)samples / (max_sec * sample_rate));
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Exit immediately if requested, e.g., the user pressed Ctrl-C. */
|
||||||
|
if (SDL_QuitRequested()) {
|
||||||
|
printf("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step the node as much as necessary to fill a buffer. Each step produces
|
||||||
|
one stereo sample. */
|
||||||
|
for (size_t i = 0; i < spec.samples; i += 2) {
|
||||||
|
Audio__main_step(&res, &mem);
|
||||||
|
buffer[i+0] = res.o.l;
|
||||||
|
buffer[i+1] = res.o.r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the generated sound to the sound card and/or file. */
|
||||||
|
if (!quiet)
|
||||||
|
SDL_QueueAudio(dev, buffer, spec.samples * sizeof *buffer);
|
||||||
|
if (file_out)
|
||||||
|
sf_writef_float(file_out, buffer, spec.samples / 2);
|
||||||
|
|
||||||
|
/* Throttle queued audio, otherwise we will certainly end up consuming all
|
||||||
|
available memory. */
|
||||||
|
buffered = SDL_GetQueuedAudioSize(dev);
|
||||||
|
while (!quiet && buffered >= 1 << 22) {
|
||||||
|
SDL_Delay(50);
|
||||||
|
buffered = SDL_GetQueuedAudioSize(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
/* Wait until the audio buffer is empty. */
|
||||||
|
printf("Waiting for queue flush... "); fflush(stdout);
|
||||||
|
while ((buffered = SDL_GetQueuedAudioSize(dev)) != 0)
|
||||||
|
SDL_Delay(50);
|
||||||
|
printf("done.\n");
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
if (file_out)
|
||||||
|
sf_close(file_out);
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
55
cours/audio/mathext.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Avoid Heptagon's math.h. I don't think there's a single place where to find
|
||||||
|
math.h on Apple-platforms. */
|
||||||
|
#ifndef __APPLE__
|
||||||
|
#include </usr/include/math.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mathext.h"
|
||||||
|
|
||||||
|
void Mathext__float_step(int x, Mathext__float_out *o) {
|
||||||
|
o->o = (float)x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__int_step(float x, Mathext__int_out *o) {
|
||||||
|
o->o = (int)x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__floor_step(float x, Mathext__floor_out *o) {
|
||||||
|
o->o = floorf(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__sin_step(float x, Mathext__sin_out *o) {
|
||||||
|
o->o = sinf(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__cos_step(float x, Mathext__cos_out *o) {
|
||||||
|
o->o = cosf(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__atan2_step(float y, float x, Mathext__atan2_out *o) {
|
||||||
|
o->o = atan2f(y, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__pow_step(float x, float y, Mathext__pow_out *o) {
|
||||||
|
o->o = powf(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__hypot_step(float x, float y, Mathext__hypot_out *o) {
|
||||||
|
o->o = hypotf(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__sqrt_step(float x2, Mathext__sqrt_out *o) {
|
||||||
|
o->o = sqrtf(x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__modulo_step(int x, int y, Mathext__modulo_out *o) {
|
||||||
|
o->o = x % y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mathext__piano_freq_of_key_step(int n, Mathext__piano_freq_of_key_out *o) {
|
||||||
|
o->f = (float)(pow(2, (float)(n - 49) / (float)12) * 440.);
|
||||||
|
}
|
||||||
16
cours/audio/mathext.epi
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
external fun float(x : int) returns (o : float)
|
||||||
|
external fun int(x : float) returns (o : int)
|
||||||
|
external fun floor(x : float) returns (o : float)
|
||||||
|
|
||||||
|
external fun sin(x : float) returns (o : float)
|
||||||
|
external fun cos(x : float) returns (o : float)
|
||||||
|
external fun atan2(y : float; x : float) returns (o : float)
|
||||||
|
external fun hypot(x : float; y : float) returns (o : float)
|
||||||
|
external fun sqrt(x2 : float) returns (o : float)
|
||||||
|
external fun pow(x : float; y : float) returns (o : float)
|
||||||
|
|
||||||
|
external fun modulo(x : int; y : int) returns (o : int)
|
||||||
|
|
||||||
|
external fun piano_freq_of_key(k : int) returns (f : float)
|
||||||
|
|
||||||
|
const pi : float = 3.14115
|
||||||
27
cours/audio/mathext.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef MATHEXT_H
|
||||||
|
#define MATHEXT_H
|
||||||
|
|
||||||
|
#include "stdbool.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "pervasives.h"
|
||||||
|
|
||||||
|
#include "hept_ffi.h"
|
||||||
|
|
||||||
|
DECLARE_HEPT_FUN(Mathext, float, (int), float o);
|
||||||
|
DECLARE_HEPT_FUN(Mathext, int, (float), int o);
|
||||||
|
DECLARE_HEPT_FUN(Mathext, floor, (float), float o);
|
||||||
|
|
||||||
|
DECLARE_HEPT_FUN(Mathext, sin, (float), float o);
|
||||||
|
DECLARE_HEPT_FUN(Mathext, cos, (float), float o);
|
||||||
|
DECLARE_HEPT_FUN(Mathext, atan2, (float, float), float o);
|
||||||
|
DECLARE_HEPT_FUN(Mathext, hypot, (float, float), float o);
|
||||||
|
DECLARE_HEPT_FUN(Mathext, sqrt, (float), float o);
|
||||||
|
DECLARE_HEPT_FUN(Mathext, pow, (float, float), float o);
|
||||||
|
|
||||||
|
DECLARE_HEPT_FUN(Mathext, modulo, (int, int), int o);
|
||||||
|
|
||||||
|
DECLARE_HEPT_FUN(Mathext, piano_freq_of_key, (int), float f);
|
||||||
|
|
||||||
|
static const float Mathext__pi = 3.14115;
|
||||||
|
|
||||||
|
#endif /* MATHEXT_H */
|
||||||
4
cours/audio/mathext_types.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef MATHEXT_TYPES_H
|
||||||
|
#define MATHEXT_TYPES_H
|
||||||
|
|
||||||
|
#endif /* MATHEXT_TYPES_H */
|
||||||
75
cours/audio/vcd.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#include "vcd.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "vcd_lib.h"
|
||||||
|
|
||||||
|
vcd_file_t *vcd = NULL;
|
||||||
|
|
||||||
|
bool enabled = false;
|
||||||
|
|
||||||
|
void hept_vcd_cleanup() {
|
||||||
|
if (vcd) {
|
||||||
|
printf("[vcd] saving trace\n");
|
||||||
|
vcd_file_write(vcd);
|
||||||
|
vcd_file_free(vcd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hept_vcd_init(const char *filename,
|
||||||
|
size_t time_number,
|
||||||
|
vcd_time_unit_t unit) {
|
||||||
|
if (vcd) {
|
||||||
|
fprintf(stderr, "[vcd] initialization has already been performed\n");
|
||||||
|
} else {
|
||||||
|
vcd = vcd_file_alloc(filename, time_number, unit);
|
||||||
|
assert (vcd);
|
||||||
|
if (atexit(hept_vcd_cleanup)) {
|
||||||
|
perror("[vcd] atexit() failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf("[vcd] will save trace to %s\n", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void trace_samples(vcd_signal_t **signal,
|
||||||
|
const char *name, vcd_signal_type_t type,
|
||||||
|
void *samples, size_t count) {
|
||||||
|
if (!vcd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!*signal) {
|
||||||
|
*signal = vcd_signal_alloc(name, type, 1 << 17);
|
||||||
|
if (!vcd_file_add_signal(vcd, *signal)) {
|
||||||
|
perror("vcd_file_add_signal()\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vcd_add_samples(*signal, samples, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HEPT_NODE_RESET(Vcd, trace_bool) {
|
||||||
|
mem->signal = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HEPT_NODE_STEP(Vcd, trace_bool, (string name, int v)) {
|
||||||
|
trace_samples(&mem->signal, name, VCD_SIGNAL_TYPE_BOOL, &v, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HEPT_NODE_RESET(Vcd, trace_int) {
|
||||||
|
mem->signal = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HEPT_NODE_STEP(Vcd, trace_int, (string name, int v)) {
|
||||||
|
trace_samples(&mem->signal, name, VCD_SIGNAL_TYPE_INT, &v, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HEPT_NODE_RESET(Vcd, trace_float) {
|
||||||
|
mem->signal = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HEPT_NODE_STEP(Vcd, trace_float, (string name, float v)) {
|
||||||
|
trace_samples(&mem->signal, name, VCD_SIGNAL_TYPE_FLOAT, &v, 1);
|
||||||
|
}
|
||||||
6
cours/audio/vcd.epi
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
(* A basic library for producing VCD files from Heptagon code, typically used
|
||||||
|
for debugging purposes. *)
|
||||||
|
|
||||||
|
external node trace_bool(name : string; v : bool) returns ()
|
||||||
|
external node trace_int(name : string; v : int) returns ()
|
||||||
|
external node trace_float(name : string; v : float) returns ()
|
||||||
18
cours/audio/vcd.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef VCD
|
||||||
|
#define VCD
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "hept_ffi.h"
|
||||||
|
#include "vcd_lib.h"
|
||||||
|
|
||||||
|
void hept_vcd_init(const char *filename,
|
||||||
|
size_t time_number,
|
||||||
|
vcd_time_unit_t unit);
|
||||||
|
|
||||||
|
DECLARE_HEPT_NODE(Vcd, trace_bool, (string, int),, vcd_signal_t *signal);
|
||||||
|
DECLARE_HEPT_NODE(Vcd, trace_int, (string, int),, vcd_signal_t *signal);
|
||||||
|
DECLARE_HEPT_NODE(Vcd, trace_float, (string, float),, vcd_signal_t *signal);
|
||||||
|
|
||||||
|
#endif /* VCD */
|
||||||
198
cours/audio/vcd_lib.c
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
#include "vcd_lib.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
size_t vcd_sizeof_signal_type(vcd_signal_type_t type) {
|
||||||
|
switch (type) {
|
||||||
|
case VCD_SIGNAL_TYPE_BOOL:
|
||||||
|
return sizeof(int);
|
||||||
|
case VCD_SIGNAL_TYPE_INT:
|
||||||
|
return sizeof(int);
|
||||||
|
case VCD_SIGNAL_TYPE_FLOAT:
|
||||||
|
return sizeof(float);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct vcd_signal {
|
||||||
|
char *name;
|
||||||
|
vcd_signal_type_t type;
|
||||||
|
buffer_t *samples;
|
||||||
|
} vcd_signal_t;
|
||||||
|
|
||||||
|
vcd_signal_t *vcd_signal_alloc(const char *name,
|
||||||
|
vcd_signal_type_t type,
|
||||||
|
size_t initial_buffer_size) {
|
||||||
|
vcd_signal_t *res = malloc_checked(sizeof *res);
|
||||||
|
res->name = strdup_checked(name);
|
||||||
|
res->type = type;
|
||||||
|
res->samples =
|
||||||
|
buffer_alloc(initial_buffer_size * vcd_sizeof_signal_type(type));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vcd_signal_free(vcd_signal_t *signal) {
|
||||||
|
assert (signal);
|
||||||
|
|
||||||
|
buffer_free(signal->samples);
|
||||||
|
free(signal->name);
|
||||||
|
free(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vcd_add_samples(vcd_signal_t *signal, void *samples, size_t count) {
|
||||||
|
assert (signal);
|
||||||
|
assert (samples);
|
||||||
|
buffer_write(signal->samples,
|
||||||
|
samples,
|
||||||
|
count * vcd_sizeof_signal_type(signal->type));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *vcd_time_unit_repr(vcd_time_unit_t u) {
|
||||||
|
const char *table[] = { "s", "ms", "us", "ns", "ps", "fs" };
|
||||||
|
assert (VCD_TIME_UNIT_S <= u && u <= VCD_TIME_UNIT_FS);
|
||||||
|
return table[u];
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct vcd_file {
|
||||||
|
char *filename;
|
||||||
|
buffer_t *signals;
|
||||||
|
vcd_time_unit_t time_unit;
|
||||||
|
size_t time_unit_factor;
|
||||||
|
} vcd_file_t;
|
||||||
|
|
||||||
|
vcd_file_t *vcd_file_alloc(const char *filename,
|
||||||
|
vcd_time_unit_t time_unit,
|
||||||
|
size_t time_unit_factor) {
|
||||||
|
assert (filename);
|
||||||
|
|
||||||
|
vcd_file_t *vcd = malloc_checked(sizeof *vcd);
|
||||||
|
vcd->filename = strdup_checked(filename);
|
||||||
|
vcd->time_unit = time_unit;
|
||||||
|
vcd->time_unit_factor = time_unit_factor;
|
||||||
|
vcd->signals = buffer_alloc(10 * sizeof(vcd_signal_t));
|
||||||
|
|
||||||
|
return vcd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vcd_file_free(vcd_file_t *vcd) {
|
||||||
|
assert (vcd);
|
||||||
|
|
||||||
|
/* Free buffers. */
|
||||||
|
buffer_foreach (vcd_signal_t *, psig, vcd->signals)
|
||||||
|
vcd_signal_free(*psig);
|
||||||
|
buffer_free(vcd->signals);
|
||||||
|
|
||||||
|
free(vcd->filename);
|
||||||
|
free(vcd);
|
||||||
|
}
|
||||||
|
|
||||||
|
vcd_signal_t *vcd_file_lookup_signal(const vcd_file_t *vcd, const char *name) {
|
||||||
|
assert (vcd);
|
||||||
|
assert (name);
|
||||||
|
|
||||||
|
vcd_signal_t *res = NULL;
|
||||||
|
|
||||||
|
buffer_foreach (vcd_signal_t *, psig, vcd->signals) {
|
||||||
|
if (strcmp((*psig)->name, name) == 0) {
|
||||||
|
res = *psig;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vcd_file_add_signal(const vcd_file_t *vcd, vcd_signal_t *signal) {
|
||||||
|
assert (vcd);
|
||||||
|
assert (signal);
|
||||||
|
|
||||||
|
if (vcd_file_lookup_signal(vcd, signal->name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
buffer_write(vcd->signals, &signal, sizeof signal);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vcd_file_write(vcd_file_t *vcd) {
|
||||||
|
FILE *f = fopen(vcd->filename, "w");
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
time_t current_time;
|
||||||
|
time(¤t_time);
|
||||||
|
|
||||||
|
fprintf(f, "$version Generated by vcd.c $end\n");
|
||||||
|
fprintf(f, "$date %s $end\n", ctime(¤t_time));
|
||||||
|
fprintf(f, "$timescale %zu %s $end\n",
|
||||||
|
vcd->time_unit_factor,
|
||||||
|
vcd_time_unit_repr(vcd->time_unit));
|
||||||
|
|
||||||
|
/* Dump signal declarations. */
|
||||||
|
fprintf(f, "$scope module Top $end\n");
|
||||||
|
buffer_foreach (vcd_signal_t *, psig, vcd->signals) {
|
||||||
|
fprintf(f, "$var ");
|
||||||
|
switch ((*psig)->type) {
|
||||||
|
case VCD_SIGNAL_TYPE_BOOL:
|
||||||
|
fprintf(f, "wire 1");
|
||||||
|
break;
|
||||||
|
case VCD_SIGNAL_TYPE_INT:
|
||||||
|
fprintf(f, "integer %zu", 8 * sizeof(int));
|
||||||
|
break;
|
||||||
|
case VCD_SIGNAL_TYPE_FLOAT:
|
||||||
|
fprintf(f, "real 32");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(f, " %p %s $end\n", (*psig), (*psig)->name);
|
||||||
|
}
|
||||||
|
fprintf(f, "$upscope $end\n");
|
||||||
|
fprintf(f, "$enddefinitions\n");
|
||||||
|
|
||||||
|
/* Dump samples. */
|
||||||
|
fprintf(f, "$dumpvars\n");
|
||||||
|
|
||||||
|
/* We maintain a pointer to the current sample in each buffer. */
|
||||||
|
size_t signal_count = vcd->signals->occupancy / sizeof(vcd_signal_t *);
|
||||||
|
unsigned char **psamples = calloc(signal_count, sizeof(unsigned char *));
|
||||||
|
assert (psamples);
|
||||||
|
for (size_t i = 0; i < signal_count; i++)
|
||||||
|
psamples[i] = ((vcd_signal_t **)vcd->signals->data)[i]->samples->data;
|
||||||
|
|
||||||
|
/* We dump */
|
||||||
|
bool active = true;
|
||||||
|
for (size_t step = 0; active; step++) {
|
||||||
|
fprintf(f, "#%zu\n", step);
|
||||||
|
active = false;
|
||||||
|
for (size_t i = 0; i < signal_count; i++) {
|
||||||
|
vcd_signal_t *sig = ((vcd_signal_t **)vcd->signals->data)[i];
|
||||||
|
if (psamples[i] < sig->samples->data + sig->samples->occupancy) {
|
||||||
|
active = true;
|
||||||
|
switch (sig->type) {
|
||||||
|
case VCD_SIGNAL_TYPE_BOOL:
|
||||||
|
fprintf(f, "%d%p\n", (*(int *)psamples[i] ? 1 : 0), sig);
|
||||||
|
psamples[i] += sizeof(int);
|
||||||
|
break;
|
||||||
|
case VCD_SIGNAL_TYPE_INT:
|
||||||
|
fprintf(f, "r%d %p\n", *(int *)psamples, sig);
|
||||||
|
psamples[i] += sizeof(int);
|
||||||
|
break;
|
||||||
|
case VCD_SIGNAL_TYPE_FLOAT:
|
||||||
|
fprintf(f, "r%.16g %p\n", *(float *)psamples, sig);
|
||||||
|
psamples[i] += sizeof(float);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(psamples);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
47
cours/audio/vcd_lib.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef VCD_LIB_H
|
||||||
|
#define VCD_LIB_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef enum vcd_signal_type {
|
||||||
|
VCD_SIGNAL_TYPE_FLOAT,
|
||||||
|
VCD_SIGNAL_TYPE_INT,
|
||||||
|
VCD_SIGNAL_TYPE_BOOL
|
||||||
|
} vcd_signal_type_t;
|
||||||
|
|
||||||
|
size_t vcd_sizeof_signal_type(vcd_signal_type_t);
|
||||||
|
|
||||||
|
typedef struct vcd_signal vcd_signal_t;
|
||||||
|
|
||||||
|
vcd_signal_t *vcd_signal_alloc(const char *name,
|
||||||
|
vcd_signal_type_t type,
|
||||||
|
size_t initial_buffer_size);
|
||||||
|
void vcd_signal_free(vcd_signal_t *signal);
|
||||||
|
|
||||||
|
void vcd_add_samples(vcd_signal_t *signal, void *samples, size_t count);
|
||||||
|
|
||||||
|
typedef enum vcd_time_unit {
|
||||||
|
VCD_TIME_UNIT_S,
|
||||||
|
VCD_TIME_UNIT_MS,
|
||||||
|
VCD_TIME_UNIT_US,
|
||||||
|
VCD_TIME_UNIT_NS,
|
||||||
|
VCD_TIME_UNIT_PS,
|
||||||
|
VCD_TIME_UNIT_FS,
|
||||||
|
} vcd_time_unit_t;
|
||||||
|
|
||||||
|
const char *vcd_time_unit_repr(vcd_time_unit_t);
|
||||||
|
|
||||||
|
typedef struct vcd_file vcd_file_t;
|
||||||
|
|
||||||
|
vcd_file_t *vcd_file_alloc(const char *filename,
|
||||||
|
vcd_time_unit_t time_unit,
|
||||||
|
size_t time_unit_factor);
|
||||||
|
void vcd_file_free(vcd_file_t *);
|
||||||
|
|
||||||
|
vcd_signal_t *vcd_file_lookup_signal(const vcd_file_t *vcd, const char *name);
|
||||||
|
bool vcd_file_add_signal(const vcd_file_t *vcd, vcd_signal_t *signal);
|
||||||
|
|
||||||
|
bool vcd_file_write(vcd_file_t *);
|
||||||
|
|
||||||
|
#endif /* VCD_LIB_H */
|
||||||
4
cours/audio/vcd_types.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef VCD_TYPES
|
||||||
|
#define VCD_TYPES
|
||||||
|
|
||||||
|
#endif /* VCD_TYPES */
|
||||||
62
cours/inverted-pendulum/Makefile
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
HEPTC=heptc
|
||||||
|
PYGMENTS=python -m pygments -x -l ../../../notes/heptagon.py:HeptagonLexer
|
||||||
|
|
||||||
|
HEPT_NAME=pendulum
|
||||||
|
|
||||||
|
HEPT_SOURCES=$(HEPT_NAME).ept
|
||||||
|
HEPT_GENERATED=\
|
||||||
|
$(HEPT_NAME)_types.h \
|
||||||
|
$(HEPT_NAME).h \
|
||||||
|
$(HEPT_NAME)_types.c \
|
||||||
|
$(HEPT_NAME).c
|
||||||
|
C_SOURCES=mathext.c
|
||||||
|
|
||||||
|
SWIG_SOURCE=$(HEPT_NAME).i
|
||||||
|
SWIG_GENERATED=$(HEPT_NAME).py $(HEPT_NAME)_wrap.c
|
||||||
|
|
||||||
|
PY_SUFFIX=$(shell python -c \
|
||||||
|
"import sysconfig as s; print(s.get_config_var('EXT_SUFFIX'))")
|
||||||
|
TARGET?=_$(HEPT_NAME)$(PY_SUFFIX)
|
||||||
|
|
||||||
|
HTML=pendulum.html
|
||||||
|
|
||||||
|
.PHONY: all clean run runplot repl
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.epci *.log *.mls *.obc *.epci *.epo
|
||||||
|
rm -f $(SWIG_GENERATED) $(HEPT_GENERATED)
|
||||||
|
rm -rf $(HEPT_NAME)_c build __pycache__ *.so
|
||||||
|
rm -f $(HTML)
|
||||||
|
|
||||||
|
repl: all
|
||||||
|
python -i -c 'import $(HEPT_NAME)'
|
||||||
|
|
||||||
|
run: all
|
||||||
|
./main.py
|
||||||
|
|
||||||
|
runplot: all
|
||||||
|
./main.py --plot
|
||||||
|
|
||||||
|
%.html: %.ept
|
||||||
|
$(PYGMENTS) -O full -o $@ $^
|
||||||
|
|
||||||
|
$(TARGET): $(SWIG_GENERATED) $(HEPT_GENERATED) $(C_SOURCES)
|
||||||
|
python setup.py build_ext --inplace
|
||||||
|
@echo $@
|
||||||
|
|
||||||
|
$(SWIG_GENERATED): $(SWIG_SOURCE) $(HEPT_GENERATED) $(C_SOURCES)
|
||||||
|
swig -python $<
|
||||||
|
|
||||||
|
%_types.h %_types.c %.c %.h %.epci : %.ept
|
||||||
|
$(HEPTC) -c -target c $<
|
||||||
|
cp $(foreach ext,c h,$(basename $<)_c/*.$(ext)) .
|
||||||
|
|
||||||
|
%.epci: %.epi
|
||||||
|
$(HEPTC) $<
|
||||||
|
|
||||||
|
$(HEPT_SOURCES): mathext.epci debug.epci
|
||||||
|
|
||||||
|
%.html: %.ept
|
||||||
|
$(PYGMENTS) -O full -o $@ $^
|
||||||
43
cours/inverted-pendulum/README.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Pendule inversé et contrôleur PID
|
||||||
|
|
||||||
|
## Présentation
|
||||||
|
|
||||||
|
Ce dossier contient un exemple classique de système physique qu'on peut chercher
|
||||||
|
à contrôler, le pendule inversé.
|
||||||
|
|
||||||
|
## Dépendances
|
||||||
|
|
||||||
|
Le projet utilise du code Python 3, et le générateur d'interfaces SWIG pour
|
||||||
|
exposer le code C généré par Heptagon à Python. Pour le lancer, vous devez :
|
||||||
|
|
||||||
|
- avoir Heptagon, à installer via OPAM,
|
||||||
|
|
||||||
|
- avoir SWIG, à installer via le gestionnaire de paquet de votre système
|
||||||
|
d'exploitation (`apt-get` sous GNU/Linux Debian ou Ubuntu, `pacman` sous Arch
|
||||||
|
Linux, `brew` sous macOS, etc.),
|
||||||
|
|
||||||
|
- avoir la bibliothèque Python `matplotlib`, à installer `pip install --user
|
||||||
|
matplotlib`.
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
Vous pouvez lancer le programme en exécutant `make run`.
|
||||||
|
|
||||||
|
Pour lancer le programme avec l'affichage des courbes, exécutez `make runplot`.
|
||||||
|
Attention : afficher les courbes engendre un ralentissement assez conséquent.
|
||||||
|
|
||||||
|
L'interface utilisateur fonctione de la façon suivante :
|
||||||
|
|
||||||
|
- **Q** permet de quitter,
|
||||||
|
|
||||||
|
- **P** permet de mettre en pause,
|
||||||
|
|
||||||
|
- **R** permet de réinitialiser la simulation,
|
||||||
|
|
||||||
|
- **M** permet de changer de mode (manuel, contrôleur PID, contrôleur BangBang),
|
||||||
|
|
||||||
|
- **←** et **→** permettent de déplacer le mobile,
|
||||||
|
|
||||||
|
- **clic gauche** permet de déplacer le mobile à la souris.
|
||||||
|
|
||||||
|
Les deux dernières commandes ne fonctionnent qu'en mode manuel.
|
||||||
88
cours/inverted-pendulum/cutils.c
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* This file is part of SyncContest.
|
||||||
|
Copyright (C) 2017-2020 Eugene Asarin, Mihaela Sighireanu, Adrien Guatto. */
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
log_verbosity_level level = LOG_INFO;
|
||||||
|
FILE *f = NULL;
|
||||||
|
char *filename = NULL;
|
||||||
|
|
||||||
|
void log_set_verbosity_level(log_verbosity_level l) {
|
||||||
|
level = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_message_v(log_verbosity_level msg_level, const char *fmt, va_list va) {
|
||||||
|
va_list vb;
|
||||||
|
FILE *out = msg_level == LOG_INFO ? stdout : stderr;
|
||||||
|
|
||||||
|
if (msg_level > level)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_copy(vb, va);
|
||||||
|
if (f != NULL) {
|
||||||
|
vfprintf(f, fmt, va);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfprintf(out, fmt, vb);
|
||||||
|
fflush(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_message(log_verbosity_level msg_level, const char *fmt, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
log_message_v(msg_level, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_fatal(const char *fmt, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
log_message_v(LOG_FATAL, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_info(const char *fmt, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
log_message_v(LOG_INFO, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_debug(const char *fmt, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
log_message_v(LOG_DEBUG, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_init(const char *fn) {
|
||||||
|
if (!fn) {
|
||||||
|
log_info("[log] initializing, not saving to file\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = strdup(fn);
|
||||||
|
assert (filename);
|
||||||
|
f = fopen(filename, "w");
|
||||||
|
if (!f)
|
||||||
|
log_fatal("[log] could not open log file %s (fopen)", filename);
|
||||||
|
|
||||||
|
log_info("[log] logging to %s\n", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_shutdown() {
|
||||||
|
if (f) {
|
||||||
|
log_info("[log] shutting down, closing %s\n", filename);
|
||||||
|
fclose(f);
|
||||||
|
free(filename);
|
||||||
|
} else {
|
||||||
|
log_info("[log] shutting down\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
30
cours/inverted-pendulum/cutils.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/* This file is part of SyncContest.
|
||||||
|
Copyright (C) 2017-2020 Eugene Asarin, Mihaela Sighireanu, Adrien Guatto. */
|
||||||
|
|
||||||
|
#ifndef CUTILS_H
|
||||||
|
#define CUTILS_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LOG_FATAL = 0,
|
||||||
|
LOG_INFO = 1,
|
||||||
|
LOG_DEBUG = 2,
|
||||||
|
} log_verbosity_level;
|
||||||
|
|
||||||
|
/* Calling `log_init(fn)` initializes the logging subsystem, asking it to save
|
||||||
|
log messages to the file `fn`. This pointer may be NULL, in which case the
|
||||||
|
messages are not saved. */
|
||||||
|
void log_init(const char *filename);
|
||||||
|
void log_shutdown();
|
||||||
|
|
||||||
|
void log_set_verbosity_level(log_verbosity_level level);
|
||||||
|
|
||||||
|
void log_message_v(log_verbosity_level level, const char *fmt, va_list);
|
||||||
|
void log_message(log_verbosity_level level, const char *fmt, ...);
|
||||||
|
|
||||||
|
void log_fatal(const char *fmt, ...);
|
||||||
|
void log_info(const char *fmt, ...);
|
||||||
|
void log_debug(const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif /* CUTILS_H */
|
||||||
39
cours/inverted-pendulum/debug.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
|
||||||
|
void Debug__dbg_step(char *msg, Debug__dbg_out *o) {
|
||||||
|
log_info("%s\n", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug__dbg_bool_step(char *msg, bool x, Debug__dbg_bool_out *o) {
|
||||||
|
log_info("%s %d\n", msg, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug__dbg_int_step(char *msg, int x, Debug__dbg_int_out *o) {
|
||||||
|
log_info("%s %d\n", msg, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug__dbg_float_step(char *msg, float x, Debug__dbg_float_out *o) {
|
||||||
|
log_info("%s %f\n", msg, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug__d_init_step(Debug__d_init_out *o) {
|
||||||
|
/* Empty by design */
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug__d_string_step(Debug__world _w, char *s, Debug__d_string_out *o) {
|
||||||
|
log_info("%s", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug__d_bool_step(Debug__world _w, bool b, Debug__d_bool_out *o) {
|
||||||
|
log_info("%d", b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug__d_int_step(Debug__world _w, int i, Debug__d_int_out *o) {
|
||||||
|
log_info("%d", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug__d_float_step(Debug__world _w, float f, Debug__d_float_out *o) {
|
||||||
|
log_info("%f", f);
|
||||||
|
}
|
||||||
11
cours/inverted-pendulum/debug.epi
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
external fun dbg(msg : string) returns ()
|
||||||
|
external fun dbg_bool(msg : string; x : bool) returns ()
|
||||||
|
external fun dbg_int(msg : string; x : int) returns ()
|
||||||
|
external fun dbg_float(msg : string; x : float) returns ()
|
||||||
|
|
||||||
|
type world
|
||||||
|
external fun d_init() returns (n : world)
|
||||||
|
external fun d_string(w : world; string) returns (n : world)
|
||||||
|
external fun d_bool(w : world; bool) returns (n : world)
|
||||||
|
external fun d_int(w : world; int) returns (n : world)
|
||||||
|
external fun d_float(w : world; float) returns (n : world)
|
||||||
23
cours/inverted-pendulum/debug.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef DEBUG_H
|
||||||
|
#define DEBUG_H
|
||||||
|
|
||||||
|
#include "stdbool.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "pervasives.h"
|
||||||
|
|
||||||
|
#include "hept_ffi.h"
|
||||||
|
|
||||||
|
DECLARE_HEPT_FUN(Debug, dbg, (char *),);
|
||||||
|
DECLARE_HEPT_FUN(Debug, dbg_bool, (char *, bool),);
|
||||||
|
DECLARE_HEPT_FUN(Debug, dbg_int, (char *, int),);
|
||||||
|
DECLARE_HEPT_FUN(Debug, dbg_float, (char *, float),);
|
||||||
|
|
||||||
|
typedef struct { } Debug__world;
|
||||||
|
|
||||||
|
DECLARE_HEPT_FUN_NULLARY(Debug, d_init, Debug__world n);
|
||||||
|
DECLARE_HEPT_FUN(Debug, d_string, (Debug__world, char *), Debug__world n);
|
||||||
|
DECLARE_HEPT_FUN(Debug, d_bool, (Debug__world, bool), Debug__world n);
|
||||||
|
DECLARE_HEPT_FUN(Debug, d_int, (Debug__world, int), Debug__world n);
|
||||||
|
DECLARE_HEPT_FUN(Debug, d_float, (Debug__world, float), Debug__world n);
|
||||||
|
|
||||||
|
#endif /* DEBUG_H */
|
||||||
4
cours/inverted-pendulum/debug_types.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef DEBUG_TYPES_H
|
||||||
|
#define DEBUG_TYPES_H
|
||||||
|
|
||||||
|
#endif /* DEBUG_TYPES_H */
|
||||||